问题
im having a bit of trouble writing a keyboard hook in C++.
I can read keystrokes but im trying to using ToUnicodeEx() to convert keystrokes when shift key is pressed. In the code i have so far i have
i = ToUnicodeEx(keyboard.vkCode, keyboard.scanCode, (PBYTE)&keyState, (LPWSTR)&keybuff, sizeof(keybuff) / 16, 0,keyboardlayout);
MessageBox(MainnhWnd,keybuff, L"message", MB_OK | MB_ICONEXCLAMATION);
with this 'MessageBox' line when I press Shift+2 i get two message boxes pops up, the first is blank for the shift key, the second shows a '@' character. This is expected.
But if i remove this messagebox, the ToUnicodeEx() function converts the keystroke as if the shift key had not been used. I can see this by either setting a breakpoint, with a hit counter, or outputting the character to an edit box in my program windows.
Also when i include the MsgBox line and use the CapLock, my letters change accordingly but after i remove the msgbox line it only uses the state of the cap lock at the time my program starts (cap locks is on when programm starts, all letters are capital, vice verse, caps off when programm starts all letters are small,, even if i change the cap lock state)
Anyone know why my hook just remembers the keyboard state at start, unless i include the msgbox?
My hook is set like:
theHook = SetWindowsHookEx ( WH_KEYBOARD_LL, (HOOKPROC) KeyEvent, exe, 0);
and my hook callback function is:
DLLEXPORT LRESULT CALLBACK KeyEvent(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode>=0) {
int i = 0;
KBDLLHOOKSTRUCT keyboard;
WCHAR keybuff[256]= {0};
if ((wParam == WM_KEYDOWN)|| (wParam == WM_SYSKEYDOWN)||(wParam == WM_SYSKEYUP)) {
keyboard = *((KBDLLHOOKSTRUCT*)lParam);
if (keyboard.vkCode == VK_RETURN) {
i += wsprintf (((LPWSTR)keybuff + i),L"[Return]\r\n");
}
else {
HKL keyboardlayout = GetKeyboardLayout(0);
GetKeyboardState((PBYTE)&keyState);
i = ToUnicodeEx(keyboard.vkCode, keyboard.scanCode, (PBYTE)&keyState, (LPWSTR)&keybuff, sizeof(keybuff) / 16, 0,keyboardlayout);
MessageBox(MainnhWnd,keybuff, L"message", MB_OK | MB_ICONEXCLAMATION);
}
if (keybuff>0) {
addToEditBox(keybuff);
}
}
}
return CallNextHookEx(theHook, nCode, wParam, lParam);
}
回答1:
According to documentation of ToUnicodeEx function, you should provide a pointer to a 256-byte array that contains the current keyboard state (const BYTE *lpKeyState
). Each element (byte) in the array contains the state of one key. If the high-order bit of a byte is set, the key is down.
Before you call ToUnicodeEx
, you should set this array like this (pseudocode):
enum Keys
{
ShiftKey = 16, // shift
ControlKey = 17, // ctrl
Menu = 18, // alt
Capital = 20, // caps lock
};
BYTE keyState[256]= {0};
if (Control key down)
keyState[Keys::ControlKey] = 0x80;
if (Shift key down)
keyState[Keys::ShiftKey] = 0x80;
if (Alt key down)
keyState[Keys::Menu] = 0x80;
if (Caps lock ON)
keyState[Keys::Capital] = 0x01;
And when keyState array is set, then you can call:
ToUnicodeEx(keyboard.vkCode, keyboard.scanCode, (PBYTE)&keyState, (LPWSTR)&keybuff, sizeof(keybuff) / 16, 0,keyboardlayout);
I have been working with ToUnicodeEx
function just like this and it worked fine.
Hope this will help you ;)
来源:https://stackoverflow.com/questions/9046817/c-tounicodeex-not-recognizing-shift-key-unless-i-have-a-messgaebox