不进入控制台应用程序上的 Windows GetMessage 循环

2022-01-11 00:00:00 windows console c++ getmessage

我想检测 C++ 中的按键,我需要使用 Windows 系统调用.所以,我做了一些研究,这就是我使用 Hooks 和 Message 得到的结果:

I want to detect keypress in C++ and i need to use Windows System Call. So, i did some research and this is what i got using Hooks and Message:

#include <Windows.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>

using namespace std;

LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
    if (code == HC_ACTION) {
        switch (wParam) {
        case WM_KEYDOWN:
            PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
            char c = char(MapVirtualKey(p->vkCode, MAPVK_VK_TO_CHAR));
            cout << c << endl;
        }
    }
    return CallNextHookEx(NULL, code, wParam, lParam);
}

int main() {    
    HHOOK HKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);

    MSG msg;
    BOOL bRet;

    while ((bRet = GetMessage(&msg, NULL, 0, 0)) > 0) {
        cout << "bRet = " << bRet << endl; // I want to do something here, but the program doesn't seem to go in here
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    UnhookWindowsHookEx(HKeyboard);
    return 0;
}

我的问题是为什么我的程序没有进入循环内部(而是停留在 GetMessage 函数上)?我需要它来设置几秒钟后终止的条件,那么我应该把条件放在哪里?我知道 GetMessage 函数读取 Message,但是当我按下键盘上的键时它仍然无法进入,并且回调函数工作正常.

My question is why my program doesn't go inside the loop(and instead stuck on GetMessage function)? I need it to set conditions to terminate after some seconds, so where should i put the conditions? I know the GetMessage function reads Message, but when i press keys on my keyboard it still not going in and the callback function works just fine.

推荐答案

事件被发布到活动窗口.控制台窗口由控制台子系统 csrss.exe 拥有,它接收事件,然后将它们转换为字符并将它们放入作为应用程序的 stdin 的控制台对象中.

The events are posted to the active window. Console windows are owned by the console subsystem, csrss.exe, and it receives the events, then translates them to characters and puts them in the console object which is your application's stdin.

如果你想用 Win32 GUI 方式处理事件,你应该使用 Win32 窗口(例如 RegisterClassCreateWindow),而不是控制台窗口.

If you want to process events the Win32 GUI way, you should use a Win32 window (e.g. RegisterClass and CreateWindow), not a console window.

如果您只想让回调在一段时间内工作,您可以使用可警报等待,例如 SleepExMsgWaitForMultipleObjects,它们接受超时.

If you just want the callbacks to work for a certain period of time, you can use an alertable wait such as SleepEx or MsgWaitForMultipleObjects, which accept a timeout.

相关文章