【问题标题】:Make global shortcut configurable in electron app在电子应用程序中使全局快捷方式可配置
【发布时间】:2020-07-18 07:02:20
【问题描述】:

我将一个 web 应用程序(软件电话)打包到一个电子应用程序中,以便从我可以使用电子程序编码到应用程序中的一些自动化中受益。
我正在使用电子globalShortcut 注册一个全局快捷方式,以将应用程序置于最前面并专注于网络应用程序的搜索栏。

但是,因为我的同事也开始使用该应用程序,所以我想让使用的全局快捷方式可配置。
由于我无法更改网络应用程序本身(它由第三方托管),因此我不知道如何创建用户可以设置快捷方式的菜单。
我知道有 menumenuItem 对象,但我不知道如何要求用户提供一个键或组合键以使用它设置为 globalShortcut。

我该怎么做?

编辑:
澄清我的期望:正如我已经解释的那样,我正在寻找任何可以提供可以配置快捷方式的菜单的解决方案。该菜单可能存在于菜单栏/工具栏中,也可能通过 javascript DOM 操作放置在 Web 文档中 - 也许使用 iframe 作为最后的手段?
任何关于如何在应用程序重新启动时保存设置的想法也值得赞赏。

【问题讨论】:

    标签: javascript electron


    【解决方案1】:

    看到这个问题后,我对你的主题做了一个小的研究。首先想到的是电子是否允许监听关键事件,但据此thread 电子开发人员正在阻止电子成为 键盘记录器。所以我有以下方法来解决这个问题。我不知道这些是否最适合这种情况,但这是我认为可以做到的方式。这基本上是围绕电子商店构建的,它可以用来保存用户定义的组合键。所以应用程序可以从商店中检索定义的组合键(如果没有配置组合,它使用架构上提供的默认组合键)并使用它注册一个globalshortcut。我已经提供了如何实现它的步骤

    1. 使用electron-store 安装和配置默认键值。如下所示

    main.js

    const Store = require('electron-store'); 
    const schema = {
        defaultKeyCombination: {
            type: 'string',
            default: 'CommandOrControl+Y'
        }
    }
    const store = new Store({schema});
    
    1. 导入此defaultKeyCombination,您可以在应用准备就绪时注册global-shortcut。 (当应用程序被销毁时,不要忘记删除全局快捷方式)
    app.on('ready', () => {
        // Register a defaultKeyCombination shortcut listener.
        globalShortcut.register(store.get('defaultKeyCombination'), () => {
        // Do stuff when Y and either Command/Control is pressed.
        })
    })
    
    1. 通过单击菜单(菜单栏>选项>配置)创建并打开另一个浏览器窗口,并让用户使用可用的modifierskey codes在输入框中创建/输入accelerator修饰符(更好在输入框下方的新窗口中显示这些); 例如:用户可以在浏览器中输入MODIFIER+KEY_CODECmdOrCtrl+A

    2. 一旦用户按下submit按钮,将使用IPCRenderer输入的组合键发送到主进程,并通过接收到的值设置存储defaultKeyCombination值。

    3. 触发 IPC 向用户发送回复说“请重新启动应用程序”并在警报或任何情况下显示它。

    渲染进程

    let args = "CmdOrCtrl+A"
    ipcRenderer.send('set::keycombine',args)
        
    ipcRenderer.on('done::keycombine', (event, arg) => {
    // display message to restart the app
    })
    

    主进程

    ipcMain.on('set::keycombine', (event, arg) => {
        console.log(arg) // prints "keycombine"
        //setting the new value
        store.set('defaultKeyCombination', arg)
        // sending reply to renderer work is done
        event.reply('done::keycombine')
    })
    

    应用重新启动后,商店将加载新配置的组合键并使用它注册快捷事件。

    这是我在进行这项小型研究时想到的。在这里,我找到了一个名为 iohook 的关键事件侦听器,但这仅适用于电子 2.XX 。在上面的过程中可能存在错误和流程问题,我只是发布了一些代码来了解一下。

    编辑 1:

    这是我的样品。在我的 index.html 上,我定义了一个按钮来调用 set() 函数。您可以集成输入框,以便输入命令。使用存储设置键后,除非用户更改它,否则它将始终使用此新键值加载。你可以阅读更多关于electron-store from here的信息希望这会给你一个想法:)

    Main.js

    const {app, BrowserWindow, ipcMain } = require('electron')
    const Store = require('electron-store'); 
    const schema = {
      defaultKeyCombination: {
        type: 'string',
        default: 'CommandOrControl+Y'
      }
    }
    const store = new Store({schema});
    
    console.log(store.get("defaultKeyCombination"))
    
    function createWindow () {
      const window = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
          nodeIntegration: true
        }
      })
    
      window.loadFile('./index.html')
      // window.loadURL("https://www.zap.co.il")
      window.webContents.openDevTools()
    }
    ipcMain.on('set::keycombine', (event, arg) => {
      console.log(arg) // prints "keycombine"
      //setting the new value
      store.set('defaultKeyCombination', arg)
      // sending reply to renderer work is done with new key 
      event.reply('done::keycombine', store.get('defaultKeyCombination'))
    })
    
    
    app.wheReady().then(createWindow)
    
    //app.on('ready', createWindow)
    
    app.on('window-all-closed', () => {
      // On macOS it is common for applications and their menu bar
      // to stay active until the user quits explicitly with Cmd + Q
      if (process.platform !== 'darwin') {
        app.quit()
      }
    })
    

    Renderer.js

    const { ipcRenderer } = require('electron')
    function set() {
      console.log("clicked")
      let args = "CmdOrCtrl+A"
      ipcRenderer.send('set::keycombine',args)
    
    }
    ipcRenderer.on('done::keycombine', (event, arg) => {
      console.log("DONEEEEEEEEEE", arg)
    })
    
    

    【讨论】:

    • 我认为您的解决方案正是我所需要的。我只有一个问题:我在哪里加载 Renderer.js?
    • 我已经发现:Renderer.js 的内容需要进入我加载的 html 页面以显示和编辑设置。它工作的人! :) 只有一个问题(我只是将其注释掉):event.reply 方法似乎不存在。遇到异常。
    【解决方案2】:

    假设hotkeySettings.html

    <!DOCTYPE html>
    <html lang="en">
      <head> </head>
      <body>
        <input id="hotkey" onkeyup="keyUp(event)" />
        <button id="save" onclick="saveHotkey()">save</button>
        <script>
          const storage = require("electron-json-storage");
          async function loadHotkey() {
            storage.get("hotkey", function (error, key) {
              document.getElementById("hotkey").value = key;
            });
          }
          async function saveHotkey() {
            const { globalShortcut } = require("electron").remote;
    
            const hotkey = document.getElementById("hotkey").value;
            await storage.set("hotkey", hotkey);
            globalShortcut.register(hotkey, () => {
              console.log(hotkey, "key pressed");
            });
          }
          function keyUp(event) {
            const keyCode = event.keyCode;
            const key = event.key;
            const charCode = event.code;
    
            if ((keyCode >= 16 && keyCode <= 18) || keyCode === 91) return;
    
            const value = [];
            event.ctrlKey ? value.push("Control") : null;
            event.shiftKey ? value.push("Shift") : null;
            event.isAlt ? value.push("Alt") : null;
            value.push(key.toUpperCase());
    
            document.getElementById("hotkey").value = value.join("+");
          }
          loadHotkey();
        </script>
      </body>
    </html>
    

    loadHotkey 功能:将加载上一个注册的热键。热键在appData

    saveHotKey 功能:将根据您的输入注册新的热键并将此值保存到appData,以便保持。

    main.js

    ...
    // Open this browserWindow when you click menuItem to see the registered hotkey
    // And to update the hotkey
    const hotkeySettingsWindow = new BrowserWindow({
        height: 600,
        width: 600,
        webPreferences: {
          nodeIntegration: true
        }
    })
    hotkeySettingsWindow.loadFile('hotkeySettings.html')
    

    【讨论】:

    • 谢谢,您的解决方案也有效,并向我展示了如何打开另一个设置窗口。
    猜你喜欢
    • 2018-05-03
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 2016-05-25
    • 1970-01-01
    相关资源
    最近更新 更多