[win32] - how use the WM_KEYDOWN and alt keys?

i can test when 2 or more keys are pressed:
1
2
3
4
5
6
7
8
9
10
11
bool KeyPressed(int a)
{
    if(GetAsyncKeyState(a))
    {
        return true;
    }
    else
    {
        return false;
    }
}


but imagine that i need these key combination: ALT+E(realy like the alt key combinations)... how can i do it?
Fixed line 3 for you:

 
    if(GetAsyncKeyState(a) & 0x8000)



If you don't want to use hotkeys, you can catch the WM_KEYDOWN message for 'E', then check to see if Alt is being held with GetAsyncKeyState:

1
2
3
4
5
6
7
8
9
10
11
case WM_KEYDOWN:
    switch(wParam)
    {
    case 'E':
        if( KeyPressed(VK_MENU) ) // is the menu/alt key being held down?
        {
            // here, Alt+E was pressed
        }
        break;
    }
    break;


But again, probably easier to use Hotkeys.



EDIT:

Actually... Alt+Key might not send a WM_KEYDOWN message because it might be treated as a system key. I'm not sure and I'm too lazy to try it out myself. Does the above not work?
Last edited on
sorry, the ' & 0x8000' don't works for me(give me, always, false) :(
now i have tested with hotkeys and works 100% fine(like i wanted).. thanks for all
(sorry about don't accept so easy the hotkeys. but now i understand that it's what i need.)
let me ask: when i use the WM_KEYDOWN how i can test the alt\control\shift keys with wParam or lParam?
sorry, the ' & 0x8000' don't works for me(give me, always, false) :(


o_O

huh?

let me ask: when i use the WM_KEYDOWN how i can test the alt\control\shift keys with wParam or lParam?


You can't. wParam and lParam are used for other things. Reference:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646280%28v=vs.85%29.aspx
yah... the alt key is a system key... so not always works correctly... that was my problem...
thanks for all... realy thanks and heres how i get the alt key(from caption):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char GettingAltKey(string text)
{
    char altkey;
    for(int i=0; text.length()-2;i++)
    {
        if(i>=1 && text[i-1]!='&' && text[i]=='&' && text[i+1]!='&' )
        {
            altkey=upper((char)text[i+1]);
            break;
        }
        else if(i<1 && text[i]=='&' && text[i+1]!='&' )
        {
            altkey=upper((char)text[i+1]);
            break;
        }
    }
    return altkey;
}

//WM_CREATE:
 altkey=GettingAltKey(caption);
RegisterHotKey( hwnd, Hotkey_Message, MOD_ALT, altkey );

when i must redefine the Hotkey_Message key, i belive that i must use the same id(Hotkey_Message).. correct me if i'm wrong, but i can test it ;)
thanks for all

Last edited on
Are.... are you simulating Window's accelerator functionality?

o_O

Windows does this automatically, you know.
Last edited on
yes i'm ;)
why? because i can do more with DrawText() than with SetWindowText() ;)
and, of course, i'm using the DrawItem message ;)

"Windows does this automatically, you know." i only use 1 function for show the underline letter when i press the alt key
for finish: can you explain to me how the lparam works?
i'm reading: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646280%28v=vs.85%29.aspx
but don't make sence to me :(
the 24 bit: "Indicates whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0."
i don't understand these(i said the 24, i could said other bit) :(
ok... i know the lparam have 1 value... but i don't understand these context 'the bit x'.
can you explain better please?
This site has a section for bitwise operators and how you can use them.
using binary numbers... but the lparam isn't a binary number
Computer memory is represented in binary, you can say 'everything is binary'.
but how can i give from bit x to bit y?
LPARAM is a 32-bit integer. Each bit can be either set (1) or clear (0).

Using hexadecimal numbers is easier to deal with binary because it more closely resembles binary. 1 hex digit directly corresponds to 4 binary digits. Here's a quick chart of hex numbers and their binary equivalents:


HEX     BINARY
================
0x01    00000001
0x02    00000010
0x04    00000100
0x08    00001000
0x10    00010000
0x20    00100000
0x40    01000000
0x80    10000000


The "low" bit is the bit furthest to the right. That is "bit 0". Bit bit to the left of that is bit 1. To the left of that is bit 2, and so on.

Each bit has a "weight" of 2n, where n is the bit number. So...
bit 0 has a weight of 20=1
bit 1 has a weight of 21=2
bit 2 has a weight of 22=4
bit 3 has a weight of 23=8
etc


HEX     BIN
============
0x0     0000    (0)
0x1     0001    (1)
0x2     0010    (2)
0x3     0011    (2 + 1)
0x4     0100    (4)
0x5     0101    (4 + 1)
0x6     0110    (4 + 2)
0x7     0111    (4 + 2 + 1)
0x8     1000    (8)
0x9     1001    (8 + 1)
0xA     1010    (8 + 2)
0xB     1011    (8 + 2 + 1)
0xC     1100    (8 + 4)
0xD     1101    (8 + 4 + 1)
0xE     1110    (8 + 4 + 2)
0xF     1111    (8 + 4 + 2 + 1)
        ^^^^
        ||||
        |||\___bit 0  (weight of 1)
        |||
        ||\___bit 1  (weight of 2)
        ||
        |\___bit 2  (weight of 4)
        |
        \___bit 3  (weight of 8)


