我无法从消息处理程序中正确运行消息循环。实际上复制 DialogBox() 处理消息的方式,减去所有窗口。
简单地从消息处理程序中调用 GetMessage() 几乎可以工作,除非打开系统菜单的 WM_SYSKEYDOWN 事件也触发进入子循环。在发生这种奇怪的事情之后,按键被吞下,与系统菜单相关的 WM_MOUSEMOVE 消息被发送到主窗口。
作为记录,这发生在 Windows 8 和 XP 中。
为了给出一些上下文,我正在尝试一个线程模型,其中(无窗口)工作线程通过阻塞 SendMessage 调用回作为服务器的主窗口进行通信。这些操作可能需要进一步的输入或依赖于其他 I/O,因此需要处理常规消息,直到准备好回复。
我相当肯定这是我的一个基本错误或误解,就像我上次在这里发帖一样,但我似乎无法完全弄清楚我自己做错了什么。
这是我的复制案例。按 ALT+SPACE 打开系统菜单后尝试导航,
#include <windows.h>
BOOL update;
LRESULT WINAPI WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
MSG msg;
char text[256];
switch(uMsg) {
case WM_DESTROY:
ExitProcess(0);
// Trigger an update on input
case WM_SYSKEYDOWN:
update = TRUE;
break;
// Display the update from the worker thread, returning once it is time to
// ask for the next one
case WM_USER:
wsprintf(text, TEXT("%u"), (unsigned int) lParam);
SetWindowText(hwnd, text);
while(!update && GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
update = FALSE;
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
DWORD WINAPI ThreadProc(void *hwnd) {
// Submit updates as quickly as possible
LONG sequence = 1;
for(;;)
SendMessage(hwnd, WM_USER, 0, sequence++);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCommandLine, int nCmdShow) {
HWND hwnd;
MSG msg;
// Create our window
WNDCLASS windowClass = { 0 };
windowClass.lpfnWndProc = WindowProc;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hCursor = NULL;
windowClass.lpszClassName = TEXT("Repro");
RegisterClass(&windowClass);
hwnd = CreateWindow(TEXT("Repro"), TEXT("Repro"),
WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
hInstance, 0);
// Launch the worker thread
CreateThread(NULL, 0, ThreadProc, hwnd, 0, NULL);
// And run the primary message loop
while(GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}