從零開始的electron開發-菜單與快捷鍵

菜單與快捷鍵

雖然咱們在平時使用桌面軟件時,大多數狀況下都是用鼠標進行操做,一些軟件提供了菜單與鍵盤快捷鍵進行操做,mac系統上比較常見一些。若是在使用軟件時有對應的快捷鍵操做或者菜單,會讓用戶的使用體驗更加順暢和方便一點。本章主要對註冊快捷鍵的幾種方式進行說明以及菜單的系統差別化處理。vue

Menu菜單

菜單這個東西呢,通常常見於mac系統上,win的話國內比較少見,算是一種約定俗成吧。實際上快捷鍵和菜單方面能夠說是一體的,咱們能夠在菜單上註冊對應的鍵盤按鍵,故mac系統可使用這個方式把快捷鍵一塊兒處理了。
優勢:最簡潔的快捷鍵處理,簡單方便。
缺點:只能在應用程序被聚焦時觸發(焦點在程序上,不僅是顯示),因爲win通常不使用菜單,故只能用於mac上。git

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: '關於',
    accelerator: isMac ? 'Alt+Cmd+I' : 'Alt+Shift+I',
    click: function () {
      info()
    }
  }]
}, {
  label: '設置',
  submenu: [{
    label: '快速重啓',
    accelerator: 'CmdOrCtrl+F5',
    role: 'reload'
  }, {
    label: '退出',
    accelerator: 'CmdOrCtrl+Q',
    role: 'quit'
  }]
}, {
  label: '開發者設置',
  submenu: [{
    label: '切換到開發者模式',
    accelerator: 'CmdOrCtrl+I',
    role: 'toggledevtools'
  }]
}]

function info() {
  dialog.showMessageBox({
    title: '關於',
    type: 'info',
    message: 'vue-cli-electron',
    // detail: `版本信息:\nelectron版本:${process.versions.electron}\n當前系統:${os.type()} ${os.arch()} ${os.release()}\n當前版本:${process.env.VUE_APP_ENV},${process.env.VUE_APP_VERSION}`,
    detail: `版本信息:\nelectron版本:${process.versions.electron}\n當前系統:${os.type()} ${os.arch()} ${os.release()}\n當前版本:${global.envConfig.VUE_APP_ENV},${global.envConfig.VUE_APP_VERSION}`,
    noLink: true,
    buttons: ['肯定']
  })
}

菜單的快捷鍵註冊是用accelerator添加的,固然你也能夠根據系統的不一樣進行差別化處理,role的話是electron內置的行爲,好比copy - 複製paste - 粘貼等等,能夠參考官方文檔 github

在windows下咱們把菜單隱藏掉,mac的話正常顯示:web

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()
  }
}

主進程監聽快捷鍵

globalShortcut

globalShortcut模塊能夠在操做系統中註冊/註銷全局快捷鍵,可是我的不推薦用這種方式來註冊快捷鍵:
優勢:響應級別最高,只要軟件在運行中,不管軟件處於什麼狀態(沒聚焦甚至隱藏),都會響應。
缺點:若是快捷鍵已經被其餘應用程序註冊掉,那麼會註冊失敗。註冊成功後,因爲其響應級別最高,因此會影響其餘軟件快捷鍵的使用,在啓動軟件後,其餘軟件的快捷鍵相同的話其餘軟件的快捷鍵沒法生效。vue-cli

// 主進程,渲染進程可使用remote來註冊:
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')
  }
  // 檢查快捷鍵是否註冊成功
  console.log(globalShortcut.isRegistered('CommandOrControl+X'))
})

app.on('will-quit', () => {
  // 註銷快捷鍵
  globalShortcut.unregister('CommandOrControl+X')

  // 註銷全部快捷鍵
  globalShortcut.unregisterAll()
})

electron-localshortcut

