Objective c 在Mac OS X上处理全局热键的事件

Objective c 在Mac OS X上处理全局热键的事件,objective-c,macos,cocoa,event-handling,Objective C,Macos,Cocoa,Event Handling,我想要什么: 我有一个程序在运行。当程序在任务栏中且不对焦时,我想设置几个全局快捷方式,以便向程序发送消息。“发送消息”是什么意思?在我的程序中,我只想访问某个标志,该标志将指示指定密钥对的状态(启动或未启动)。我会在循环中投票,然后在那里做出决定 我的发现: 我不明白的地方: 从上面的链接来看,在注册热键时,我似乎必须传递一个处理程序。按下热键时,操作系统调用处理程序。是这样吗?我不明白的是,如果我的程序正在运行,系统会如何调用我程序中的处理程序。我想你的主要问题是,在objective

我想要什么:

我有一个程序在运行。当程序在任务栏中且不对焦时,我想设置几个全局快捷方式,以便向程序发送消息。“发送消息”是什么意思?在我的程序中,我只想访问某个标志,该标志将指示指定密钥对的状态(启动或未启动)。我会在循环中投票,然后在那里做出决定

我的发现:

我不明白的地方:


从上面的链接来看,在注册热键时,我似乎必须传递一个处理程序。按下热键时,操作系统调用处理程序。是这样吗?我不明白的是,如果我的程序正在运行,系统会如何调用我程序中的处理程序。

我想你的主要问题是,在objective C和Cocoa成为标准之前,你不明白Mac编程是如何完成的。在此之前,大多数编程都是用C(或C++)编写的。这个名字用于一个库,在Mac OS(经典版)和Mac OS X之间的过渡期间,该库应该是一套更现代的API的“碳”拷贝

您必须了解的另一件事是,上面示例中给出的热键注册必须与Carbon事件处理程序的注册配对,当您点击该热键组合时,将调用该事件处理程序

也就是说,我认为您应该阅读这篇关于碳活动管理器的遗留文档:

还要特别注意碳事件应该如何记录。我特别使用:

OSStatus  InstallEventHandler(EventTargetRef target,
                              EventHandlerUPP handlerProc,
                              UInt32 numTypes,
                              const EventTypeSpec* typeList,
                              void* userData,
                              EventHandlerRef* handlerRef);
我使用它的方式是,我制作了一个objective C包装器,在其中我基本上执行以下操作:

这是类的一部分,我们称之为MyOwnEventHandler:

- (EventHandlerRef)handlerRef {

    if ( handlerRef == nil ) {
       NSAssert( InstallEventHandler(GetApplicationEventTarget(),
                                     &EventHandler,
                                      0,
                                      nil,
                                      self,
                                      &handlerRef ) == noErr, @"handlerRef" );
    }

    return handlerRef;
  }

  // this is a Carbon callback that the OS invokes when your app gets
  // a hotkey event that must be handled by you
  OSStatus EventHandler( EventHandlerCallRef inHandler,
                         EventRef inEvent,
                         void* inUserData )
 {
     EventHotKeyID hotKeyID;
     GetEventParameter( inEvent,
                        kEventParamDirectObject,
                        typeEventHotKeyID,
                        nil,
                        sizeof(EventHotKeyID,
                        nil,
                        &hotKeyID ) 

   // use this to get your MyOwnEventHandler object back if need be
   // the reason why we get this is because we passed self in InstallEventHandler
   // in Carbon event callbacks you cannot access self directly
   // because this is a C callback, not an objective C method
    MyOwnEventHandler* handler = (MyOwnEventHandler *)inUserData;

   // handle the hotkey here - I usually store the id of the EventHotKeyID struct
   // in a objective C hotkey object to look up events in an array of registered hotkeys

  return eventNotHandledErr; // return this error for other handlers to handle this event as well
}

// call this objective C wrapper method to register your Carbon Event handler
- (void)registerForGettingHotKeyEvents {
       const EventTypeSpec kHotKeysEvent[] = {{ kEventClassKeyboard,   kEventHotKeyPressed }};
       AddEventTypesToHandler( [self handlerRef], GetEventTypeCount(kHotKeysEvent), kHotKeysEvent );
    }

// call this objective C wrapper method to unregister your Carbon Event handler
- (void)unregisterFromGettingHotKeyEvents {
       const EventTypeSpec kHotKeysEvent[] = {{ kEventClassKeyboard,   kEventHotKeyPressed }};
       RemoveEventTypesFromHandler( [self handlerRef], GetEventTypeCount(kHotKeysEvent), kHotKeysEvent );
    }

我希望这有帮助。如果你被困在某处,让我知道,我会尽力帮助你。

看起来好像没有人会帮助……这对我来说是非常奇怪的,因为C++实际上是在使用C++,因为我现在正在写C++程序:这是否意味着我可以直接调用必要的方法?问题是:我有自己的主循环。事实上,我有一个SMFL窗口,我必须支持它。但是,当程序失去焦点时(它变得不可见),它不起任何作用。我还可以在那里的某个地方安装碳活动管理器吗?也许当程序变得不可见时?非常感谢你的回答!现在,Carbon事件管理器出现在Carbon.Framework中。因此,添加这个框架并通过添加#include包含必要的标题