Saturday, September 20, 2008

Messages and Message Queues

Summary of link http://msdn.microsoft.com/en-us/library/ms644927(VS.85).aspx

There are two kinds of messages

1. Queued Messages

a. A message queue is a first-in, first-out queue, a system-defined memory object that temporarily stores messages, and sending messages directly to a window procedure.

b. Messages posted to a message queue are called queued messages. They are primarily the result of user input entered through the mouse or keyboard. Other queued messages include the timer, paint, and quit messages.

c. The system maintains a single system message queue and one thread-specific message queue for each graphical user interface (GUI) thread. To avoid the overhead of creating a message queue for non–GUI threads, all threads are created initially without a message queue. The system creates a thread-specific message queue only when the thread makes its first call to one of the User or Windows Graphics Device Interface (GDI) functions.

d. Whenever the user moves the mouse, clicks the mouse buttons, or types on the keyboard, the device driver for the mouse or keyboard converts the input into messages and places them in the system message queue. The system removes the messages, one at a time, from the system message queue, examines them to determine the destination window, and then posts them to the message queue of the thread that created the destination window.

e. A thread's message queue receives all mouse and keyboard messages for the windows created by the thread. The thread removes messages from its queue and directs the system to send them to the appropriate window procedure for processing.

2. Queued Messages

Nonqueued messages are sent immediately to the destination window procedure, bypassing the system message queue and thread message queue.

Handling of messages

1. A single-threaded application usually uses a message loop in its WinMain function to remove and send messages to the appropriate window procedures for processing.

2. Applications with multiple threads can include a message loop in each thread that creates a window.

3. Only one message loop is needed for a message queue, even if an application contains many windows.

Window Procedure

1. A window procedure is a function that receives and processes all messages sent to the window. Every window class has a window procedure, and every window created with that class uses that same window procedure to respond to messages.

2. Each window has a function, called a window procedure, that the system calls whenever it has input for the window. The window procedure processes the input and returns control to the system.

The sample "Hello World" program would help understand a few concepts



HINSTANCE hinst;
HWND hwndMain;

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
BOOL bRet;
WNDCLASS wc;
UNREFERENCED_PARAMETER(lpszCmdLine);

// Register the window class for the main window.

if (!hPrevInstance)
{
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon((HINSTANCE) NULL,
IDI_APPLICATION);
wc.hCursor = LoadCursor((HINSTANCE) NULL,
IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "MainMenu";
wc.lpszClassName = "MainWndClass";

if (!RegisterClass(&wc))
return FALSE;
}

hinst = hInstance; // save instance handle

// Create the main window.

hwndMain = CreateWindow("MainWndClass", "Sample",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, (HWND) NULL,
(HMENU) NULL, hinst, (LPVOID) NULL);

// If the main window cannot be created, terminate
// the application.

if (!hwndMain)
return FALSE;

// Show the window and paint its contents.

ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);

// Start the message loop.

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

// Return the exit code to the system.

return msg.wParam;
}

LRESULT CALLBACK MainWndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam) // second message parameter
{

switch (uMsg)
{
case WM_CREATE:
// Initialize the window.
return 0;

case WM_PAINT:
// Paint the window's client area.
return 0;

case WM_SIZE:
// Set the size and position of the window.
return 0;

case WM_DESTROY:
// Clean up window-specific data objects.
return 0;

//
// Process other messages.
//

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}

No comments: