首頁 > 軟體

一文詳解Electron 快捷鍵使用技巧及範例

2023-03-29 06:02:02

引言

Electron 中可以設定全域性快捷鍵和應用快捷鍵,全域性快捷鍵就是註冊到系統裡面的,全域性生效的快捷鍵;而應用快捷鍵是指當用戶使用該應用程式時才生效的快捷鍵,它們的實現邏輯是不一樣的,接下來就為大家詳細介紹。

全域性快捷鍵

Electron 提供的 globalShortcut 模組可以用於註冊或取消全域性快捷鍵。使用方法為:

globalShortcut.register(accelerator, callback) // 註冊單個快捷鍵
globalShortcut.registerAll(accelerators, callback) // 批次註冊快捷鍵

其中引數的含義

  • accelerator 必須是有效的快捷鍵字串
  • callback 是當註冊成功後,使用者按下快捷鍵之後執行的回撥函數

有效的快捷鍵由多個功能鍵和一個鍵碼中間用加號(+)組合而成,例如:

  • Ctrl + T
  • CmdOrCtrl + Shift + Z

常用的功能鍵和鍵碼如下,設定快捷鍵的時候可以從功能鍵裡面選擇多個,從鍵碼裡面選擇一個:

功能鍵Cmd、Ctrl、CmdOrCtrl、Alt、Shift、Meta
鍵碼0~9、A~Z、F1~F24、Space、Tab、Backspace、Delete、Enter、Esc 等

不過有兩點需要注意:

  • 如果快捷鍵字串無效會直接報錯,因此建議在使用此方法的時候加 try catch 語句,防止程式崩潰。
  • 該方法並不確保一定可以成功註冊全域性快捷鍵,因為有可能被電腦上的其他應用提前佔用了,此時並不會報錯,而是返回 false,因此我們可以通過返回值來判斷快捷鍵是否註冊成功。

範例程式碼

const { app, globalShortcut } = require('electron')
app.whenReady().then(() => {
  registerGlobalShortcut('Cmd+Alt+K')
})
function registerGlobalShortcut(shortcut) {
  if (!shortcut) return false
  let flag = false
  try {
    flag = globalShortcut.isRegistered(shortcut)
    if (flag) return true
    flag = globalShortcut.register(shortcut, () => {
      console.log('toggle shortcut')
    })
  } catch (e) {
    console.error(e)
  }
  return flag
}

注意 globalShortcut 的 API 需要在 app ready 之後才能呼叫,否則會直接退出:

Electron.app/Contents/MacOS/Electron exited with signal SIGTRAP

程式碼中有一行判斷快捷鍵是否被註冊的函數:

globalShortcut.isRegistered(accelerator)

該方法只能檢測當前應用是否註冊過這個快捷鍵,並不能檢測到快鍵鍵是否被其他應用佔用,即使被其他應用註冊過了,該方法依然會返回 false,只有當前應用成功註冊了這個全域性快捷鍵,才會返回 true。

可以使用一些開源的工具來檢測快捷鍵是否被佔用,例如 Windows 系統上的 OpenArk ,Mac 上的 Shortcut Detective。

取消快捷鍵註冊的方法:

globalShortcut.unregister(accelerator) // 取消註冊指定快捷鍵
globalShortcut.unregisterAll() // 取消註冊所有快捷鍵

應用快捷鍵

與全域性快捷鍵不同,視窗快捷鍵是當視窗處於啟用狀態時,按下按鍵之後觸發的行為。例如我們開啟 word 或 photoshop 軟體,可以用 ctrl + z 復原上一步操作,用 ctrl + c 複製等。下圖是 vscode 的選單和對應的快捷鍵:

在 Electron 應用中,也提供了對應的功能,在建立選單(Menu)的時候,可以指定視窗快鍵鍵,範例程式碼如下:

