PMGuide - Messages and Message Queues: Difference between revisions
Created page with "The OS/2 operating system uses messages and message queues to communicate with applications and the windows belonging to those applications. This chapter explains how to create and use messages and message queues in PM applications. ==About Messages and Message Queues== Unlike traditional applications that take complete control of the computer's keyboard, mouse, and screen, PM applications must share these resources with other applications that are running at the sa..." |
|||
Line 13: | Line 13: | ||
===Messages=== | ===Messages=== | ||
A | A ''message'' is information, a request for information, or a request for an action to be carried out by a window in an application. | ||
action to be carried out by a window in an application. | |||
The operating system, or an application, sends or posts a message to a window | The operating system, or an application, sends or posts a message to a window | ||
Line 51: | Line 50: | ||
application forwards the message to the proper window. | application forwards the message to the proper window. | ||
A message contains two | A message contains two ''message parameters''—32-bit values that specify data or | ||
the location of data that a window uses when processing the message. The | the location of data that a window uses when processing the message. The | ||
meaning and value of a message parameter depend on the message. A message parameter | meaning and value of a message parameter depend on the message. A message parameter | ||
Line 59: | Line 58: | ||
identifier to determine how to interpret the message parameters. | identifier to determine how to interpret the message parameters. | ||
A | A ''queue message'' is a QMSG data structure that contains six data items, | ||
representing the window handle, message identifier, two message parameters, message time, | representing the window handle, message identifier, two message parameters, message time, | ||
and mouse-pointer position. The time and position are included because most | and mouse-pointer position. The time and position are included because most | ||
Line 67: | Line 66: | ||
and copying it to a message queue. | and copying it to a message queue. | ||
A | A ''window message'' consists of the window handle, the message identifier, and | ||
two message parameters. A window message does not include the message time and | two message parameters. A window message does not include the message time and | ||
mouse-pointer position, because most window messages are requests to perform a task | mouse-pointer position, because most window messages are requests to perform a task | ||
that is not related to the current time or mouse-pointer position. The operating | that is not related to the current time or mouse-pointer position. The operating | ||
system sends a window message by passing these values, as individual arguments, to a | system sends a window message by passing these values, as individual arguments, to a | ||
window procedure. | window procedure. | ||
===Message Queues=== | ===Message Queues=== |
Revision as of 03:19, 29 April 2025
The OS/2 operating system uses messages and message queues to communicate with applications and the windows belonging to those applications. This chapter explains how to create and use messages and message queues in PM applications.
About Messages and Message Queues
Unlike traditional applications that take complete control of the computer's keyboard, mouse, and screen, PM applications must share these resources with other applications that are running at the same time. All applications run independently and rely on the operating system to help them manage shared resources. The operating system does this by controlling the operation of each application, communicating with each application when there is keyboard or mouse input or when an application must move and size its windows.
Messages
A message is information, a request for information, or a request for an action to be carried out by a window in an application.
The operating system, or an application, sends or posts a message to a window so that the window can use the information or respond to the request.
There are three types of messages:
- User-initiated
- Application-initiated
- System-initiated
A user-initiated message is the direct result of a user action, such as selecting a menu item or pressing a key. An application-initiated message is generated by one window in the application to communicate with another window. System -initiated messages are generated by the interface as the indirect result of a user action (for example, resizing a window) or as the direct result of a system event (such as creating a window).
A message that requires an immediate response from a window is sent directly to the window by passing the message data as arguments to the window procedure. The window procedure carries out the request or lets the operating system carry out default processing for the message.
A message that does not require an immediate response from a window is :hp1.posted :ehp1. (the message data is copied) to the application's :hp1.message queue:ehp1.. The message queue is a storage area that the application creates to receive and hold its posted messages. Then, the application can retrieve a message at the appropriate time, sending it to the addressed window for processing.
Every message contains a :hp1.message identifier:ehp1., which is a 16-bit integer that indicates the purpose of the message. When a window processes a message, it uses the message identifier to determine what to do.
Every message contains a :hp1.window handle:ehp1., which identifies the window the message is for. The window handle is important because most message queues and window procedures serve more than one window. The window handle ensures that the application forwards the message to the proper window.
A message contains two message parameters—32-bit values that specify data or the location of data that a window uses when processing the message. The meaning and value of a message parameter depend on the message. A message parameter can contain an integer, packed bit flags, a pointer to a structure that contains additional data, and so forth. Some messages do not use message parameters and, typically, set the parameters to NULL. An application always checks the message identifier to determine how to interpret the message parameters.
A queue message is a QMSG data structure that contains six data items, representing the window handle, message identifier, two message parameters, message time, and mouse-pointer position. The time and position are included because most queue messages are input messages, representing keyboard or mouse input from the user. The time and position also help the application identify the context of the message. The operating system posts a queue message by filling the QMSG structure and copying it to a message queue.
A window message consists of the window handle, the message identifier, and two message parameters. A window message does not include the message time and mouse-pointer position, because most window messages are requests to perform a task that is not related to the current time or mouse-pointer position. The operating system sends a window message by passing these values, as individual arguments, to a window procedure.
Message Queues
Every PM application must have a :hp1.message queue:ehp1.. A message queue is the only means an application has to receive input from the keyboard or mouse. :hp1.Only applications that create message queues can create windows:ehp1..
An application creates a message queue by using the WinCreateMsgQueue function. This function returns a handle that the application can use to access the message queue. After an application creates a message queue, the system posts messages intended for windows in the application to that queue. The application can retrieve queue messages by specifying the message-queue handle in the WinGetMsg function. It also can examine messages, without retrieving them, by using the WinPeekMsg function. When an application no longer needs the message queue, it can destroy the queue by using the WinDestroyMsgQueue function.
One message queue serves all the windows in a thread. This means a queue can hold messages for several windows. A message specifies the handle of the window to which it belongs so the application can forward a message easily to the appropriate window. The message loop recognizes a NULL window handle and the message is processed within the message loop rather than passed to WinDispatchMessage. See the following figure for an example of an input-message processing loop.
An application that has more than one thread can create more than one message queue. The system allows one message queue for each thread. A message queue created by a thread belongs to that thread and has no connection to other queues in the application. When an application creates a window in a given thread, the system associates the window with the message queue in that thread. The system then posts all subsequent messages intended for that window to that queue.
:hp2.Note: :ehp2. The recommended way to structure PM applications is to have at least two threads and two message queues. The first thread and message queue control all the user-interface windows, and the second thread and message queue control all the object windows.
Several windows can use one message queue; it is important that the message queue be large enough to hold all messages that possibly can be posted to it. An application can set the size of the message queue when it creates the queue by specifying the maximum number of messages the queue can hold. The default maximum number of messages is 10.
To minimize queue size, several types of posted messages are not actually stored in a message queue. Instead, the operating system keeps a record in the queue of the message being posted and combines any information contained in the message with information from previous messages. Timer, semaphore, and paint messages are handled this way. For example, if more than one WM_PAINT message is posted, the operating system combines the :hp1.update regions :ehp1. for each into a single update region. Although there is no actual WM_PAINT message in the queue, the operating system constructs one WM_PAINT message with the single update region when an application uses the WinGetMsg function.
The operating system handles mouse and keyboard input messages differently from the way it handles other types of messages. The operating system receives all keyboard and mouse events, such as keystrokes and mouse movements, into the system message queue. The operating system converts these events into messages and posts them, one at a time, to the appropriate application message queue. The application retrieves the messages from its queue and dispatches them to the appropriate window, which processes the messages.
The operating system message queue usually is large enough to hold all input messages, even if the user types or moves the mouse very quickly. If the operating system message queue does run out of space, the system :hp1.ignores :ehp1. the most recent keyboard input (usually by beeping to indicate the input is ignored) and collects mouse motions into a WM_MOUSEMOVE message.
Every message queue has a corresponding MQINFO data structure that specifies the identifiers of the process and thread that own the message queue and gives a count of the maximum number of messages the queue can receive. An application can retrieve the structure by using the WinQueryQueueInfo function.
A message queue also has a current status that indicates the types of messages currently in the queue. An application can retrieve the queue status by using the WinQueryQueueStatus function. An application also can use the WinPeekMsg function to examine the contents of a message queue. WinPeekMsg checks for a specific message or range of messages in the queue and gives the application the option of removing messages from the queue. An application :hp1.can :ehp1. call the WinQueryQueueStatus function to determine the contents of the queue before calling the WinPeekMsg or WinGetMsg function to remove a message from the queue.
Message Handling
To handle and process messages, an application can use a :hp1.message loop :ehp1. and the :hp1. window procedure:ehp1.. These terms are explained in the following two sections.
Message Loops
Every application with a message queue is responsible for retrieving the messages from that queue. An application can do this by using a message loop, usually in the application's main function, that retrieves messages from the message queue and dispatches them to the appropriate windows. The message loop consists of two calls: one to the WinGetMsg function; the other to the WinDispatchMsg function. The message loop has the following form:
HAB hab; QMSG qmsg; while (WinGetMsg(hab, &qmsg, NULL, 0, 0)) WinDispatchMsg(hab, &qmsg);
An application starts the message loop after creating the message queue and at least one application window. Once started, the message loop continues to retrieve messages from the message queue and to dispatch (send) them to the appropriate windows. WinDispatchMsg sends each message to the window specified by the window handle in the message.
The following figure illustrates the typical routing of an input message through the operating system's and application's message loops.
Mouse ───┐ ┌─── Keystrokes � � ┌─┴───┴─┐ ├───────┤ System ├───────┤ Event (time ordered) ├───────┤ Queue └───┬───┘ │ � ┌────┴───┐ │ Input │ Scancode ┌�─────┤ Router │ Translation │ └────────┘ � ┌───────┴──────┐ │ Message │ Accelerator │ Preprocessor │ Key Translation └───────┬──────┘ ┌─ ── ─ ── ── ── ── ── ── ── ─┐ ┌───┴───┐ │ ├───────┤ Appl Priority │ ├───────┤ MssgQ Ordered │ ├───────┤ │ └───┬───┘ │ └────────┐ │ │ ┌────── ┴─WinGetMsgQ │ � WinDispatchMsg │ │ │ │ App's │ � │ Message │ Window Procedure │ Loop │ │ │ │ � │ └�───────────return; └─ ── ── ── ── ── ── ── ── ── ─┘
Input Message Processing Loop Only one message loop is needed for a message queue, even if the queue contains messages for more than one window. Each queue message is a QMSG structure that contains the handle of the window to which the message belongs. WinDispatchMsg always dispatches the message to the proper window. WinGetMsg retrieves messages from the queue in first-in, first-out (FIFO) order, so the messages are dispatched to windows in the same order they are received.
If there are no messages in the queue, the operating system temporarily stops processing the WinGetMsg function until a message arrives. This means that processor time that, otherwise, would be spent waiting for a message can be given to the applications (or threads) that do have messages in their queues.
The message loop continues to retrieve and dispatch messages until WinGetMsg retrieves a WM_QUIT message. This message causes the function to return FALSE, terminating the loop. In most cases, terminating the message loop is the first step in terminating the application. An application can terminate its own loop by posting the WM_QUIT message in its own queue.
An application can modify its message loop in a variety of ways. For example, it can retrieve messages from the queue without dispatching them to a window. This is useful for applications that post messages without specifying a window. (These messages apply to the application rather than a specific window; they have NULL window handles.) Also, an application can direct the WinGetMsg function to search for specific messages, leaving other messages in the queue. This is useful for applications that temporarily need to bypass the usual FIFO order of the message queue.