How to use (Get|Set)KeyboardState() to modify the keyboard state when using PostMessage()?

Marcus 41 Reputation points
2022-08-17T04:38:09.697+00:00

I read that when the TranslateMessage() API is called, it 'checks' your current keyboard state, so if you want to really 'simulate' a key input, you need to also modify the thread's keyboard state.

I'm trying to understand what |= 0x80 means, is it 'the key is down'?

DWORD current_thread_id = GetCurrentThreadId();  
DWORD thread_id = GetWindowThreadProcessId(hWnd, NULL);  
  
AttachThreadInput(current_thread_id, thread_id , true);  
  
BYTE KeybState[256] = { '\0' };  
  
GetKeyboardState((PBYTE)&KeybState);  
  
KeybState[...] |= 0x80;  
  
SetKeyboardState((LPBYTE)&KeybState);  
  
SetFocus(hWnd);  
  
PostMessage(hWnd, WM_KEYDOWN, ..., ...);  
PostMessage(hWnd, WM_KEYUP, ..., ...);  
  
AttachThreadInput(current_thread_id, thread_id , false);  

The order of AttachThreadInput is correct? first GetCurrentThreadId then GetWindowThreadProcessId?

What value represents when the key is up, KeybState[...] = 0?

Suppose I'm trying to send #, I need to:

KeybState[VK_SHIFT] |= 0x80;  
SetKeyboardState((LPBYTE)&KeybState);  
PostMessage(hWnd, WM_KEYDOWN, VK_SHIFT, lParam);  
PostMessage(hWnd, WM_KEYUP, 0x33, lParam); // 0x33 vk_code for the  3 key  

Or, do I also need to use KeybState[0x33] |= 0x80;?

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,523 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,637 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Bruno van Dooren 21 Reputation points
    2022-08-17T05:49:21.557+00:00

    KeybState is an array of bytes. Each of those bytes can be toggled or not (on or off). This is indicated via the most significant bit of each byte.
    That is where 0x80 comes from. In that byte value, the highest bit is 1 which means the key is 'pressed' or down.
    If you set it to 0, then the most significant bit is 0, meaning 'not pressed' or up.

    The order in which you attach seems correct. You don't need to send the keydown for the shift key. That is achieved via the keyboard state already unless you also want to process the setting of the shift key.

    KeybState[VK_SHIFT] |= 0x80;
    SetKeyboardState((LPBYTE)&KeybState);

    this will simulate the shift key being held down you don't have to postmessage the shiftkey again.

    EDIT: The easiest way to test these things is simply to make a new MFC dialog project, and put such code under a button click or in the InitDialog function. That way you can immediately see the result.

    2 people found this answer helpful.
    0 comments No comments