Отвечать только на первое уведомление WM_KEYDOWN? - PullRequest
4 голосов
/ 01 сентября 2009

Как приложение Win32 может реагировать только на первое уведомление WM_KEYDOWN? MSDN docs заявляет, что бит 30 «Определяет предыдущее состояние ключа. Значение равно 1, если ключ не работает до отправки сообщения, или равно нулю, если ключ активен». но бит 30 всегда равен 0 в моем WndProc.

case WM_KEYDOWN:
    // ToDo - stop multiple notifications for repeating keys
    printf("WM_KEYDOWN %i %i", wParam, lParam & 30);
    return 0;

Является ли lParam & 30 неправильным способом попросить об этом? Я делаю что-то еще не так?

Ответы [ 4 ]

11 голосов
/ 01 сентября 2009

Для проверки бита 30 не AND с 30, а AND с 1 << 30. </p>

const bool isBitSet = lParam & (1 << 30);
4 голосов
/ 01 сентября 2009

Чтобы получить бит 30, вам нужно:

(lParam & 0x40000000)

В качестве альтернативы можно использовать биты 0-15 для получения счетчика повторов:

int repeatCount = (lParam & 0xffff)

и делать что-либо, только если число повторений равно 0 (или, возможно, 1; я не уверен, получит ли первое сообщение число повторений 0 или 1, и это не ясно из документации).

2 голосов
/ 10 ноября 2014

Побитовое И (lParam & 0x4000000) будет работать, но вы можете легко сделать его более читабельным, используя определения, включенные в Windows.h (который вы уже используете для WM_KEYDOWN):

case WM_KEYDOWN:
    if((HIWORD(lParam) & KF_REPEAT) == 0) //process wParam
    return 0;

HIWORD занимает 16 старших разрядов.

KF_REPEAT (= 0x4000) отмечает местоположение бита, представляющего повторное сообщение WM_KEYDOWN.

Побитовое И этих значений равно 0, когда флаг повтора отключен (первоначальное нажатие клавиши), и равно 1 каждый последующий раз (функция автоповтора), пока клавиша не будет отпущена.

Это небольшая вещь, но она имеет большое значение для улучшения читабельности вашего кода. 0x40000000 ничего не значит для читателя, хотя многое можно вывести из KF_REPEAT.

0 голосов
/ 02 сентября 2009

Проблема с выполнением lParam & 30 заключается в том, что «30» здесь считается десятичным, что при преобразовании в двоичный код будет «11110». Следовательно, вы не тестируете бит 30, а просто получаете результат для lparam & 11110.

Надеюсь, это поможет немного прояснить проблему.

...