The Pianist
The Pianist

Reputation: 556

My Win32 application won't exit the main loop

This is my main loop:

    while(TRUE)
    {

    PeekMessage(&msg,hWnd,0,0,PM_REMOVE);
        if (msg.message==WM_QUIT)
            break;
        TranslateMessage(&msg);
        DispatchMessage(&msg);


    }

and this is my callback procedure:

 LRESULT CALLBACK WinProc(HWND hWnd,UINT msg1,WPARAM wParam,LPARAM lParam)
 {
    switch(msg1)
    {
        case WM_DESTROY  :
        {
            PostQuitMessage(0);
            return 0;
        }
        break;
    }

    return DefWindowProc(hWnd,msg1,wParam,lParam);
}

I found out that when I press Close button WM_NCLBUTTONDOWN will be returned by the PeekMessage function in the next loop, and no WM_QUIT!

Upvotes: 8

Views: 4539

Answers (3)

James
James

Reputation: 9278

Here's some code I found. It should give you something to work with.

    // Main message loop:
do
{
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    // Run game code here.
    gTradeApp->ExecuteNextAction();
}
while (msg.message != WM_QUIT);

and the WndProc

LRESULT CALLBACK WndProc(HWND aHWnd, UINT aMessage, WPARAM aWParam, LPARAM aLParam)
{
    switch (aMessage)
    {
    case WM_COMMAND:
        return HandleCommand(aHWnd, aMessage, aWParam, aLParam);

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(aHWnd, aMessage, aWParam, aLParam);
    }

    return 0;
}

Upvotes: 2

Orwell
Orwell

Reputation: 1518

I recommend sticking with this, to ensure errors (-1) returned by GetMessage can be handled properly:

while(GetMessage(&Msg, NULL, 0, 0) > 0) {
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
}

Also, another error is not handling WM_CLOSE properly. Try this instead to make your program actually listen to WM_CLOSE (the close button):

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
    switch(Message) {
        case WM_CLOSE: {
            DestroyWindow(hwnd); // this
            break;
        }
        case WM_DESTROY: {
            PostQuitMessage(0);
            break;
        }
        default:
            return DefWindowProc(hwnd, Message, wParam, lParam);
    }
    return 0;
 }

Upvotes: 0

user541686
user541686

Reputation: 210593

The correct way to do a message loop is

BOOL bRet;
MSG msg;
while ((bRet = GetMessage(&msg, hWnd, 0, 0)) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

You can use PeekMessage if you really need to... but why are you ignoring the return value?

Also, note that this is specific to a window. I believe PostQuitMessage is for a thread... I don't remember it off the top of my head, but you might need to pass NULL instead of hWnd.

If you have any other windows, that may hijack their message loop as well -- I don't think it's usually an issue, but it might potentially be one; keep that in mind.

Upvotes: 5

Related Questions