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

67

我想在按下 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();
    }
  });
})();

5个回答

111

请参考W3C规范中关于键盘事件的部分。提供了几个布尔属性,用于确定是否与你感兴趣的目标键一起按下了修改键(modifier keys),它们是:

  • ctrlKey     -- 按下了“Control”键。
  • shiftKey   -- 按下了“Shift”键。
  • altKey       -- 按下了“Alt”键。
  • metaKey     -- 按下了“Meta”键。

其他重要提示

  1. which属性已过时
  2. 使用keydown事件,因为Chrome不会触发已知键盘快捷方式的keypress事件。
  3. 某些规范中定义的属性,例如key,在Firefox中仅部分支持
  4. 你不需要像Tampermonkey(或Greasemonkey或大多数用户脚本引擎)那样将你的代码包装在匿名函数中。作用域保护已自动提供。

因此,你的代码将变为:

document.addEventListener ("keydown", function (zEvent) {
    if (zEvent.ctrlKey  &&  zEvent.altKey  &&  zEvent.key === "e") {  // case sensitive
        // DO YOUR STUFF HERE
    }
} );
请提供更多上下文或说明,以便我能够更准确地翻译。
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 Pyzer
@Gideon,没错,但在我的经验中,这种用例非常罕见。 - Brock Adams
事件代码是否已更改为charCode或keyCode?我的IDE智能感知列表中列出了charCode或keyCode,但在我键入event时没有列出code。同时列出的只有event.char和event.key - 但是没有列出event.code?只是想知道,但如果我键入even.code,运行时不会出现错误,所以它肯定知道它是什么? - Neal Davis
这个例子在Edge中似乎无法使用cntrl-alt-d或任何类似的3个字符按键?随着Edge即将转向Chrome引擎,也许不需要担心这个问题了? - Neal Davis
2
请注意,此代码在Firefox的OSX版本中会失败,因为按下“alt”+“e”会打印出这个字符:´。在事件触发时,zEvent.key属性将是´而不是e。我通过使用Ctrl + Shift + e来解决了这个问题,但请记住跨平台! - David Vitale
显示剩余7条评论

6
keypress事件在按下一个键时立即触发。如果您按下多个键,则它将为每个按键触发事件,因此它们被视为独立的按键操作。
相反,您可以使用keydownkeyup事件来检测多个按键操作。您可以拥有一个包含3个键和布尔状态的对象。在keydown事件中,如果当前键与对象中的键匹配,则设置该键的状态为true。在keyup事件中,将当前键的状态重置为false。如果最后一次按键时所有3个状态都为true,则触发事件。
请参见使用jQuery实现此逻辑的此示例更新 Brock的答案是一个更好的解决方案,他使用修饰键与单个键代码目标组合,因为检测到ctrlKeyaltKey修饰键的组合,而不是独立地处理它们。如果您想要检测像EF之类的多个键码,请按上述方式使用keydownkeyup来进行跟踪。

这不是一个好的方法来处理像“Control”、“Shift”、“Alt”等修改器键。 - Brock Adams
我无法让Firefox识别带有字母键的Alt Gr组合键,只能使用普通Alt组合键。因此,我使用了这种方法,不过需要修改和修复其中一些不太优秀的逻辑。但是,核心思想当然是有效的。请注意,如果您的按键事件函数是包含await的异步函数,则keyup事件永远不会触发!因此,需要额外的逻辑来解决这个问题。但最终,经过所有这些努力,它已经非常好地工作了。我找到了真正的解决方案,即event.getModifierState('AltGraph'),这才是我从一开始就在寻找的东西。 - Magnus

1
快速提醒。如果您正在检测shift,则需要将您正在检查的任何字母大写化。Shift会将通常小写的字母转换为大写。

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

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

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


1
我正在使用hotkeys-js来抽象功能,但仍然需要让用户选择自己的自定义快捷键(事先不知道)。 然后,我尝试了@Brock Adams的答案,在输入框中获取与hotkeys-js等效格式的按下快捷键。 在我的实验中发现以下事项(在Chrome 92上使用意大利QWERTY键盘布局):
  • 每个AltGr字符都会“丢失”修改器属性。可以用Ctrl+Alt组合替换AltGr。因此,Ctrl+Alt+E(如OP问题中)会输出。同样的情况也适用于Ctr+Alt+5。其他组合也存在同样的问题,比如在意大利键盘上,Ctrl+Alt+ò会输出@
  • 每个Shifted字符在e.key中都会以其Shifted对应项的形式出现,保留了修改器属性,因此Shift+5打印为Shift+%,这是有争议的(考虑到AltGr的行为)。
  • 有些组合无论如何都不会触发事件。我在我的键盘上找到了Ctrl+Shift+9Ctrl+Shift+0Ctrl+Shift+LCtrl+Shift+Alt+D作为示例。这可能是薄膜键盘的限制。

第二点对我来说非常重要,因为我们的客户习惯于使用Ctrl+Shift+[数字]组合。

我通过处理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">

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

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接