Nick Van Brunt
Nick Van Brunt

Reputation: 15474

Respond to only the first WM_KEYDOWN notification?

How can a Win32 application respond to only the first WM_KEYDOWN notification? The MSDN docs claim bit 30 "Specifies the previous key state. The value is 1 if the key is down before the message is sent, or it is zero if the key is up." but bit 30 is always 0 in my WndProc.

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

Is lParam & 30 the wrong way to ask for this? Am I doing something else wrong?

Upvotes: 4

Views: 6094

Answers (4)

Sanders
Sanders

Reputation: 109

Bitwise AND (lParam & 0x4000000) will work but you can easily make it more readable using the defines included with Windows.h (which you're already using for WM_KEYDOWN):

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

HIWORD takes the most significant 16 bits.

KF_REPEAT (= 0x4000) flags the location of the bit representing a repeat WM_KEYDOWN message.

The bitwise AND of these values equals 0 when the repeat flag is off (the initial keypress) and equals 1 every subsequent time (the autorepeat feature) until the key is released.

It's a small thing but it goes a long way to improving the readability of your code. 0x40000000 does not mean anything to the reader while much can be inferred from KF_REPEAT.

Upvotes: 4

Pratik Bhatt
Pratik Bhatt

Reputation: 687

The problem with doing lParam & 30 is that, '30' over here is considered to be in decimal, which when converted to binary would '11110'. Hence you are not testing bit 30 but just getting the result for lparam & 11110.

Hope this helps in clarifying the problem a bit.

Upvotes: 1

sharptooth
sharptooth

Reputation: 170499

To test bit 30 don't AND with 30, instead AND with 1 << 30.

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

Upvotes: 12

RichieHindle
RichieHindle

Reputation: 281495

To get bit 30, you need this:

(lParam & 0x40000000)

An alternative would be to use bits 0-15 to get the repeat count:

int repeatCount = (lParam & 0xffff)

and only do anything if the repeat count is 0 (or possibly 1; I'm not sure whether the first message gets a repeat count of 0 or 1, and it's not clear from the documentation).

Upvotes: 4

Related Questions