Mac Cocoa App中如何实现快捷键输入?

发布于 2024-12-17 05:47:33 字数 203 浏览 1 评论 0原文

我需要在我的 Cocoa 应用程序中制作一个全局热键输入框。

我知道 Shortcut Recorder,但它是一个非常古老的解决方案。它的某些部分是使用 Carbon 实现的,而 Carbon 已被弃用,如果我使用它,我将无法将我的应用程序发布到 Mac App Store。

有没有现成的现代解决方案?有人可以给我自己做这个的方法吗(我不知道从哪里开始)?

I've needed to make a global hot key input box in my Cocoa App.

I know about Shortcut Recorder, but it is a very old solution. It has parts implemented using Carbon, which has been deprecated, and I can't publish my app to the Mac App Store if I use it.

Is there any ready-to-use modern solution? Can anybody give me the way to make this by myself (I don't know where to start from)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

总以为 2024-12-24 05:47:33

有一个名为 MASShortcut 的现代框架,用于在 OS X 10.7+ 中实现全局快捷方式。

There is a modern framework named MASShortcut for implementing Global Shortcuts in OS X 10.7+.

别低头,皇冠会掉 2024-12-24 05:47:33

并非所有 Carbon 都被弃用。你不能再制作纯 Carbon 应用程序,但一些 API 仍然存在,其中一些仍然是执行某些操作的最简单方法。

其中之一是 Carbon Events 热键 API。您当然可以使用 NSEvent 的事件监视器方法筛选所有事件,但这是不必要的工作。 Carbon Events 热键 API 仍然受支持并且简单得多 — 您只需告诉它您想要匹配哪个键以及按下该键时要调用哪个函数。还有像 DDHotKey 这样的 Cocoa 包装器可以让事情变得更加简单。

  • RegisterEventHotKey,相关的 Carbon Events 函数(另请参阅同一文档中的 UnregisterEventHotKey)
  • KeyboardShortcuts,用 Swift 编写,包含 SwiftUI 热键记录器视图 [由项目作者在编辑时添加到此答案] 。

Not all of Carbon is deprecated. You can't make a pure-Carbon application anymore, but some APIs live on and some of them are still the easiest way to do certain things.

One of these is the Carbon Events hotkey API. You certainly can sift through all the events using NSEvent's event-monitor methods, but it's unnecessary work. The Carbon Events hotkey API is still supported and much simpler—you just tell it what key you want to match and what function to call when the key is pressed. And there are Cocoa wrappers such as DDHotKey that make it even simpler.

  • RegisterEventHotKey, the relevant Carbon Events function (see also UnregisterEventHotKey in the same doc)
  • KeyboardShortcuts, written in Swift and includes a SwiftUI hotkey recorder view [added to this answer in edit by the project's author].
缘字诀 2024-12-24 05:47:33

在 Mac OS X 10.6 及更高版本中,您可以使用方法 +addGlobalMonitorForEventsMatchingMask:handler:+addLocalMonitorForEventsMatchingMask:handler:NSEvent 类定义。 监控事件报告以下信息:

本地事件监视器和全局事件监视器是互斥的。例如,全局监视器不会观察其所安装的应用程序的事件流。本地事件监视器仅观察其应用程序的事件流。要监视来自所有应用程序(包括“当前”应用程序)的事件,您必须安装两个事件监视器。

该页面中显示的代码适用于本地事件监视器,但全局事件监视器的代码类似;改变的是调用的 NSEvent 的方法。

_eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:
        (NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask | NSKeyDownMask)
        handler:^(NSEvent *incomingEvent) {
    NSEvent *result = incomingEvent;
    NSWindow *targetWindowForEvent = [incomingEvent window];
    if (targetWindowForEvent != _window) {
        [self _closeAndSendAction:NO];
    } else if ([incomingEvent type] == NSKeyDown) {
        if ([incomingEvent keyCode] == 53) {
            // Escape
            [self _closeAndSendAction:NO];
            result = nil; // Don't process the event
        } else if ([incomingEvent keyCode] == 36) {
            // Enter
            [self _closeAndSendAction:YES];
            result = nil;
        }
    }
    return result;
}];

一旦不再需要监视器,您可以使用以下代码将其删除:

[NSEvent removeMonitor:_eventMonitor];

In Mac OS X 10.6 and higher, you can use the methods +addGlobalMonitorForEventsMatchingMask:handler: and +addLocalMonitorForEventsMatchingMask:handler: defined from the NSEvent class. Monitoring Events reports the following information:

Local and global event monitors are mutually exclusive. For example, the global monitor does not observe the event stream of the application in which it is installed. The local event monitor only observes the event stream of its application. To monitor events from all applications, including the "current" application, you must install both event monitors.

The code shown in that page is for a local event monitor, but the code for a global event monitor is similar; what changes is the invoked NSEvent's method.

_eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:
        (NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask | NSKeyDownMask)
        handler:^(NSEvent *incomingEvent) {
    NSEvent *result = incomingEvent;
    NSWindow *targetWindowForEvent = [incomingEvent window];
    if (targetWindowForEvent != _window) {
        [self _closeAndSendAction:NO];
    } else if ([incomingEvent type] == NSKeyDown) {
        if ([incomingEvent keyCode] == 53) {
            // Escape
            [self _closeAndSendAction:NO];
            result = nil; // Don't process the event
        } else if ([incomingEvent keyCode] == 36) {
            // Enter
            [self _closeAndSendAction:YES];
            result = nil;
        }
    }
    return result;
}];

Once the monitor is not anymore necessary, you remove it using the following code:

[NSEvent removeMonitor:_eventMonitor];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文