Ответьте только на первое уведомление WM_KEYDOWN?

Как приложение 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 неправильным способом просить об этом? Я делаю что-то еще не так?

Ответ 1

Чтобы получить бит 30, вам понадобится следующее:

(lParam & 0x40000000)

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

int repeatCount = (lParam & 0xffff)

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

Ответ 2

Для проверки бита 30 не следует И с 30, вместо И с 1 < 30.

const bool isBitSet = lParam & (1 << 30);

Ответ 3

Побитовое И (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.

Ответ 4

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

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