我有一个非常古老的应用程序,我很惊讶。 此应用程序运行没有消息循环。 ( GetMessage或PeekMessage )。
这怎么可能?
从Visual Studio编辑的例子:
HINSTANCE g_hInstance = NULL; LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); ATOM _RegisterClass(HINSTANCE hInstance); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); _RegisterClass(hInstance); InitInstance(hInstance, SW_NORMAL); return 0; } ATOM _RegisterClass(HINSTANCE hInstance) { WNDCLASSEXA wcex = {0}; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_SAVEBITS; wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.lpszClassName = "TEST_CLASS"; ATOM a = 0; a = RegisterClassExA(&wcex); return a; } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; g_hInstance = hInstance; // Store instance handle in our global variable hWnd = CreateWindowA("TEST_CLASS", "TEST_WINDOW", WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } SendMessageW(hWnd, WM_USER, 111, 0); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_CREATE: OutputDebugStringA("Create called.\n"); break; case WM_USER: { if (wParam == 111) { OutputDebugStringA("User called.\n"); } } break; case WM_DESTROY: OutputDebugStringA("Destroy called.\n"); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
debugging输出:
创build调用。 用户呼叫。 消灭叫。 程序“[2152] Test.exe:Native”已退出,代码为0(0x0)。
这是预期的行为。
CreateWindow
调用SendMessage
将WM_NCCREATE
和WM_CREATE
发送到正在创建的窗口。 SendMessage
行为如下(引自MSDN):
如果指定的窗口是由调用线程创建的,则窗口过程将立即作为子例程调用。
你的程序调用CreateWindow
,随后调用你的窗口过程(在WM_CREATE
输出“Create called”),然后返回。 它会验证窗口句柄是否为非空值,并返回0,而不是输入消息泵。
它不会输出“Destroy called”(因为你可能预料到),因为这没有发生。 这个窗口没有被破坏(好吧, 最后是操作系统),程序就退出了。
关于编辑的代码:
新的代码在调用SendMessageW
不同,它直接调用窗口过程。 因此,尽管没有消息泵,但用户消息仍被接收。
现在看来,摧毁的信息也是如此,这当然有点令人惊讶。 不知道这是什么原因。
请注意,该窗口是用“A”函数创建的,所以调用“W”函数通常是不可取的(即使它似乎“在这里工作”)。