我有一个非常古老的应用程序,我很惊讶。此应用程序在没有消息循环的情况下运行。 (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;
}
调试输出:
创建调用。 用户调用。 销毁调用。 程序“[2152] Test.exe: Native”已退出,代码为 0 (0x0)。
最佳答案
这是预期的行为。
CreateWindow
调用SendMessage
将WM_NCCREATE
和WM_CREATE
发送到正在创建的窗口。 SendMessage
的行为如下(引自 MSDN):
If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine.
您的程序调用 CreateWindow
,它随后调用您的窗口过程(在 WM_CREATE
上输出“Create called”)然后返回。它验证窗口句柄是否为非空(情况确实如此),并以退出代码 0 返回,而不是进入消息泵。
它不会输出“Destroy called”(如您所料),因为这并没有发生。窗口没有被销毁(好吧,最终它被操作系统销毁),程序只是退出。
关于编辑后的代码:
新代码在调用 SendMessageW
时有所不同,它再次直接调用窗口过程。因此,虽然没有消息泵,但还是收到了用户消息。
似乎销毁消息现在也通过了,这确实有点令人惊讶。不确定这是什么原因。
请注意,窗口是使用“A”函数创建的,因此通常不建议调用“W”函数(即使它在这里似乎“有效”)。
关于c - 是否可以在没有消息循环的情况下运行窗口应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20075771/