Getting the key state in Win32
Getting the key state in Win32
I'm programming a key logging program...and I need to get if and what key(s) are pressed. This should be called in the WinProc function....
I don't know how to use GetKeyboardState or GetKeyState....
I don't know how to use GetKeyboardState or GetKeyState....
Re:Getting the key state in Win32
well, what exactly are you trying to do? if you're trying to figure out what keys are pressed for any window in the entire system, probably the best way would be somewhat difficult (getting it so that your program intercepts keyboard input the way some of those virtual keyboards do). In fact, that's probably the only way that's guaranteed to work for something like that. If you just want to know if a specific key is pressed, then you should use GetAsyncKeyState, not GetKeyState and then test the return value against 0x8000. GetAsyncKeyState and GetKeyState both take an argument which is the virtual key code for the key you want to test (for example, if you want to see if Shift is being pressed at the moment, you use:
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
The reason for the 0x8000 thing is that GetAsyncKeyState and GetKeyState return a USHORT (16-bit unsigned int), and if the key is pressed then the highest-order bit is set, which is exactly the condition indicated by 0x8000. GetKeyState will tell you whether a given virtual key was pressed when a message was sent to your window, it will not give you the current state of the keyboard. Note that to log generic key presses, you'd have to call GetAsyncKeyState a ridiculous number of times, and by the time they all finish there's no guarantee that you won't miss a key press (I haven't actually tried it, so it might work just fine, but I'd say there's at least some probability that you could miss a key press). Also, your program will have to be a console application or else be multithreaded, otherwise Windows will log it as not responding (you'd have to call GetAsyncKeyState in a basically infinite loop). You could ask Windows to send you timer messages, but the smallest available resolution is something like 52 milliseconds.
You can always test these methods out and see if they work by hitting a key as fast as you possibly can. If you can't make your program miss the keypress after a bunch of tries, then you might assume that it's safe. Of course, there's still no guarantee, but the probability is higher, anyway.
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
The reason for the 0x8000 thing is that GetAsyncKeyState and GetKeyState return a USHORT (16-bit unsigned int), and if the key is pressed then the highest-order bit is set, which is exactly the condition indicated by 0x8000. GetKeyState will tell you whether a given virtual key was pressed when a message was sent to your window, it will not give you the current state of the keyboard. Note that to log generic key presses, you'd have to call GetAsyncKeyState a ridiculous number of times, and by the time they all finish there's no guarantee that you won't miss a key press (I haven't actually tried it, so it might work just fine, but I'd say there's at least some probability that you could miss a key press). Also, your program will have to be a console application or else be multithreaded, otherwise Windows will log it as not responding (you'd have to call GetAsyncKeyState in a basically infinite loop). You could ask Windows to send you timer messages, but the smallest available resolution is something like 52 milliseconds.
You can always test these methods out and see if they work by hitting a key as fast as you possibly can. If you can't make your program miss the keypress after a bunch of tries, then you might assume that it's safe. Of course, there's still no guarantee, but the probability is higher, anyway.
Re:Getting the key state in Win32
I found some example code that won't work...if I if (GetAsyncKeyState(VK_F2)) MessageBox("Test","Test", MB_OK, MB_ICONINFORMATION);
I get no message when I press F2.....
I get no message when I press F2.....
Re:Getting the key state in Win32
Apparently, it can't be a console app...this code seems to work fine (I couldn't get it to work as a console app, although I could get it to work as a console app when I tested the left mouse button):
Code: Select all
#include <windows.h>
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uiMsg,
WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR pszCmdLine, int nShowCmd)
{
MSG msg;
WNDCLASS wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = MainWndProc;
wndclass.lpszClassName = "KeyStateTestClass";
wndclass.lpszMenuName = NULL;
wndclass.style = 0;
RegisterClass(&wndclass);
HWND hwnd = CreateWindow("KeyStateTestClass", "Key Test",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uiMsg,
WPARAM wParam, LPARAM lParam)
{
switch(uiMsg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 0, NULL);
return 0;
case WM_DESTROY:
KillTimer(hwnd, 1);
PostQuitMessage(0);
return 0;
case WM_TIMER:
if (GetAsyncKeyState(VK_F2) & 0x8000)
{
MessageBox(hwnd, "Got F2", "Test", MB_OK);
}
return 0;
}
return ::DefWindowProc(hwnd, uiMsg, wParam, lParam);
}
Re:Getting the key state in Win32
by the way...I was wrong...GetAsyncKeyState returns a SHORT, not a USHORT
Re:Getting the key state in Win32
And I also need the MessageBox to come up out of the window....like if i'm in another window I need the message box on top of all windows...and need the "Key Test" window hidden....
Re:Getting the key state in Win32
Code: Select all
#include <windows.h>
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uiMsg,
WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR pszCmdLine, int nShowCmd)
{
MSG msg;
WNDCLASS wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = MainWndProc;
wndclass.lpszClassName = "KeyStateTestClass";
wndclass.lpszMenuName = NULL;
wndclass.style = 0;
RegisterClass(&wndclass);
HWND hwnd = CreateWindow("KeyStateTestClass", "Key Test",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uiMsg,
WPARAM wParam, LPARAM lParam)
{
switch(uiMsg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 0, NULL);
return 0;
case WM_DESTROY:
KillTimer(hwnd, 1);
PostQuitMessage(0);
return 0;
case WM_TIMER:
if (GetAsyncKeyState(VK_F2) & 0x8000)
{
MessageBox(hwnd, "Got F2", "Test", MB_OK | MB_SYSTEMMODAL);
}
return 0;
}
return ::DefWindowProc(hwnd, uiMsg, wParam, lParam);
}