【问题标题】:Detecting combination keypresses (Control, Alt, Shift)?检测组合按键(Control、Alt、Shift)?
【发布时间】:2025-12-30 04:15:12
【问题描述】:

我正在尝试在按下 Ctrl + Alt + e 时运行脚本。
Tampermonkey 如何同时使用 ctrl、alt 和 e 键触发?

我尝试过ctrlKeyaltKey。我没有找到任何有效的方法。
如何编辑下面的脚本以在 Ctrl + Alt + e 上触发,而不仅仅是 e

(function() {
  document.addEventListener("keypress", function(e) {
    if (e.which == 101) {
      var xhttp = new XMLHttpRequest;
      xhttp.onreadystatechange = function() {
        4 == xhttp.readyState && 200 == xhttp.status && eval(xhttp.responseText)
      }, xhttp.open("GET", "http://127.0.0.1:2337/inject", !0), xhttp.send();
    }
  });
})();

【问题讨论】:

    标签: javascript greasemonkey tampermonkey ctrl modifier-key


    【解决方案1】:

    请参阅the W3C spec for keyboard events。提供了几个布尔属性来确定 修饰键 是否与您感兴趣的任何目标键一起按下。它们是:

    • ctrlKey     -- 还按下了“控制”键。
    • shiftKey - 还按下了“Shift”键。
    • altKey      -- 也按下了“Alt”键。
    • metaKey     -- “Meta”键也被按下了。

    其他重要说明

    1. The which property is deprecated
    2. 使用keydown 因为Chrome does not fire the keypress event for known keyboard shortcuts.
    3. 一些规范的属性,例如key,是only partly functional in Firefox
    4. 您不需要像 Tampermonkey(或 Greasemonkey 或大多数用户脚本引擎)那样将代码包装在匿名函数中。自动提供范围保护。

    因此,您的代码将变为:

    document.addEventListener ("keydown", function (zEvent) {
        if (zEvent.ctrlKey  &&  zEvent.altKey  &&  zEvent.key === "e") {  // case sensitive
            // DO YOUR STUFF HERE
        }
    } );
    

    运行这个方便的演示(现在更新 key 已完全支持)

    var targArea = document.getElementById ("keyPrssInp");
    targArea.addEventListener ('keydown',  reportKeyEvent);
    
    function reportKeyEvent (zEvent) {
        var keyStr = ["Control", "Shift", "Alt", "Meta"].includes(zEvent.key) ? "" : zEvent.key + " ";
        var reportStr   =
            "The " +
            ( zEvent.ctrlKey  ? "Control " : "" ) +
            ( zEvent.shiftKey ? "Shift "   : "" ) +
            ( zEvent.altKey   ? "Alt "     : "" ) +
            ( zEvent.metaKey  ? "Meta "    : "" ) +
            keyStr + "key was pressed."
        ;
        $("#statusReport").text (reportStr);
    
        //--- Was a Ctrl-Alt-E combo pressed?
        if (zEvent.ctrlKey  &&  zEvent.altKey  &&  zEvent.key === "e") {  // case sensitive
            this.hitCnt = ( this.hitCnt || 0 ) + 1;
            $("#statusReport").after (
                '<p>Bingo! cnt: ' + this.hitCnt + '</p>'
            );
        }
        zEvent.stopPropagation ();
        zEvent.preventDefault ()
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
    <p><label>Press keys in here:<input type="text" value="" id="keyPrssInp"></label>
    </p>
    <p id="statusReport"></p>

    【讨论】:

    • 非常有见地。对于使用修饰符和仅一个目标键代码的情况,这似乎是一种更简单的解决方案。对于多个键,您必须跟踪使用 keydownkeyup 选择的内容。
    • @Gideon,是的,但根据我的经验,这种用例很少见。
    • zEvent.code 在 Chrome 中不存在,在我意识到这一点之前,我一直没有定义,你应该改用 zEvent.key
    • @CarlosMafla,它仍然可以正常工作。在 Chrome 65.0.3325.181 和其他几个浏览器中重新验证。您使用的是什么浏览器版本和操作系统?
    • 仅供参考,这在 OSX 上的 Firefox 中失败,因为按“alt”+“e”会打印出这个字符:´。在事件触发时,zEvent.key 属性将是 ´ 而不是 e。我通过使用 Ctrl + Shift + e 解决了这个问题,但请记住跨平台!
    【解决方案2】:

    一旦按下一个键,keypress 事件就会被触发。如果您按下多个键,每次按下都会触发事件,因此它们被视为独立的按键。

    相反,您可以同时使用keydownkeyup 事件来检测多个按键。您可以拥有一个包含 3 个键和一个布尔状态的对象。在keydown 事件中,如果当前键与对象中的键匹配,则将该键的状态设置为true。在keyup 事件中,您将当前密钥的状态重置为false。如果在最后一次按键时所有 3 个状态都是 true,则触发事件。

    请参阅this example,它使用 jQuery 实现此逻辑。

    更新 Brock 的答案是您将修饰键与单个键代码目标结合使用的更好解决方案,因为 ctrlKeyaltKey 修饰符是组合检测的,而不是单独处理的。例如,如果您想同时检测多个关键代码,例如EF,则需要按照上述方法使用keydownkeyup 跟踪它们。

    【讨论】:

    • 这对于 修饰符 键(如“Control”、“Shift”、“Alt”等)来说不是一个好方法。
    • 我无法让 Firefox 识别 Alt Gr 与字母键的组合,只能识别与普通 Alt 的组合。所以我使用了这种方法,尽管我不得不修改它并修复它。它有一些不太理想的逻辑。但它的核心思想当然有效。请注意,如果您的键事件函数是包含等待的异步函数,则 keyup 事件永远不会触发!所以这个问题需要额外的逻辑。但最后,毕竟这一切都很好。我找到了真正的解决方案, event.getModifierState('AltGraph') 这是我从一开始就在寻找的。​​span>
    【解决方案3】:

    如果您像我一样来到这里了解如何检测“Alt Gr”键与字母键的组合,那么像 event.altKey 这样的属性不能用于此,因为没有event.AltGrKey 属性。

    在这种情况下你可以使用

    event.getModifierState('AltGraph')
    

    更多详情见https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState

    【讨论】:

      【解决方案4】:

      我正在使用hotkeys-js 来抽象功能,但仍然必须让用户选择自己的自定义快捷方式(事先不知道)。 然后我尝试了@Brock Adams 的答案,以获得输入框中按下的快捷键的等效格式的 hotkeys-js。

      我在试验时发现的东西(在 Chrome 92 上的意大利 QWERTY 键盘布局上):

      • 每个 AltGr 字符都会“丢失”修饰符属性。 AltGr 可以替换为 Ctrl+Alt 组合。所以Ctrl+Alt+E(如在OP问题中)给出Ctr+Alt+5 也是如此。其他组合也有同样的问题,比如Ctrl+Alt+ò,它在意大利语键盘上给出@
      • 每个 Shifted 字符都在 e.key 中找到,因为它是已移动的对应物,保留了修饰符属性,因此 Shift+5 打印为 Shift+%,这是有问题的(考虑到 AltGr 行为)。
      • 某些组合无论如何都不会触发事件。我在我的键盘上找到了 Ctrl+Shift+9Ctrl+Shift+0Ctrl+Shift+LCtrl+Shift+Alt+D 作为示例。这可能是薄膜键盘的限制。

      第二点对我来说很关键,因为我们的客户习惯于 Ctrl+Shift+[Number] 组合。

      我通过处理 keyCode 介于 48 和 58 之间的特殊情况并手动转换为相应的数字来解决它。虽然它仍然不能解决任何其他用 Shift 修改的特殊字符,但是鉴于它们非常依赖于键盘布局,我看不到任何通用的解决方案。不过,我从不知道有人想要使用特殊字符的快捷方式。

      const input = document.getElementById("keyPrssInp");
      input.addEventListener('keydown', e => {
        input.value = `${e.ctrlKey ? 'ctrl+' : ''}${e.shiftKey ? 'shift+' : ''}${e.altKey ? 'alt+' : ''}${e.metaKey ? 'meta+' : ''}${["Control", "Shift", "Alt", "Meta"].includes(e.key) ? "" : (e.keyCode < 58 && e.keyCode > 47 ? e.keyCode - 48 : e.key)}`
        e.preventDefault();
      });
      Press keys in here: &lt;input type="text" value="" id="keyPrssInp"&gt;

      如果不要求可读性和/或您事先知道要检查的组合键,则使用event.keyCode 而不是event.key 可能更安全。

      【讨论】:

        【解决方案5】:

        快速笔记。如果您检测到班次,那么您需要将要检查的任何字母大写。 Shift 将通常的小写字母大写。

        if (zEvent.shiftKey &amp;&amp; zEvent.key === "T")

        if (zEvent.ctrlKey &amp;&amp; zEvent.key === "t")

        if (zEvent.altKey &amp;&amp; zEvent.key === "t")

        【讨论】:

          最近更新 更多