user2120666
user2120666

Reputation: 597

Is possible run window application without message loop

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

Answers (1)

Damon
Damon

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

Related Questions