拦截/禁用键盘快捷键(例如CMD+q)

5
有没有办法在Objective-C的Mac应用程序中截取并更改/忽略全局给定的快捷方式?
例如,BetterTouchTool可以覆盖提供的任何快捷方式。
我想做的是在特定应用程序打开时防止“退出”快捷键(即CMD+q),因为在这种情况下,该快捷键会意外按下并不希望关闭应用程序。
简而言之,我能否监听任何全局键事件,然后在将其传递到目标应用程序之前更改该事件?

作为完全非编程解决方案,您可以在“系统偏好设置>键盘>键盘快捷键>应用程序快捷键>[特定应用程序]”中更改该应用程序的关键等效项(我认为这在Mavericks中已经移动了,但它仍然应该在某个地方的系统偏好设置中)。例如,我将浏览器的退出菜单项设置为^⌥⌘Q。从编码角度来看,您正在寻找CGEventTaps。 - jscs
这不起作用,因为应用程序是使用bash脚本启动的,而不是*.app应用程序。我会研究CGEventTaps,你有任何即时资源吗? - ehftwelve
明白了。Quartz事件服务参考是官方文档。 - jscs
这适用于macOS/pynput: https://dev59.com/E734oIgBc1ULPQZFxgV6 - Bernd
1个回答

5
这里是设置事件监听器的方法。
CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap,
                                kCGHeadInsertEventTap,
                                kCGEventTapOptionDefault,
                                CGEventMaskBit(kCGEventKeyDown),
                                &KeyDownCallback,
                                NULL);

CFRunLoopSourceRef runLoopSource = CFMachPortCreateRunLoopSource(NULL, eventTap, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
CFRelease(runLoopSource);
CGEventTapEnable(eventTap, true);

接下来是“回调函数”:

static CGEventRef KeyDownCallback(CGEventTapProxy proxy,
                              CGEventType type,
                              CGEventRef event,
                              void *refcon)
{
    /* Do something with the event */
    NSEvent *e = [NSEvent eventWithCGEvent:event];
    return event;
}

在已解析的NSEvent上,有modifierFlags和keyCode属性。keyCode是按下的键的代码,而modifierFlags则是不同的修饰符(Shift、Alt/Option、Command等)。
在KeyDownCallback方法中,简单地返回NULL即可停止事件传播。
注意:事件挂钩超时似乎存在问题,为解决此问题,您可以“重置”事件挂钩。
在KeyDownCallback方法中,检查CGEventType类型是否为kCGEventTapDisabledByTimeout,代码如下:
if (type == kCGEventTapDisabledByTimeout)
{
    /* Reset eventTap */
    return NULL;
}

当出现Reset eventTap时,重新执行上面的事件监听器设置。


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