【发布时间】:2010-01-06 06:46:01
【问题描述】:
如果你创建一个没有窗口的状态栏应用,你如何响应事件?
我的第一个猜测是创建 NSResponder 的子类并覆盖适当的方法。 然而,他们永远不会被调用。
此线索明确调用:
[self becomeFirstResponder];
这也不起作用(我不相信 Apple Docs 推荐)
有没有办法让我的 NSResponder 子类进入响应者链?
【问题讨论】:
标签: objective-c cocoa input
如果你创建一个没有窗口的状态栏应用,你如何响应事件?
我的第一个猜测是创建 NSResponder 的子类并覆盖适当的方法。 然而,他们永远不会被调用。
此线索明确调用:
[self becomeFirstResponder];
这也不起作用(我不相信 Apple Docs 推荐)
有没有办法让我的 NSResponder 子类进入响应者链?
【问题讨论】:
标签: objective-c cocoa input
如果您没有窗口,您希望收到什么样的关键事件?
如果您需要全局拦截关键事件,则需要使用 Quartz Event Tap。您必须非常小心这些,因为在事件点击处理程序中抛出异常可能会冻结窗口服务器,因此您应该进行异常处理。
#import <ApplicationServices/ApplicationServices.h>
//assume CGEventTap eventTap is an ivar or other global
void createEventTap(void)
{
CFRunLoopSourceRef runLoopSource;
///we only want keydown events
CGEventMask eventMask = (1 << kCGEventKeyDown);
// Keyboard event taps need Universal Access enabled,
// check whether we're allowed to attach an event tap
if (!AXAPIEnabled()&&!AXIsProcessTrusted()) {
// error dialog here
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert addButtonWithTitle:@"OK"];
[alert setMessageText:@"Could not start event monitoring."];
[alert setInformativeText:@"Please enable \"access for assistive devices\" in the Universal Access pane of System Preferences."];
[alert runModal];
return;
}
//create the event tap
eventTap = CGEventTapCreate(kCGHIDEventTap, //this intercepts events at the lowest level, where they enter the window server
kCGHeadInsertEventTap,
kCGEventTapOptionDefault,
eventMask,
myCGEventCallback, //this is the callback that we receive when the event fires
nil);
// Create a run loop source.
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
// Add to the current run loop.
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
// Enable the event tap.
CGEventTapEnable(eventTap, true);
}
//the CGEvent callback that does the heavy lifting
CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef theEvent, void *refcon)
{
//handle the event here
//if you want to capture the event and prevent it propagating as normal, return NULL.
//if you want to let the event process as normal, return theEvent.
return theEvent;
}
【讨论】:
答案当然很简单:
[NSApp currentEvent];
返回任何可可应用程序中的当前事件。
【讨论】: