Jump to content

Message loop in Microsoft Windows

From Wikipedia, the free encyclopedia

This is an old revision of this page, as edited by Jarble (talk | contribs) at 00:48, 6 May 2021 (linking). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

The message loop is an obligatory section of code in every program that uses a graphical user interface under Microsoft Windows. Windows programs that have a GUI are event-driven. Windows maintains an individual message queue for each thread that has created a window. Usually only the first thread creates windows. Windows places messages into that queue whenever mouse activity occurs on that thread's window, whenever keyboard activity occurs while that window has focus, and at other times. A process can also add messages to its own queue. To accept user input, and for other reasons, each thread with a window must continuously retrieve messages from its queue, and act on them. A programmer makes the process do that by writing a loop that calls GetMessage (which blocks for a message and retrieves it), and then calls DispatchMessage (which dispatches the message), and repeats indefinitely. This is the message loop. There usually is a message loop in the main program, which runs on the main thread, and additional message loop in each created modal dialog. Messages for every window of the process pass through its message queue, and are handled by its message loop. A message loop is one kind of event loop.

A basic message loop appears as follows:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    BOOL bRet;

    while (1)
    {
        bRet = GetMessage(&msg, NULL, 0, 0);

        if (bRet > 0)  // (bRet > 0 indicates a message that must be processed.)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else if (bRet < 0)  // (bRet == -1 indicates an error.)
        {
            // Handle or log the error; possibly exit.
            // ...
        }
        else  // (bRet == 0 indicates "exit program".)
        {
            break;
        }
    }
    return msg.wParam;
}

It is conventional for the event loop to call TranslateMessage on each message which can translate virtual keystrokes into strings. Calling TranslateMessage is not technically required, but problems can result if it is not called. The message loop must call DispatchMessage.

The message loop does not directly act on the messages that it handles. It dispatches them by calling DispatchMessage, which transfers the message to the "window procedure" for the window that the message was addressed to. (The "window procedure" is a callback procedure, which got associated with the window class when it was registered.) (More than one window can use the same window procedure.)

Code can also send messages directly to a window procedure. These are called nonqueued messages.

A strict message loop is not the only option. Code elsewhere in the program can also accept and dispatch messages. PeekMessage is a non-blocking call that returns immediately, with a message if any are waiting, or no message if none is waiting. WaitMessage allows a thread to sleep until a message is in the queue.

Modern graphical interface frameworks, such as Windows Forms, Windows Presentation Foundation, MFC, Delphi, Qt, and others do not require applications to code a Windows message loop, because they automatically route events such as key presses and mouse clicks to their appropriate handlers as defined within the framework. However, each framework implements a message loop somewhere, and the message loop can usually be accessed or replaced when more direct control is required.

See also