4

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?

Nick Van Brunt
  • 14,952
  • 11
  • 64
  • 91
  • How did you end up implementing this? repeatCount=(lParam & 0xffff); if(repeatCount < 1) Action(); Doesn't seem to work for me. Nor does repeatCount < 2. I either get repeating keys or no key press at all. – Sam152 Oct 12 '09 at 04:16
  • 1
    I used: if ((lParam & (1 << 30)) == 0)... although if (lParam & 0x40000000) worked as well if I remember correctly. My choice was based on readability (1 << 30) makes more sense to me than 0x40000000 – Nick Van Brunt Oct 13 '09 at 15:09
  • Thanks man, I will give it a squeeze. – Sam152 Oct 14 '09 at 14:15

4 Answers4

11

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

const bool isBitSet = lParam & (1 << 30);
sharptooth
  • 163,328
  • 92
  • 501
  • 942
4

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).

RichieHindle
  • 258,929
  • 46
  • 350
  • 392
  • This worked - thank you. My bit fiddling-fu is a little shaky. What exactly is 0x40000000? – Nick Van Brunt Sep 01 '09 at 14:36
  • 2
    That's a DWORD representing a bitmask consisting of bit 30 set and all other bits cleared. – sharptooth Sep 01 '09 at 14:37
  • You might want to read an introduction to hexadecimal, eg. http://www.learn-programming.za.net/articles_decbinhexoct.html It's not too hard, but not so trivial that I can explain it all here. – RichieHindle Sep 01 '09 at 14:40
4

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.

Sanders
  • 109
  • 5
1

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.

Pratik Bhatt
  • 687
  • 4
  • 15