【发布时间】:2011-08-16 05:42:37
【问题描述】:
假设您正在为 Mac OS X 创建游戏。事实上,假设您正在创建 Quake,但它是 2011 年,您更愿意只使用现代的、未弃用的框架。
您希望在用户按下(或释放)键盘上的键(任意键)时通知您的游戏。这包括修改键,如 shift 和 control。 编辑添加:另外,您想知道修改键的左或右版本是否被按下。
您还希望您的游戏有一个配置屏幕,用户可以在其中检查和修改键盘配置。它应该包含以下内容:
- 前进:W
- 跳跃:空间
- 火:LCTRL
你是做什么的?一天左右以来,我一直试图找到一个好的答案,但没有成功。
这是我想出的:
- 子类 NSResponder,实现 keyUp: 和 keyDown:,就像在 this answer 中一样。这种方法的一个问题是,当用户仅按下修饰键时,不会调用 keyUp: 和 keyDown:。要解决这个问题,您可以实现 flagsChanged:,但这感觉像是 hack。
- 使用Quartz Event Tap。这仅适用于应用程序以 root 身份运行,或者用户启用了对辅助设备的访问权限。此外,修饰键事件仍然不算作常规键事件。
- 使用 HI 工具箱。在 10.6 开发者文档中几乎没有提及它。它似乎非常非常不推荐使用。
那么,这样做的正确方法是什么?这真的感觉像是一个应该有一个众所周知的、有据可查的解决方案的问题。游戏并不是非常小众。
【问题讨论】:
-
FWIW,我不认为
-flagsChanged:或NSFlagsChangedMask是黑客。这是记录在修改键(如 Control)更改时通知的方式。 -
我并不是说 flagsChanged: 是一种 hack,而是说使用它为此目的感觉就像是一种 hack。如果您正在编写文本编辑器,那么以不同的方式处理修饰键事件是个好主意!但是,如果您想知道刚刚按下了哪个键,无论可能是哪种键,flagsChanged: 似乎都不适合我。当然,您可以存储 [event modifierFlags] 的值并对此进行比较——它可以做到——但我觉得应该有一个更好、更直接的方法,这已经足够了。有吗?
-
我认为没有其他方法。据我所知,Cocoa 遵循您所描述的推理:在大多数情况下,修饰键本身并不相关。也就是说,您可以将
-keyDown:、-keyUp:、-flagsChanged:抽象为一两个有效地执行应用程序中的操作的方法——这三个方法将简单地过滤事件并调用您的自定义方法。 -
呸,奇怪的行为。我已经通过使用静态计数器解决了这个问题:在您的
if部分,我增加了计数器,如果计数器小于 2,则认为它是一个键;否则,我会减少计数器并将其视为向上键。在else部分,我递减计数器并将其视为向上键。我只为一个键做到了这一点;您必须为每个修饰键设置一个计数器。 -
我不确定这是一个好的解决方案,因为 2 是恒定的,我猜理论上用户有可能拥有多个键盘,而 2 应该是 4。我无法对此进行测试,不过。