Несколько клавиш удерживаются в Какао (OS X) - PullRequest
3 голосов
/ 20 июля 2009

Я новичок в программировании на 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, клавиша «вниз» помещается в набор и удаляется в keyUp. Это означает, что в наборе есть полный набор клавиш, удерживаемых в данный момент, что позволяет избежать проблемы «только повторения последнего удержания». Это «достаточно хорошо», поэтому я использую этот метод сейчас. Кажется, он работает хорошо, и поскольку он использует стандартную систему событий клавиатуры (а не HID), проблем с совместимостью не должно быть.

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

Ответы [ 5 ]

2 голосов
/ 20 июля 2009

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

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

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

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

2 голосов
/ 20 июля 2009

Каждое событие NSE представляет только одно: одно событие. Когда ключ падает, это одно событие. Когда нажимается другая клавиша, это другое событие.

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

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

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

1 голос
/ 27 декабря 2014

Ну, ссылка принятого ответа мертва, возможно, это было что-то похожее на:

#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 голос
/ 21 июля 2009

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

0 голосов
/ 20 июля 2009

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

Клавиши-модификаторы - это отдельная история. Если вы ищете клавиши-модификаторы, то вам нужно что-то вроде:

if ([event modifiers] & NSShiftKeyMask) {
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...