在Cocoa(OS X)中按下了多个键

时间:2009-07-20 02:32:52

标签: cocoa keyboard

我是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),所以不应存在任何兼容性问题。

此致 沙恩

5 个答案:

答案 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) {
    ...
}