const { app, BrowserWindow, Menu } = require('electron')
app.whenReady().then(() => {
  createWindow()
})
let win
function createWindow() {
  win = new BrowserWindow({
    width: 600,
    height: 400,
  })
  const tpl = [
    {
      label: '自定義選單',
      submenu: [
        {
          label: '開啟控制檯',
          role: 'toggleDevTools',
        },
        {
          label: '繫結快捷鍵',
          accelerator: 'Ctrl+Shift+K',
          click: () => {
            console.log('menu shortcut pressed')
          },
        },
      ],
    },
  ]
  if (process.platform === 'darwin') {
    tpl.unshift({ label: '' })
  }
  const menu = Menu.buildFromTemplate(tpl)
  Menu.setApplicationMenu(menu)
}

最終的效果是:系統選單項繫結了快捷鍵,如下圖所示:

當應用處於啟用狀態時,如果使用者觸發了 Ctrl+Shift+K 快捷鍵,會執行回撥函數,列印相關資訊:

再次強調,一定要在開啟當前應用後觸發快捷鍵才行,如果在別的應用中觸發這個快捷鍵是沒有效果的,正如官方檔案中說的:

其實每個桌面軟體都有註冊了自己的「應用快捷鍵」,例如 ctrl+cctrl+v 這種通用的都屬於應用快捷鍵。在 Windows 系統上,還可以為每個視窗設定不同的快捷鍵。例如,你可以在一個視窗中設定 Ctrl+O 快捷鍵開啟檔案,在另一個視窗中設定 Ctrl+S 快捷鍵儲存檔案。

在開發的時候,可能會想做這樣的事情:註冊一個不在選單中顯示的應用快捷鍵便於偵錯(例如開啟控制檯或者上傳紀錄檔等),那有沒有辦法能夠做到不註冊選單,只註冊快捷鍵呢?有兩種方案:

方法1:把選單給隱藏掉

MenuItem 有個 visibile 屬性用於設定選單項是否展示,預設是 true,設定成 false 即可,不過 2015 年的一個 issue 說,在 macOS 系統上如果隱藏選單,快捷鍵就失效了,但是經過筆者實際測試,發現並沒有失效(macOS 12.6.3 系統),所以這種方法是可行的,而且非常簡單,只需要修改一行程式碼即可:

const tpl = [
  {
    label: '自定義選單',
    submenu: [
      {
        label: '開啟控制檯',
        role: 'toggleDevTools',
      },
      {
        label: '繫結快捷鍵',
        accelerator: 'Ctrl+Shift+K',
        visible: false, // 設定選單項為隱藏選單
        click: () => {
          console.log('menu shortcut pressed')
        },
      },
    ],
  },
]

方法2:利用 webContents.on('before-input-event') 事件

具體的內容可參見這個 issue,利用的是 webContentsbefore-input-event 事件。範例程式碼如下:

app.on('web-contents-created', function (event, wc) {
  wc.on('before-input-event', function (event, input) {
    if (input.key === 'x' && input.ctrl && !input.alt && !input.meta && !input.shift) {
      // Do something for Ctrl-X
      event.preventDefault()
    }
  })
})

社群有開發者基於此封裝了 electron-localshortcut 包,可以非常方便的給不同的視窗(BrowserWindow)繫結快捷鍵,使用起來更簡單:

const { app, BrowserWindow } = require('electron')
const localShortcut = require('electron-localshortcut')
app.whenReady().then(() => createWindow())
let win1, win2
function createWindow() {
  win1 = new BrowserWindow({ width: 600, height: 400 })
  win1.loadURL('https://www.baidu.com')
  localShortcut.register(win1, 'Ctrl+Shift+K', () => {
    console.log('register local shortcut for win1')
  })
  win2 = new BrowserWindow({ width: 600, height: 400 })
  win2.loadURL('https://www.taobao.com')
  localShortcut.register(win2, 'Ctrl+Shift+T', () => {
    console.log('register local shortcut for win2')
  })
}

以上就是Electron 中的快捷鍵的詳細內容,更多關於Electron 快捷鍵的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com