While most of our desktop software is operated with the mouse, some software provides menus and keyboard shortcuts, which are more common on MAC systems. If there is a corresponding shortcut key operation or menu when using the software, it will make the user’s use experience more smooth and convenient. This chapter mainly describes several ways of registering shortcut keys and the differentiated treatment of the menu system.

The Menu Menu

Menu this thing, generally seen in MAC system, win is relatively rare in China, it is a convention. In fact, the shortcut and menu aspects can be said to be one, we can register the corresponding keyboard key on the menu, so the MAC system can use this way to handle the shortcut together. Advantages: the most concise shortcut key processing, simple and convenient. Cons: Can only be triggered when the application is focused (focus on the application, not just the display). Since Win does not use menus in general, it can only be used on the MAC.

import { app, dialog, Menu } from 'electron' import config from './index' import global from './global' const os = require('os') const isMac = Process. platform === 'Darwin' const menuConfig = [{label: app.name, submenu: [{label: 'about ', accelerator: 'Alt+Cmd+I' : 'Alt+Shift+I', click: function () {info()}}]}, {label: 'set ', submenu: [{label: 'quick restart ', accelerator: 'CmdOrCtrl+F5', role: 'reload'}, {label:' exit ', accelerator: 'CmdOrCtrl+Q', role: 'quit'}]}, {label: 'developer Settings ', submenu: [{label:' switch to developer mode ', Accelerator: 'CmdOrCtrl+I', role: Function info() {dialog.showMessageBox({title: 'about ', type: 'info', message: 'vue-cli-electron', // detail: ` version information: \ nelectron version: ${process. Versions. Electron} \ n current system: ${OS. The type ()} ${OS. The arch ()} ${OS. Release ()} \ n the current version: The ${process. The env. VUE_APP_ENV}, ${process. The env. VUE_APP_VERSION} `, the detail: ` version information: \ nelectron version: ${process. Versions. Electron} \ n current system: ${OS. The type ()} ${OS. The arch ()} ${OS. Release ()} \ n the current version: ${globally.envconfig.vue_app_env}, ${globally.envconfig.vue_app_version} ', noLink: true, buttons: [' ok ']})}Copy the code

The menu shortcut registration is added by accelerator. Of course, you can also make different processing according to different systems. Role is the built-in behavior of electron, such as copy-copy, paste, etc., please refer to the official documents

On Windows we hide the menu, and on MAC we display it normally:

function setMenu(win) {
  let menu
  if (config.devToolsShow) {
    menu = Menu.buildFromTemplate(menuConfig)
    Menu.setApplicationMenu(menu)
    win.webContents.openDevTools({ mode: 'detach' })
  } else {
    if (isMac) {
      menu = Menu.buildFromTemplate(menuConfig)
      Menu.setApplicationMenu(menu)
    } else {
      Menu.setApplicationMenu(null)
    }
    win.webContents.openDevTools({ mode: 'detach' })
    // win.webContents.closeDevTools()
  }
}
Copy the code

The main process listens for shortcuts

globalShortcut

The globalShortcut module can register/unregister global shortcuts in the operating system, but it is not recommended to register shortcuts in this way. Advantages: Highest response level, responds whenever the software is running, regardless of what state it is in (unfocused or even hidden). Disadvantages: If the shortcut is already registered by another application, the registration will fail. After successful registration, it has the highest response level, so it will affect the use of shortcut keys of other software. After starting the software, if the shortcut keys of other software are the same, the shortcut keys of other software cannot take effect.

// The main process, rendering process can use remote to register:  const { app, globalShortcut } = require('electron') app.whenReady().then(() => { const ret = globalShortcut.register('CommandOrControl+X', () => { console.log('CommandOrControl+X is pressed') }) if (! Ret) {console.log('registration failed')} // Check whether the shortcut key is successfully registered console.log(globalShortcut.isRegistered('CommandOrControl+X')) }) app.on('will-quit', () = > {/ / logout shortcuts globalShortcut unregister (' CommandOrControl + X) / / cancellation of all shortcuts globalShortcut unregisterAll ()})Copy the code

electron-localshortcut

The third party NPM package, API is similar to globalShortcut and is relatively less aggressive. It is targeted at window registrations, so the incoming window is registered. If the window is not focused, it does not respond. Advantages: For window listening, the response needs to be in the focused state, which can be used in most scenarios. Disadvantages: Third-party packages need to be introduced, the page has a WebView, and the focus on the WebView cannot be triggered.

npm install --save electron-localshortcut const electronLocalshortcut = require('electron-localshortcut') const win = new BrowserWindow() win.loadUrl('https://github.com') win.show() electronLocalshortcut.register(win, 'Ctrl+A', () = > {the console. The log (' You pressed CTRL & A ')}) / / check if the shortcut to register the console log (electronLocalshortcut. IsRegistered (win, 'Ctrl + A) / / logout shortcuts electronLocalshortcut unregister (win,' Ctrl + A) electronLocalshortcut. UnregisterAll (win)Copy the code

The rendering process listens for shortcuts

Own page listening

In fact, it is the listener of the keyup of the web page, which can use the communication to transmit the information of the keyboard keys to the main process. Of course, you can also use before-input-event in the main process. Before-input-event is emitted in the rendering process before the keyDown and KeyUp events are scheduled on the page. The key information is captured in the main process. Advantage: for the page listening, often used for a particular page key listening. Disadvantages: If the page has an iframe or webView and the focus is on the iframe or WebView, it cannot be triggered (iframe can trigger before-input-event).

Rendering process:  window.addEventListener('keyup', handleKeyPress, Function handleKeyPress(event) {$message. Success (' keyup listener ${event.key} ') console.log(' You pressed ${event.key} ') } window. RemoveEventListener (' keyup handleKeyPress, true) main process:  win.webContents.on('before-input-event', (event, input) => { if (input.control && input.key.toLowerCase() === 'i') { console.log('Pressed Control+I') event.preventDefault() } })Copy the code

Combination of keys: of course, generally speaking, shortcut keys are combination of keys, we can use a third-party key library to deal with.

NPM I mouseTrap render process  Mousetrap.bind('ctrl+k', function() { $message.success(`Mousetrap ctrl+k`) }) Mousetrap.unbind('ctrl+k')Copy the code

Webview or iframe embedded web page listener

If we have a WebView or iframe in our page, and the focus is on the WebView or iframe, it will cause our shortcut keys to fail.

  1. The Menu Menu and globalShortcut do not fail.
  2. Electron localshortcut: Invalid webView, valid iframe
  3. Keyup: invalid webView, invalid iframe, before-input-event: valid iframe.

This is going to be a bit hard to handle when applying webView, only the Menu Menu and globalShortcut work for it, so what else? We can listen for keyboard keys by injecting preload.js into the WebView and then send the keyboard information back to our rendering process

In vue. Config. Js electronBuilder is amended as: preload: {preload: 'the renderer/SRC/preload/ipcRenderer. Js', webviewPreload: 'SRC/renderer/preload/webview. Js'} webviewPreload injections into the webview is our js, of course, you have to build corresponding files, notice how we build file is webview. Js. It will compile to WebViewPreload.js, so we will inject webViewPreload.js. Note: WebView startup and Node Integration enablement must be configured in webPreferences in the main process window. Webview. Js:  const { ipcRenderer } = require('electron') window.addEventListener('keyup', handleKeyPress, true) function handleKeyPress(event) { console.log(event.key) ipcRenderer.sendToHost('ipc-message', { data: Event.key})} Render process:  <webview ref="webviewRef" class="webview" src="https://www.baidu.com" :preload="state.preload" ></webview> const { remote } = require('electron') const path = require('path') const webview = webviewRef.value state.preload = path.resolve(remote.app.getAppPath(), './webviewPreload.js') webview.addEventListener('ipc-message', webMessage) webview.addEventListener('dom-ready', () => {webView.openDevTools ()}) function webMessage(event) {console.log(' receive events in this listener that respond to webView nested pages ', $message. Success (' webView: ${event.args[0].data} ')}Copy the code

To summarize briefly, we inject WebViewPreload. js into WebView, use this JS to perform keyup listening of the keyboard, and then send the information back to the rendering process through sendToHost, and the rendering process gets the returned information. The rendering process does not see the printout of our injected JS and WebView. You can use webView.OpenDevTools () to open the WebView console. This example does not cover key combinations, so you need to inject mouseTrap yourself.

This series of updates can only be arranged on weekends and after work, the update of more content will be slow, hope to help you, please more star or like collection support

This article address: xuxin123.com/electron/me… This post is on Github