So as you can see, the binary value of 0101 is a value of 5... because bits 0 and 2 are set. Which means the value is:

20 + 22
= 1 + 4
= 5



With that in mind... the binary operators AND (&), OR (|), and complement (~) are frequently used to pull out individual bits from a value. Each operation is performed on each bit in the values. See below for examples:

OR takes 2 bits, and if either one of them are set, the result is set. Otherwise the result is clear.

0 OR 0 = 0
0 OR 1 = 1
1 OR 0 = 1
1 OR 1 = 1


Therefore... 0x26 | 0x44 == 0x66 because:

0x26  =  00100110
0x44  =  01000100
     OR  ========
0x66     01100110



OR is frequently used to set specific bits, because any bit OR 1 will result in 1:
1
2
3
4
5
6
7
8
9
myval = myval | 0x04;  // set bit 2

/* because:

myval = xxxxxxxx  (can be anything)
0x04  = 00000100
     OR ========
        xxxxx1xx  (x bits remain unchanged... bit 2 forced to be set)
*/



AND takes 2 bits, and if both one of them are set, the result is set. Otherwise the result is clear.

0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1


Therefore... 0x26 & 0x44 == 0x04 because:

0x26  =  00100110
0x44  =  01000100
    AND  ========
0x04     00000100



AND is frequently used to isolate bits you are interested in by forcing other bits to be clear.... because any bit AND 0 will result in 0:
1
2
3
4
5
6
7
8
9
myval = myval & 0x04;  // isolate bit 2

/* because:

myval = xxxxxxxx  (can be anything)
0x04  = 00000100
    AND ========
        00000x00  (bit 2 remains unchanged... all other bits forced to 0)
*/




COMPLEMENT takes 1 bit, and just flips it. So if it was clear, it is set, and if it was set, it is cleared.

~0 = 1
~1 = 0


Therefore... ~0x04 == 0xFB (assuming 8-bit value) because:

0x04  =  00000100
   COMP  ========
0xFB     11111011  (all bits flipped)



COMPLEMENT is frequently used with AND to clear specific bits. Kind of like the opposite of an OR operation:
1
2
3
4
5
6
7
8
9
10
11
12
myval = myval & ~0x04;  // clear bit 2

/* because:
0x04  = 00000100
   COMP ========
        11111011

        11111011
myval = xxxxxxxx
    AND ========
        xxxxx0xx  (all bits unchanged except for bit 2, which is forced clear)
*/




This is why... when you use GetAsyncKeyState... you should always AND with 0x8000. Since the keystate is stored in bit 15... that is probably the only bit you are interested in. All the other bits mean something else:

1
2
3
4
5
6
7
8
9
int foo = GetAsyncKeyState( VK_ESCAPE );  // get the key state

// key state is in bit 15 only .. other bits means other stuff
//  so isolate bit 15 with an AND operation:

if( foo & 0x8000 )  // is bit 15 set?
{
   // if yes, the key is pressed
}




For the LPARAM in WM_KEYDOWN, you can use AND to isolate the bits you are interested in. So if you want to look at the repeat count (which is in bits 0-15):

 
int repeatcount = lParam & 0x0000FFFF;  // isolate the low 16 bits by forcing all other bits to be clear 


To get the scan code (in bits 16-23), you'd do the same thing, but you'd want to shift the bits over as well:

1
2
3
int scancode = lParam & 0x00FF0000;  // isolate bits 16-23
scancode >>= 16;  // then shift all bits to the right 16 places
                  // this turns 0x00FF0000 into 0x000000FF 
Last edited on
now i understand better.. thanks for all
the manuals aren't completed, but you give the better for use with real examples... thanks for all
then for bit 24 we do:
int extendedkey= lParam & 0x00FFFFFF;
is these correct?
Cambalinho wrote:
then for bit 24 we do:
int extendedkey= lParam & 0x00FFFFFF;
is these correct?



0x00FFFFFF = 00000000 11111111 11111111 11111111
                    ^        ^        ^        ^
                    |        |        |        |
                    |        |        |        \__ bit 0
                    |        |        |
                    |        |        \__ bit 8
                    |        |
                    |        \__ bit 16
                    |
                    \__ bit 24


So that will isolate bits 0-23 (the low 24 bits)
But not bit 24. Bit 24 will be forced to zero.

If you want bit 24 (the extended key bit), then you want:


0x01000000 = 00000001 00000000 00000000 00000000
                    ^        ^        ^        ^
                    |        |        |        |
                    |        |        |        \__ bit 0
                    |        |        |
                    |        |        \__ bit 8
                    |        |
                    |        \__ bit 16
                    |
                    \__ bit 24


So you could say:

1
2
3
4
if(lParam & 0x01000000)
{
    // extended key bit is set
}



Or... rather than counting out the bits like that, you can cheat with the left shift operator. IE: 1<<x will give you a value where all bits are clear except for bit X which will be set.

So if you want bit 24:

1
2
3
4
if(lParam & (1<<24)) // <- is bit 24 set?
{
    // extended key bit is set
}
thanks for all... i mistake for a while ;)
thanks for all
Topic archived. No new replies allowed.