不进入控制台应用程序的 Windows GetMessage 循环
does not go inside the Windows GetMessage loop on console application
我想在 C++ 中检测按键,我需要使用 Windows 系统调用。所以,我做了一些研究,这就是我使用 Hooks 和 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,但是当我按下键盘上的键时它仍然没有进入并且回调函数工作正常。
这并不奇怪,您的线程队列中实际上没有任何消息,而且您没有 window,所以也没有 window 队列。
如果您想使用挂钩返回的值,请将代码放在挂钩回调函数中。
我应该警告你,像这样的钩子在控制台应用程序中不起作用,因为控制台 window 驻留在另一个进程中。此外,如果您查看 SetWindowsHookEx
的 MSDN 页面,您会发现 WH_KEYBOARD_LL
只是一个全局挂钩,即您必须将挂钩处理程序放入 DLL 库中并将挂钩注入其他应用程序。那你就得自己处理32/64位的问题了。
最后一点,当您在处理程序中说 cout << c;
时,将在进程的输出文件句柄 中打印 ,而不是您自己的。
活动已发布到活动 window。控制台 windows 由控制台子系统 csrss.exe 拥有,它接收事件,然后将它们转换为字符并将它们放入控制台对象中,该对象是应用程序的 stdin
.
如果您想以 Win32 GUI 方式处理事件,您应该使用 Win32 window(例如 RegisterClass
和 CreateWindow
),而不是控制台 window。
如果您只想让回调工作一段时间,您可以使用可提醒等待,例如 SleepEx
或 MsgWaitForMultipleObjects
,它们接受超时。
我想在 C++ 中检测按键,我需要使用 Windows 系统调用。所以,我做了一些研究,这就是我使用 Hooks 和 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,但是当我按下键盘上的键时它仍然没有进入并且回调函数工作正常。
这并不奇怪,您的线程队列中实际上没有任何消息,而且您没有 window,所以也没有 window 队列。
如果您想使用挂钩返回的值,请将代码放在挂钩回调函数中。
我应该警告你,像这样的钩子在控制台应用程序中不起作用,因为控制台 window 驻留在另一个进程中。此外,如果您查看 SetWindowsHookEx
的 MSDN 页面,您会发现 WH_KEYBOARD_LL
只是一个全局挂钩,即您必须将挂钩处理程序放入 DLL 库中并将挂钩注入其他应用程序。那你就得自己处理32/64位的问题了。
最后一点,当您在处理程序中说 cout << c;
时,将在进程的输出文件句柄 中打印 ,而不是您自己的。
活动已发布到活动 window。控制台 windows 由控制台子系统 csrss.exe 拥有,它接收事件,然后将它们转换为字符并将它们放入控制台对象中,该对象是应用程序的 stdin
.
如果您想以 Win32 GUI 方式处理事件,您应该使用 Win32 window(例如 RegisterClass
和 CreateWindow
),而不是控制台 window。
如果您只想让回调工作一段时间,您可以使用可提醒等待,例如 SleepEx
或 MsgWaitForMultipleObjects
,它们接受超时。