Cocoa:拖动时不会触发键盘事件(NSEventTrackingRunLoopMode)

时间:2013-08-04 21:35:25

标签: objective-c cocoa event-handling nsrunloop

通过我的窗口控制器的keyDown:方法,我成功地能够对键盘事件作出反应 执行鼠标拖动时出现问题:
键盘事件似乎被延迟,只会在鼠标上启动。

要明确,我的意思是:
•在窗口控制器的keyDown中放置一个日志语句:方法
•启动您的应用程序,执行一些拖动操作(例如,在NSSlider上) •在保持阻力的同时,按任意键:没有任何记录到控制台 •释放拖动:日志出现,是的...

我正在拖动的控件是一个自定义的NSSlider 我已经使用“鼠标跟踪循环”方法实现了拖动机制。 据我所知,在拖动时,NSApplication的主要运行循环模式正在切换到NSEventTrackingRunLoopMode,从而限制了传入事件。

所以,我只是添加了NSKeyDownMask& NSKeyUpMask在我的跟踪循环中并且在受到欢迎时,相应地称为self.nextResponder keyDown / up:方法。 我的问题已经解决了这个特定的自定义子类。

但是可可的原生控制怎么样?我无法编写该异常代码......

我曾希望NSEvent的“addLocalMonitorForEventsMatchingMask:”方法 但唉,doc说:“不会被嵌套事件跟踪循环所消耗的事件调用,例如控制跟踪,菜单跟踪或窗口拖动”。

那么,无论应用程序的runloop模式如何,是否有接收键盘事件的直接解决方案?

1 个答案:

答案 0 :(得分:2)

正如您在NSEvent班级'的文档中找到的那样addGlobalMonitorForEventsMatchingMask:handler:,此限制是设计使然。

但是,您可以通过使用IOKit框架(特别是IOHID部分)来接收它,以接收低级别设备事件/中断。我最近不得不这样做,以便在鼠标拖动过程中跟踪一些特定的按键。

基本要点是使用IOHIDManagerCreate()创建一个IOHID管理器,然后将管理员的类型添加到管理器中,它应该"监控"使用IOHIDManagerSetDeviceMatchingMultiple(),通过IOHIDManagerRegisterInputValueCallback()向管理员注册回调,为IOHIDManagerScheduleWithRunLoop()的经理安排正确的运行循环,最后使用IOHIDManagerOpen()打开经理。

要在鼠标拖动期间获取这些低级别事件,请在单独的线程中执行此设置。在为管理器安排运行循环时,使用CFRunLoopGetCurrent()获取当前线程的运行循环,并在CFRunLoopRun()之后调用IOHIDManagerOpen()

This guide from Apple可以帮助您开始使用this Q&A here on Stack Overflow