Using Messages and Message Queues
The following code examples demonstrate how to perform the following tasks associated with Windows messages and message queues.
Creating a Message Loop
The system does not automatically create a message queue for each thread. Instead, the system creates a message queue only for threads that perform operations which require a message queue. If the thread creates one or more windows, a message loop must be provided; this message loop retrieves messages from the thread’s message queue and dispatches them to the appropriate window procedures.
Because the system directs messages to individual windows in an application, a thread must create at least one window before starting its message loop. Most applications contain a single thread that creates windows. A typical application registers the window class for its main window, creates and shows the main window, and then starts its message loop — all in the WinMain function.
You create a message loop by using the GetMessage and DispatchMessage functions. If your application must obtain character input from the user, include the TranslateMessage function in the loop. TranslateMessage translates virtual-key messages into character messages. The following example shows the message loop in the WinMain function of a simple Windows-based application.
The following example shows a message loop for a thread that uses accelerators and displays a modeless dialog box. When TranslateAccelerator or IsDialogMessage returns TRUE (indicating that the message has been processed), TranslateMessage and DispatchMessage are not called. The reason for this is that TranslateAccelerator and IsDialogMessage perform all necessary translating and dispatching of messages.
Examining a Message Queue
Occasionally, an application needs to examine the contents of a thread’s message queue from outside the thread’s message loop. For example, if an application’s window procedure performs a lengthy drawing operation, you may want the user to be able to interrupt the operation. Unless your application periodically examines the message queue during the operation for mouse and keyboard messages, it will not respond to user input until after the operation has completed. The reason for this is that the DispatchMessage function in the thread’s message loop does not return until the window procedure finishes processing a message.
You can use the PeekMessage function to examine a message queue during a lengthy operation. PeekMessage is similar to the GetMessage function; both check a message queue for a message that matches the filter criteria and then copy the message to an MSG structure. The main difference between the two functions is that GetMessage does not return until a message matching the filter criteria is placed in the queue, whereas PeekMessage returns immediately regardless of whether a message is in the queue.
The following example shows how to use PeekMessage to examine a message queue for mouse clicks and keyboard input during a lengthy operation.
Other functions, including GetQueueStatus and GetInputState, also allow you to examine the contents of a thread’s message queue. GetQueueStatus returns an array of flags that indicates the types of messages in the queue; using it is the fastest way to discover whether the queue contains any messages. GetInputState returns TRUE if the queue contains mouse or keyboard messages. Both of these functions can be used to determine whether the queue contains messages that need to be processed.
Posting a Message
You can post a message to a message queue by using the PostMessage function. PostMessage places a message at the end of a thread’s message queue and returns immediately, without waiting for the thread to process the message. The function’s parameters include a window handle, a message identifier, and two message parameters. The system copies these parameters to an MSG structure, fills the time and pt members of the structure, and places the structure in the message queue.
The system uses the window handle passed with the PostMessage function to determine which thread message queue should receive the message. If the handle is HWND_TOPMOST, the system posts the message to the thread message queues of all top-level windows.
You can use the PostThreadMessage function to post a message to a specific thread message queue. PostThreadMessage is similar to PostMessage, except the first parameter is a thread identifier rather than a window handle. You can retrieve the thread identifier by calling the GetCurrentThreadId function.
Use the PostQuitMessage function to exit a message loop. PostQuitMessage posts the WM_QUIT message to the currently executing thread. The thread’s message loop terminates and returns control to the system when it encounters the WM_QUIT message. An application usually calls PostQuitMessage in response to the WM_DESTROY message, as shown in the following example.
Sending a Message
The SendMessage function is used to send a message directly to a window procedure. SendMessage calls a window procedure and waits for that procedure to process the message and return a result.
A message can be sent to any window in the system; all that is required is a window handle. The system uses the handle to determine which window procedure should receive the message.
Before processing a message that may have been sent from another thread, a window procedure should first call the InSendMessage function. If this function returns TRUE, the window procedure should call ReplyMessage before any function that causes the thread to yield control, as shown in the following example.
A number of messages can be sent to controls in a dialog box. These control messages set the appearance, behavior, and content of controls or retrieve information about controls. For example, the CB_ADDSTRING message can add a string to a combo box, and the BM_SETCHECK message can set the check state of a check box or radio button.
Use the SendDlgItemMessage function to send a message to a control, specifying the identifier of the control and the handle of the dialog box window that contains the control. The following example, taken from a dialog box procedure, copies a string from a combo box’s edit control into its list box. The example uses SendDlgItemMessage to send a CB_ADDSTRING message to the combo box.
WM_SHOWWINDOW message
Sent to a window when the window is about to be hidden or shown.
A window receives this message through its WindowProc function.
Parameters
Indicates whether a window is being shown. If wParam is TRUE, the window is being shown. If wParam is FALSE, the window is being hidden.
The status of the window being shown. If lParam is zero, the message was sent because of a call to the ShowWindow function; otherwise, lParam is one of the following values.
Value | Meaning |
---|---|
SW_OTHERUNZOOM 4 | The window is being uncovered because a maximize window was restored or minimized. |
SW_OTHERZOOM 2 | The window is being covered by another window that has been maximized. |
SW_PARENTCLOSING 1 | The window’s owner window is being minimized. |
SW_PARENTOPENING 3 | The window’s owner window is being restored. |
Return value
Type: LRESULT
If an application processes this message, it should return zero.
Remarks
The DefWindowProc function hides or shows the window, as specified by the message. If a window has the WS_VISIBLE style when it is created, the window receives this message after it is created, but before it is displayed. A window also receives this message when its visibility state is changed by the ShowWindow or ShowOwnedPopups function.
The WM_SHOWWINDOW message is not sent under the following circumstances:
- When a top-level, overlapped window is created with the WS_MAXIMIZE or WS_MINIMIZE style.
- When the SW_SHOWNORMAL flag is specified in the call to the ShowWindow function.
Show a popup/message box from a Windows batch file
Is there a way to display a message box from a batch file (similar to how xmessage can be used from bash-scripts in Linux)?
21 Answers 21
I would make a very simple VBScript file and call it using CScript to parse the command line parameters.
Something like the following saved in MessageBox.vbs :
Which you would call like:
MsgBox reference if you are interested in going this route.
First of all, DOS has nothing to do with it, you probably want a Windows command line solution (again: no DOS, pure Windows, just not a Window, but a Console).
You can either use the VBScript method provided by boflynn or you can mis-use net send or msg . net send works only on older versions of windows:
This also depends on the Messenger service to run, though.
For newer versions (XP and onward, apparently):
It should be noted that a message box sent using msg.exe will only last for 60 seconds. This can however be overridden with the /time:xx switch.
Might display a little flash, but no temp files required. Should work all the way back to somewhere in the (IIRC) IE5 era.
Don’t forget to escape your parentheses if you’re using if :
This will pop-up another Command Prompt window:
If you are using Windows XP’s command.com, this will open a message box.
Opening a new cmd window isn’t quite what you were asking for, I gather. You could also use VBScript, and use this with your .bat file. You would open it from the bat file with this command:
What this does is change the directory command.com will search for files from, then on the next line:
Then you create a new Notepad document, type in
You would then save this as a .vbs file (by putting «.vbs» at the end of the filename), save as «All Files» in the drop down box below the file name (so it doesn’t save as .txt), then click Save!
3) Here’s parameterized .bat/jscript hybrid (should be saved as bat ). It again uses JavaScript despite the OP request but as it is a bat it can be called as a bat file without worries. It uses POPUP which allows a little bit more control than the more popular MSGBOX. It uses WSH, but not MSHTA like in the example above.
4) and one jscript.net/.bat hybrid (should be saved as .bat ) .This time it uses .NET and compiles a small .exe file that could be deleted:
5) and at the end one single call to powershell that creates a pop-up (can be called from command line or from batch if powershell is installed):
6) And the dbenham’s approach seen here
7) For a system tray notifications you can try this:
WM_NOTIFY message
Sent by a common control to its parent window when an event has occurred or the control requires some information.
Parameters
The identifier of the common control sending the message. This identifier is not guaranteed to be unique. An application should use the hwndFrom or idFrom member of the NMHDR structure (passed as the lParam parameter) to identify the control.
A pointer to an NMHDR structure that contains the notification code and additional information. For some notification messages, this parameter points to a larger structure that has the NMHDR structure as its first member.
Return value
The return value is ignored except for notification messages that specify otherwise.
Remarks
The destination of the message must be the HWND of the parent of the control. This value can be obtained by using GetParent, as shown in the following example, where m_controlHwnd is the HWND of the control itself.
Applications handle the message in the window procedure of the parent window, as shown in the following example, which handles the notification message sent by the custom control in the previous example.
Some notifications, chiefly those that have been in the API for a long time, are sent as WM_COMMAND messages. For more information, see Control Messages.
If the message handler is in a dialog box procedure, you must use the SetWindowLong function with DWL_MSGRESULT to set a return value.
For Windows Vista and later systems, the WM_NOTIFY message cannot be sent between processes.
Many notifications are available in both ANSI and Unicode formats. The window sending the WM_NOTIFY message uses the WM_NOTIFYFORMAT message to determine which format should be used. See WM_NOTIFYFORMAT for further discussion.
Closing the Window
When the user closes a window, that action triggers a sequence of window messages.
The user can close an application window by clicking the Close button, or by using a keyboard shortcut such as ALT+F4. Any of these actions causes the window to receive a WM_CLOSE message. The WM_CLOSE message gives you an opportunity to prompt the user before closing the window. If you really do want to close the window, call the DestroyWindow function. Otherwise, simply return zero from the WM_CLOSE message, and the operating system will ignore the message and not destroy the window.
Here is an example of how a program might handle WM_CLOSE.
In this example, the MessageBox function shows a modal dialog that contains OK and Cancel buttons. If the user clicks OK, the program calls DestroyWindow. Otherwise, if the user clicks Cancel, the call to DestroyWindow is skipped, and the window remains open. In either case, return zero to indicate that you handled the message.
If you want to close the window without prompting the user, you could simply call DestroyWindow without the call to MessageBox. However, there is a shortcut in this case. Recall that DefWindowProc executes the default action for any window message. In the case of WM_CLOSE, DefWindowProc automatically calls DestroyWindow. That means if you ignore the WM_CLOSE message in your switch statement, the window is destroyed by default.
When a window is about to be destroyed, it receives a WM_DESTROY message. This message is sent after the window is removed from the screen, but before the destruction occurs (in particular, before any child windows are destroyed).
In your main application window, you will typically respond to WM_DESTROY by calling PostQuitMessage.
We saw in the Window Messages section that PostQuitMessage puts a WM_QUIT message on the message queue, causing the message loop to end.
Here is a flow chart showing the typical way to process WM_CLOSE and WM_DESTROY messages: