检测组合按键(Control、Alt、Shift)?

Detecting combination keypresses (Control, Alt, Shift)?

我正在尝试制作脚本 运行 当 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();
    }
  });
})();

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

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

参见 this example 使用 jQuery 实现此逻辑。

更新 Brock 的回答是将修饰键与单个键代码目标结合使用的更好解决方案,因为 ctrlKeyaltKey 修饰符是组合检测的,而不是独立处理的。例如,如果您想一起检测多个键码,例如 EF,您需要使用 keydownkeyup 来跟踪它们.

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

  • ctrlKey -- "Control" 键也被按下。
  • 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>

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

在那种情况下你可以使用

event.getModifierState('AltGraph')

有关详细信息,请参阅 https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState

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

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

  • 每个 AltGr 角色都“失去”修饰符属性。 AltGr 可以用 Ctrl+Alt 组合代替。所以 Ctrl+Alt+E(如 OP 问题)给出 Ctr+Alt+5 也是如此。其他组合也有同样的问题,比如 Ctrl+Alt+ò 在意大利语键盘上给出 @
  • 每个移位字符都在 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: <input type="text" value="" id="keyPrssInp">

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

快速说明。如果您正在检测班次,那么您需要将您正在检查的任何字母大写。 Shift 将通常为小写的字母大写。

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

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

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