Reputation: 597
I have a very old application and I'm surprised. This application runs without message loop. (GetMessage or PeekMessage).
How is it possible?
Edited example from 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;
}
DEBUG OUTPUT:
Create called. User called. Destroy called. The program '[2152] Test.exe: Native' has exited with code 0 (0x0).
Upvotes: 3
Views: 1493
Reputation: 70126
That is expected behavior.
CreateWindow
calls SendMessage
to send WM_NCCREATE
and WM_CREATE
to the window being created. SendMessage
behaves as follows (quote from MSDN):
If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine.
Your program calls CreateWindow
, which subsequently calls your window procedure (outputting "Create called" upon WM_CREATE
) and then returns. It verifies that the window handle is non-null, which is the case, and returns with an exit code of 0 instead of entering a message pump.
It does not output "Destroy called" (as you maybe expected) because that isn't happening. The window is not being destroyed (well, eventually it is, by the operating system), the program just exits.
About the edited code:
The new code differs in calling SendMessageW
, which again calls the window procedure directly. Therefore, the user message is received although there is no message pump.
It seems like the destroy message now makes it through, too, which is admittedly a bit surprising. Not sure what the reason for that would be.
Note that the window was created with an "A" function, so calling a "W" function is generally not advisable (even though it seems to "work" here).
Upvotes: 4