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



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

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

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

所以,我简单地添加了NSKeyDownMask&NSKeyUpMask在我的跟踪循环中,当被计算时,相应地调用self.nextResponder keyDown/up:方法。这个特殊的自定义子类解决了我的问题。

但可可的天然对照品呢?我无法对那个异常进行编码。。。

我曾希望NSEvent的"addLocalMonitorForEventsMatchingMask:"方法但遗憾的是,doc表示:"对于嵌套事件跟踪循环(如控件跟踪、菜单跟踪或窗口拖动)所消耗的事件,将不会调用它"。

那么,无论应用程序的运行循环模式如何,都没有一个简单的解决方案来接收键盘事件吗?

正如您在NSEvent类'addGlobalMonitorForEventsMatchingMask:handler:的文档中所发现的,这种限制是设计的。

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

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

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

这本来自苹果的指南可以帮助你开始,以及这个问答;这里的堆栈溢出。

最新更新