Я новичок в программировании для Mac, поэтому надеюсь, что это не очевидно.

Короче говоря, похоже, что я не получаю несколько событий нажатия клавиш. Я создал этот фрагмент, который никогда не запускает assert и, следовательно, никогда не печатает несколько ключей. Но я получаю отпечатки единственного ключа.

- (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), проблем с совместимостью быть не должно.

С уважением, Шейн

3
Shane 20 Июл 2009 в 06:32

5 ответов

Лучший ответ

Я разместил ответ на свой вопрос в самом теле вопроса, но вкратце я нашел статью GameKeyBoardHandling о CocoaDev что хорошо работает.

1
Peter Hosey 24 Май 2012 в 08:43

Во-первых, вы проверяете количество символов в событии, которое почти всегда равно 1. Самый распространенный способ получить более 1 символа в событии - это использование метода ввода IME для не западных символов.

Непонятно, чего вы пытаетесь достичь. Если вы пытаетесь отреагировать на нажатие и удержание клавиши пользователем, вы получите несколько событий keyDown :. Вызов isARepeat для первого события вернет NO, для последующих событий - YES.

Если вы пытаетесь обнаружить одновременное нажатие нескольких клавиш, вам необходимо самостоятельно отслеживать состояния клавиш между keyDown: и keyUp :. Итак, если вы нажали f и g одновременно, вы получите один или несколько keyDown: с f и один или несколько keyDown: с g. тогда, если вы отпустите f, все еще удерживая g, вы получите keyUp: for f, продолжая получать keyDown: for g. Вы можете установить флаг для каждой полученной клавиши, а затем сбросить флаг, когда клавиша поднимется.

Если ни одно из этих действий не является тем, что вы пытаетесь сделать, возможно, вы захотите объяснить, что вы делаете дальше.

2
Jon Steinmetz 20 Июл 2009 в 03:03

Каждое NSEvent представляет именно это: одно событие. Когда клавиша выходит из строя, это одно событие. Когда другая клавиша выходит из строя, это другое событие.

Строка characters - это всего лишь текстовая строка. Это то, что вы бы вставили в свое текстовое хранилище, если бы делали это вручную. Он не сообщает вам, какие символьные клавиши были нажаты; это работа ключевых кодов. Для клавиш-модификаторов это работа битовой маски modifierFlags.

Если вы пишете игру, вы можете найти либо DDHIDLib или новый HID API в Leopard более полезны. Также помните, что у пользователя может быть несколько клавиатур, поэтому пользователь (пользователи) могут, например, нажать два пробела.

Наконец, пожалуйста, протестируйте свою программу с Дворжаком. Многие приложения, которые пытаются обрабатывать необработанные события клавиатуры, ошибаются и в конечном итоге сбивают нас с толку или даже вообще не работают для нас. Flash имеет давнюю проблему игнорирования клавиш, которые являются знаками препинания в QWERTY, даже если они являются буквенными клавишами в активной раскладке (верно для нескольких клавиш в Dvorak). И не только мы не используем QWERTY; многие неанглоязычные клавиатуры отличаются от раскладки QWERTY.

2
Peter Hosey 20 Июл 2009 в 03:19

Что ж, ссылка на принятый ответ мертва, вероятно, это было что-то похожее на:

#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 */ }
}

В исходном коде выше также говорится, что могут быть некоторые аппаратные ограничения, мы должны быть осторожны о.

1
guness 27 Дек 2014 в 17:24

Я не верю, что при нормальных обстоятельствах вы можете получить одновременно несколько ключей. keyDown вызывается только тогда, когда нажата клавиша и (я не думаю, что) две клавиши могут быть нажаты в одно и то же время; однако одно нажатие клавиши может генерировать более одного символа в соответствии с документы Apple на NSEvent. Я предполагаю, что несколько символов относятся к кодовым точкам UNICODE, за исключением того, что NSString является последовательностью UNICODE, поэтому я не вижу, как вы могли бы сгенерировать более одного символа, кроме как путем создания собственного события.

Однако с клавишами-модификаторами дело обстоит иначе. Если вы ищете клавиши-модификаторы, вам понадобится что-то вроде:

if ([event modifiers] & NSShiftKeyMask) {
    ...
}
0
D.Shawley 20 Июл 2009 в 02:48