第三方的npm包,api和globalShortcut基本一致,相對而言沒那麼激進,是針對於窗口註冊的,故需傳入窗口進行註冊,當窗口沒聚焦時,不會相應。
優勢:針對於窗口的監聽,響應需處於聚焦狀態,基本上能知足大多數場景。
缺點:須要引入第三方包,頁面有webview,且焦點在webview上時沒法觸發。npm

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', () => {
  console.log('You pressed ctrl & A')
})
// 檢查快捷鍵是否註冊成功
console.log(electronLocalshortcut.isRegistered(win, 'Ctrl+A'))
// 註銷快捷鍵
electronLocalshortcut.unregister(win, 'Ctrl+A')
electronLocalshortcut.unregisterAll(win)

渲染進程監聽快捷鍵

本身頁面監聽

實際上就是網頁keyup的監聽,能夠用通訊把鍵盤按鍵的信息傳送到主進程。
固然你也能夠在主進程中使用before-input-event,渲染進程中調度頁面中的keydown和keyup事件以前,會發出before-input-event事件,能夠在主進程捕獲按鍵信息。
優勢:針對於頁面的監聽,經常使用於某個頁面的特殊按鍵監聽。
缺點:頁面有iframe或webview,且焦點在iframe或webview上時,沒法觸發(iframe能夠觸發before-input-event)。windows

渲染進程:
window.addEventListener('keyup', handleKeyPress, true)
function handleKeyPress(event) {
  $message.success(`keyup 監聽${event.key}`)
  console.log(`You pressed ${event.key}`)
}
window.removeEventListener('keyup', handleKeyPress, true)


主進程:
win.webContents.on('before-input-event', (event, input) => {
  if (input.control && input.key.toLowerCase() === 'i') {
    console.log('Pressed Control+I')
    event.preventDefault()
  }
})

組合按鍵:固然通常來講快捷鍵都是組合按鍵的,咱們能夠藉助第三方按鍵庫來處理。api

npm i mousetrap

渲染進程:

Mousetrap.bind('ctrl+k', function() { 
  $message.success(`Mousetrap ctrl+k`)
})

Mousetrap.unbind('ctrl+k')

webview或iframe嵌入網頁監聽

若是咱們的頁面中有webview或iframe,且焦點在webview或iframe上時,會致使咱們的快捷鍵失效。app

  1. Menu菜單和globalShortcut不會失效。
  2. electron-localshortcut:webview無效,iframe有效
  3. keyup:webview無效,iframe無效,before-input-event:iframe有效。

這樣看下來在應用webview的時候比較難處理,只有Menu菜單和globalShortcut對其生效,那麼還有其餘方式嗎?
咱們能夠經過向webview注入preload.js來進行鍵盤按鍵的監聽,而後將鍵盤信息回傳給咱們的渲染進程dom

vue.config.js中electronBuilder修改成:
preload: { preload: 'src/renderer/preload/ipcRenderer.js', webviewPreload: 'src/renderer/preload/webview.js' }

webviewPreload是咱們向webview注入的js,固然你得新建對應文件,注意一下咱們創建的文件是webview.js,編譯後爲webviewPreload.js,故咱們注入的爲webviewPreload.js。
注:webview 啓動及Node integration啓用須在主進程窗口webPreferences進行配置。
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
    })
}

渲染進程:
<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('在此監聽事件中接收webview嵌套頁面所響應的事件', event)
  $message.success(`webview:${event.args[0].data}`)
}

簡單梳理一下,咱們把webviewPreload.js注入webview,經過這個js進行鍵盤的keyup監聽,而後經過sendToHost把信息回傳給渲染進程,渲染進程中獲取回傳的信息。
渲染進程是看不到咱們注入js以及webview的打印,可使用webview.openDevTools(),打開webview的控制檯查看。
本例子就沒說明組合鍵了,想用組合鍵請自行注入mousetrap進行操做。

本系列更新只有利用週末和下班時間整理,比較多的內容的話更新會比較慢,但願能對你有所幫助,請多多star或點贊收藏支持一下

本文地址:連接
本文github地址:連接

相關文章
相關標籤/搜索