我是Mac编程的新手,所以我希望这不是很明显。
简而言之,我似乎没有得到多个按键事件。我创建了这个片段,它永远不会触发断言,因此永远不会打印多个键。不过,我得到了单键打印。
- (void)keyDown:(NSEvent *) theEvent {
NSString *characters = [theEvent characters];
assert([characters length]<2);
for (int i=0;i<[characters length];++i) {
NSLog(@"k=[%d]\n", [characters characterAtIndex:i]);
}
}
有谁知道我做错了什么?如果您有兴趣,我需要多次按键才能进行OpenGL查看应用程序。也许我对这种应用完全不合适。
编辑:经过进一步研究,我发现了这个: http://www.cocoadev.com/index.pl?GameKeyBoardHandling 这基于这里的讨论是有意义的,因为只有最后一个键重复。当抛出keyDown事件时,向下键放在set中并在keyUp上删除。这意味着该集具有完整的当前按下键,避免了重复上次持有的问题。 它“足够好”,所以我现在正在使用这种方法。它似乎运行良好,并且因为它使用标准键盘事件系统(而不是HID),所以不应存在任何兼容性问题。
此致 沙恩
答案 0 :(得分:2)
有一点是你正在测试事件中几乎总是1的字符数。在事件中获得超过1个字符的最常见方法是对非西方字符使用IME输入法。
目前还不清楚你想要完成什么。如果您尝试对用户按下并按住某个键作出反应,您将获得多个keyDown:事件。在第一个事件上调用isARepeat将返回NO,在后续事件中它将返回YES。
如果您尝试同时检测多个按键,则需要在keyDown:和keyUp:之间自行跟踪关键状态。因此,如果您同时按下f和g,您将获得一个keyDown或更多keyDown:使用f和一个或多个keyDown:with g。然后,如果你在仍然持有g的情况下释放f,你将得到一个keyUp:for f,同时继续接收keyDown:for g。您可以为每个键设置一个标志,然后在键上升时清除标志。
如果这些都不是你想要做的,那么你可能想要解释你在做什么。
答案 1 :(得分:2)
每个NSEvent代表:一个事件。当一个键发生故障时,这就是一个事件。当另一个键发生故障时,那是另一个事件。
characters
字符串就是:文本字符串。如果您手动执行此操作,则会将其插入到文本存储中。它不会告诉您按下了哪些字符键;这是关键代码的工作。对于修饰键,它是modifierFlags
位掩码的作用。
如果你正在编写游戏,你可能会发现DDHIDLib或Leopard中的新HID API更有用。此外,请记住,用户可能有多个键盘,因此用户可以按两个空格键,例如。
最后,请用Dvorak测试你的程序。许多试图处理原始键盘事件的应用程序都错了,最终让我们感到困惑,甚至根本不为我们工作。 Flash有一个长期存在的问题,即忽略QWERTY中标点符号的键,即使它们是活动布局中的字母键(Dvorak中的几个键都是如此)。而且我们不是唯一不使用QWERTY的人;许多非英语键盘偏离了QWERTY布局。
答案 2 :(得分:1)
我已在实际问题正文中发布了我的问题的答案,但总之我发现the GameKeyBoardHandling article on CocoaDev 效果很好。
答案 3 :(得分:1)
嗯,接受的答案的链接已经死了,可能它类似于:
#import <Carbon/Carbon.h> // for kVK_* names
- (void)keyDown:(NSEvent *event)
{
unsigned keyCode = [event keyCode];
if (keyCode < 128) keysDown[keyCode] = YES;
}
- (void)keyUp:(NSEvent *event)
{
unsigned keyCode = [event keyCode];
if (keyCode < 128) keysDown[keyCode] = NO;
}
- (void)whereverYouUpdateTheStateOfYourGame
{
if (keysDown[kVK_ANSI_A] && !keysDown[kVK_ANSI_D]) { /* move left */ }
if (keysDown[kVK_ANSI_D] && !keysDown[kVK_ANSI_A]) { /* move right */ }
if (keysDown[kVK_ANSI_W] && !keysDown[kVK_ANSI_S]) { /* move up */ }
if (keysDown[kVK_ANSI_S] && !keysDown[kVK_ANSI_W]) { /* move down */ }
}
上面的source of code还指出,我们应该注意一些硬件限制。
答案 4 :(得分:0)
我认为在正常情况下您不能同时收到多个密钥。仅在按下某个键时调用keyDown
并且(我不认为)可以在同一时间按下两个键;但是,根据the Apple docs on NSEvent
,单个按键可能会生成多个字符。我最好的猜测是多个字符引用UNICODE代码点,除了NSString
是一个UNICODE序列,所以我看不出如何生成多个字符,除非创建自己的事件。
然而,修饰键是一个不同的故事。如果您正在寻找修改键,那么您需要以下内容:
if ([event modifiers] & NSShiftKeyMask) {
...
}