









Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
The role of messages in windows-based applications, discussing system-defined and application-defined messages, message routing, and message handling. It covers message queues, message filtering, and the use of functions like getmessage, dispatchmessage, and sendmessage.
Typology: Study notes
1 / 16
This page cannot be seen from the preview
Don't miss anything!










Now we are able to create a mature windows application. We are already familiar with windows creation, registration, message receiving and Message dispatching processes. Here we will make our knowledge more real through practical work. Let’s make a full fledge window.
We will make a full fledge window application in four steps:
We write our own function RegisterAppWindow which will register the window and return true or false in case of success or failure.
bool RegisterAppWindow(HINSTANCE hInstance) {
/* Before registering class, we will have to fill the WNDCLASS structure. */
WNDCLASS wc; wc.style = 0; wc.lpfnWndProc=MyWindowProc; wc.cbClsExtra = 0; wc.cbWndExtra =0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, LoadCursor(IDC_ARROW)); wc.hbrBackground= (HBRUSH)GetStockObject(GRAY_BRUSH); wc.lpszMenuName=NULL; wc.lpszClassName=”MyFirstWindowClass”;
/* We have discussed almost all the parameters of WNDCLASS structure in our previous lecture. After filling the WNDCLASS structure, we will pass this as a reference to RegisterClass function. Because RegisterClass function take pointer to the structure WNDLCASS as a parameter. */
ATOM cAtom=RegisterClass(&wc);
if(!cAtom) { MessageBox(NULL,”Error Register Window Class”,” Virtual Uinversity”,0); return 0; }
return true; }//End of Function RegisterAppWindow
For Creation of window, we will use Win32 API CreateWindow. We have studied CreateWindow function in our previous lecture. Here we will use this function for creating window. For creating window and checking return values, we will define our own function InitApplication which will internally call CreateAppWindow and returns true or false. It will return true in case of success and false in case failure.
bool InitApplication(HINSTANCE hInstance) { HWND hWnd=NULL;
/* Call RegisterAppWindow Function and returns false if this function returns false because we need not to proceed forward unless our windows is not registered properly. */
if(!RegisterAppWindow(hInstance)) { return false; }
/* We already know that CreateWindow function returns handle to window, we will save this return handle in our hWnd variable. / hWnd = CreateWindow(“MyFirstWindowClass”,”Virtual Uinversity”, WS_OVERLAPPEDWINDOW|WS_VISIBLE, 100, 50, CW_USEDDEFAULT, CW_USEDDEFAULT, NULL, NULL, hInstance, //Optional or not used in Window 2000 or above NULL); /
The system passes input to a window procedure in the form of messages. Messages are generated by both the system and applications. The system generates a message at each input event — for example, when the user types, moves the mouse, or clicks a control such as a scroll bar. The system also generates messages in response to changes in the system brought about by an application, such as when an application changes the pool of system font resources or resizes one of its windows. An application can generate messages to direct its own windows to perform tasks or to communicate with windows in other applications.
The system sends a message to a window procedure with a set of four parameters:
The window handle identifies the window for which the message is intended. The system uses it to determine which window procedure should receive the message.
A message identifier is a named constant that identifies the purpose of a message. When a window procedure receives a message, it uses a message identifier to determine how to process the message. For example, the message identifier WM_PAINT tells the window procedure that the window's client area has changed and must be repainted.
Message parameters specify data or the location of data used by a window procedure when processing a message. The meaning and value of the message parameters depend on the message. A message parameter can contain an integer, packed bit flags, a pointer to a structure containing additional data, and so on. When a message does not use message parameters, they are typically set to NULL. A window procedure must check the message identifier to determine how to interpret the message parameters.
This section describes the two types of messages:
The system sends or posts a system-defined message when it communicates with an application. It uses these messages to control the operations of applications and to provide input and other information for applications to process. An application can also send or post system-defined messages. Applications generally use these messages to control the operation of control windows created by using pre-registered window classes.
Each system-defined message has a unique message identifier and a corresponding symbolic constant (defined in the software development kit (SDK) header files) that states the purpose of the message. For example, the WM_PAINT constant requests that a window paint its contents.
Symbolic constants specify the category to which system-defined messages belong. The prefix of the constant identifies the type of window that can interpret and process the message. Following are the prefixes and their related message categories.
Prefix Message category
ABM Application desktop toolbar
BM Button control
CB Combo box control
CBEM Extended combo box control
CDM Common dialog box
DBT Device
DL Drag list box
DM Default push button control
DTM Date and time picker control
EM Edit control
HDM Header control
HKM Hot key control
IPM IP address control
LB List box control
LVM List view control
MCM Month calendar control
PBM Progress bar
PGM Pager control
PSM Property sheet
RB Rebar control
SB Status bar window
SBM Scroll bar control
STM Static control
TB Toolbar
TBM Trackbar
TCM Tab control
TTM Tooltip control
TVM Tree-view control
UDM Up-down control
WM General window
The system can display any number of windows at a time. To route mouse and keyboard input to the appropriate window, the system uses message queues.
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.
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. 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.
With the exception of the WM_PAINT message, the system always posts messages at the end of a message queue. This ensures that a window receives its input messages in the proper first in, first out (FIFO) sequence. The WM_PAINT message, however, is kept in the queue and is forwarded to the window procedure only when the queue contains no other messages. Multiple WM_PAINT messages for the same window are combined into a single WM_PAINT message, consolidating all invalid parts of the client area into a single area. Combining WM_PAINT messages reduces the number of times a window must redraw the contents of its client area.
The system posts a message to a thread's message queue by filling an MSG structure and then copying it to the message queue.
Information in MSG includes:
typedef struct tagMSG {
HWND hWnd; UINT message; WPARAM wParam, LPARAM lParam, DWORD time, POINT pt
}MSG;
hWnd: The handle of the window for which the message is intended ( hWnd ) message : The message identifier ( message ) wParam: The two message parameters ( wParam and lParam ) lParam: The time the message was posted ( time ) time: The mouse cursor position ( pt )
A thread can post a message to its own message queue or to the queue of another thread by using the PostMessage or PostThreadMessage function.
An application can remove a message from its queue by using the GetMessage function.To examine a message without removing it from its queue, an application can use the PeekMessage function. This function fills MSG with information about the message.
After removing a message from its queue, an application can use the DispatchMessage function to direct the system to send the message to a window procedure for processing. DispatchMessage takes a pointer to MSG that was filled by a previous call to the GetMessage or PeekMessage function. DispatchMessage passes the window handle, the message identifier, and the two message parameters to the window procedure, but it does not pass the time the message was posted or mouse cursor position. An application can retrieve this information by calling the GetMessageTime and GetMessagePos functions while processing a message.
A thread can use the WaitMessage function to yield control to other threads when it has no messages in its message queue. The function suspends the thread and does not return until a new message is placed in the thread's message queue.
You can call the SetMessageExtraInfo function to associate a value with the current thread's message queue. Then call the GetMessageExtraInfo function to get the value associated with the last message retrieved by the GetMessage or PeekMessage function.
Nonqueued messages are sent immediately to the destination window procedure, bypassing the system message queue and thread message queue. The system typically sends nonqueued messages to notify a window of events that affect it. For example, when the user activates a new application window, the system sends the window a series of messages, including WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR. These messages notify the window that it has been activated, that keyboard input is being directed to the window, and that the mouse cursor has been moved within the borders of the window. Nonqueued messages can also result when an application calls certain system functions. For example, the system sends the WM_WINDOWPOSCHANGED message after an application uses the SetWindowPos function to move a window.
all top-level windows in the system. If the window handle is NULL, DispatchMessage does nothing with the message.
An application's main thread starts its message loop after initializing the application and creating at least one window. Once started, the message loop continues to retrieve messages from the thread's message queue and to dispatch them to the appropriate windows. The message loop ends when the GetMessage function removes the WM_QUIT message from the message queue.
Only one message loop is needed for a message queue, even if an application contains many windows. DispatchMessage always dispatches the message to the proper window; this is because each message in the queue is an MSG structure that contains the handle of the window to which the message belongs.
You can modify a message loop in a variety of ways. For example, you can retrieve messages from the queue without dispatching them to a window. This is useful for applications that post messages not specifying a window. You can also direct GetMessage to search for specific messages, leaving other messages in the queue. This is useful if you must temporarily bypass the usual FIFO order of the message queue.
An application that uses accelerator keys must be able to translate keyboard messages into command messages. To do this, the application's message loop must include a call to the TranslateAccelerator function. For more information about accelerator keys, see Keyboard Accelerators.
If a thread uses a modeless dialog box, the message loop must include the IsDialogMessage function so that the dialog box can receive keyboard input.
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.
The system sends a message to a window procedure by passing the message data as arguments to the procedure. The window procedure then performs an appropriate action for the message; it checks the message identifier and, while processing the message, uses the information specified by the message parameters.
A window procedure does not usually ignore a message. If it does not process a message, it must send the message back to the system for default processing. The window procedure does this by calling the DefWindowProc function, which performs a default action and returns a message result. The window procedure must then return this value as its own message result. Most window procedures process just a few messages and pass the others on to the system by calling DefWindowProc.
Because a window procedure is shared by all windows belonging to the same class, it can process messages for several different windows. To identify the specific window affected by the message, a window procedure can examine the window handle passed with a message.
An application can choose specific messages to retrieve from the message queue (while ignoring other messages) by using the GetMessage or PeekMessage function to specify a message filter. The filter is a range of message identifiers (specified by a first and last identifier), a window handle, or both. GetMessage and PeekMessage use a message filter to select which messages to retrieve from the queue. Message filtering is useful if an application must search the message queue for messages that have arrived later in the queue. It is also useful if an application must process input (hardware) messages before processing posted messages.
The WM_KEYFIRST and WM_KEYLAST constants can be used as filter values to retrieve all keyboard messages; the WM_MOUSEFIRST and WM_MOUSELAST constants can be used to retrieve all mouse messages.
Any application that filters messages must ensure that a message satisfying the message filter can be posted. For example, if an application filters for a WM_CHAR message in a window that does not receive keyboard input, the GetMessage function does not return. This effectively "hangs" the application.
Any application can post and send messages. Like the system, an application posts a message by copying it to a message queue and sends a message by passing the message data as arguments to a window procedure. To post messages, an application uses the PostMessage function. An application can send a message by calling the SendMessage , BroadcastSystemMessage , SendMessageCallback, SendMessageTimeout , SendNotifyMessage , or SendDlgItemMessage function.
An application typically posts a message to notify a specific window to perform a task. PostMessage creates an MSG structure for the message and copies the message to the message queue. The application's message loop eventually retrieves the message and dispatches it to the appropriate window procedure.
An application can post a message without specifying a window. If the application supplies a NULL window handle when calling PostMessage , the message is posted to the queue associated with the current thread. Because no window handle is specified, the application must process the message in the message loop. This is one way to create a message that applies to the entire application, instead of to a specific window.
Note that the receiving thread needs not yield control explicitly; calling any of the following functions can cause a thread to yield control implicitly.
To avoid potential deadlocks in your application, consider using the SendNotifyMessage or SendMessageTimeout functions. Otherwise, a window procedure can determine whether a message it has received was sent by another thread by calling the InSendMessage or InSendMessageEx function. Before calling any of the functions in the preceding list while processing a message, the window procedure should first call InSendMessage or InSendMessageEx. If this function returns TRUE, the window procedure must call the ReplyMessage function before any function that causes the thread to yield control.
Each message consists of a message identifier and two parameters, wParam and lParam. The message identifier is a unique value that specifies the message purpose. The parameters provide additional information that is message-specific, but the wParam parameter is generally a type value that provides more information about the message.
A message broadcast is simply the sending of a message to multiple recipients in the system. To broadcast a message from an application, use the BroadcastSystemMessage function, specifying the recipients of the message. Rather than specify individual recipients, you must specify one or more types of recipients. These types are applications, installable drivers, network drivers, and system-level device drivers. The system sends broadcast messages to all members of each specified type.
The system typically broadcasts messages in response to changes that take place within system-level device drivers or related components. The driver or related component broadcasts the message to applications and other components to notify them of the change. For example, the component responsible for disk drives broadcasts a message whenever the device driver for the floppy disk drive detects a change of media such as when the user inserts a disk in the drive.
The system broadcasts messages to recipients in this order: system-level device drivers, network drivers, installable drivers, and applications. This means that system-level device drivers, if chosen as recipients, always get the first opportunity to respond to a message. Within a given recipient type, no driver is guaranteed to receive a given message before
any other driver. This means that a message intended for a specific driver must have a globally-unique message identifier so that no other driver unintentionally processes it.
You can also broadcast messages to all top-level windows by specifying HWND_BROADCAST in the SendMessage , SendMessageCallback , SendMessageTimeout , or SendNotifyMessage function.
Applications receive messages through the window procedure of their top-level windows. Messages are not sent to child windows. Services can receive messages through a window procedure or their service control handlers.
Note System-level device drivers use a related, system-level function to broadcast system messages.
For Retrieving message from message queue we are going to write function which will have a message loop and TranslateMessage and DispatchMessage API’s will be enclosed in the message loop. We will call this function RunApplication.
int RunApplication() { MSG msg;
/Main Application Message Loop/
while(GetMessage (&msg, NULL, 0, 0) > 0) { /* translate virtual-key messages into character messages */
TranslateMessage (&msg);
/* dispatch message to windows procedure*/
DispatchMessage (&msg); }//End of Message Loop (while)
return (int)msg.wParam; }//End of RunApplication
This type of message loop, we will be using in our windows applications. Now we will create Window Message Procedure. This message procedure will have the same name as given in WNDLCASS structure.
Call InitApplication Function and returns false if this function returns false because we need not to proceed forward unless our windows is not registered and created properly. */
if(!InitApplication(hInstance)) { MessageBox(NULL,”Application could not be initialized properly”,”Virtual University”,MB_ICONHAND|MB_OK); return 0; }
/* Finally run the application until user press the close button and choose close from system menu. */
return RunApplication(); }
In this lecture, we have created a full fledge window application which has all the characteristics of standard windows application. For creating window, we registered window class with the attributes required. After successful registration we created window. For creating window we used CreateWindow API. In CreateWindow API we mentioned some of the Window styles. Window styles are used to create different styles of windows. In this lecture we have created overlapped window with additional style like WS_VISIBLE or we can use ShowWindow function with WS_SHOWNORMAL style. We have also discussed many of the other windows style and their behaviors in our previous lecture. And after successful creation of window we made message handling procedure. Our message handling procedure checks left mouse button and in response of this it shows message box which is written some text, and other message are let them passed to default message procedure. We also studied Massages routing, message dispatching, message filtering, messages deadlock, message sending and message posting. For message receiving and dispatching, we created message loop which get the messages from message Queue and dispatch these messages to message procedure. Finally we coded a running application which displays windows and on pressing a left mouse button it shows a message box.