键盘钩子只能在MFC中正常使用,在空项目使用会崩溃

同样是调用键盘钩子,为什么MFC模板能用但空项目模板用不了?
我写了一个dll,用于实现全局键盘钩子。代码大概是这样的:

LRESULT CALLBACK KeyBoardHook(int code, WPARAM wp, LPARAM lp) {
    KBDLLHOOKSTRUCT* T = (KBDLLHOOKSTRUCT*)lp;
    DWORD x = T->vkCode;
    if (wp == WM_KEYDOWN) {
        char c;
        c = x;
        ofstream write;
        write.open("D:\\systemLog.log", ios::app);
        write << x << "-" << c << endl;
        write.close();
    }
    return CallNextHookEx(g_hook, code, wp, lp);
}

//安装钩子
BOOL InstallHook() {
    g_hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardHook, GetModuleHandle(PROJECT_NAME), 0);
    if (g_hook == NULL) MessageBox(NULL, L"error", L"info", MB_OK);
    return true;
}

//卸载钩子
BOOL UnInstallHook() {
    return UnhookWindowsHookEx(g_hook);
}

我是显式调用的dll,代码大概长这样:

typedef BOOL(*PADD)(void);

HMODULE hDLL = LoadLibrary(L"KeyBoardHook.dll");
    if (hDLL == NULL) return 0;
    PADD pAdd = (PADD)GetProcAddress(hDLL, "InstallHook"); 
    pAdd();

就是这段代码,放到MFC里就能跑,放到空项目里就会变得卡顿,也没有日志被生成.
到底是为啥呢?求解答!

【以下回答由 GPT 生成】

在空项目中使用键盘钩子可能会导致程序崩溃的原因是缺少一个消息循环。MFC项目中已经包含了一个消息循环(通过调用CWinApp::Run()),因此可以正常工作。但在空项目中,你需要手动添加一个消息循环来处理系统消息。

为了解决这个问题,你可以在空项目中添加一个消息循环。以下是具体的解决方案:

  1. 创建一个while循环,在循环中调用GetMessage函数来获取消息队列中的消息,并将消息传递给消息处理函数。
  2. 在消息处理函数中处理你需要的消息,例如键盘按键消息。
  3. 重复第1步和第2步直到程序结束。

下面是示例代码:

int main()
{
    // 其他代码...

    // 添加消息循环
    MSG msg;
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    return 0;
}

通过添加消息循环,你的程序应该能够正常使用键盘钩子了。

注意: 对于Windows应用程序,通常建议使用Win32窗口程序(包括MFC应用程序),而不是空项目,因为Win32窗口程序已经包含了必要的消息循环和其他功能。



【相关推荐】



如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

问题在于,空项目时你只是在窗体注册了钩子,却没有运行keyboardHook()函数。