Display a TopMost System Modal Message Box

From an Inactive Delphi Application

Group of IT experts in their office.
Getty Images/gilaxia

With desktop (Windows) applications, a message (dialog) box is used to alert the user of the application that some action needs to be taken, that some operation was completed or, in general, to get users' attention.

In Delphi, there are several ways of displaying a message to the user. You can either use any of the ready-made message displaying routines provided in the RTL, like ShowMessage or InputBox; or you can create your own dialog box (for reuse): CreateMessageDialog.

A common problem with all the above dialog boxes is that they require the application to be active to be displayed to the user. "Active" refers to when your application has the "input focus."

If you really want to grab the user's attention and stop them from doing anything else, you need to be able to display a system-modal topmost message box even when your application is not active.

System-Modal Top Most Message Box

Even though this might sound complicated, in actuality it really is not.

Since Delphi can easily access most of the Windows API calls, executing the "MessageBox" Windows API function will do the trick.

Defined in the "windows.pas" unit -- the one included by default in the uses clause of every Delphi form, the MessageBox function creates, displays, and operates a message box. The message box contains an application-defined message and title, along with any combination of predefined icons and push buttons.

Here's how the MessageBox is declared:

 function MessageBox(
   hWnd: HWND;
   lpText,
   lpCaption : PAnsiChar;
   uType : Cardinal) : integer;
 

The first parameter, hwnd, is the handle of the owner window of the message box to be created. if you create a message box while a dialog box is present, use a handle to the dialog box as the hWnd parameter.

The lpText and lpCaption specify the caption and the message text that is displayed in the message box.

Last is the uType parameter and is the most interesting. This parameter specifies the contents and behavior of the dialog box. This parameter can be a combination of various flags.

An Example: System Modal Warning Box when the System Date/Time Changes

Let's take a look at an example of creating a system modal topmost message box. You'll handle the Windows message that is dispatched to all the running applications when the system date/time changes -- for example using the "Date and Time Properties" Control Panel applet.

The MessageBox function will be called as:

   Windows.MessageBox(
     handle,
     'This is a system modal message'#13#10'from an inactive application',
     'A message from an inactive application!',
     MB_SYSTEMMODAL or MB_SETFOREGROUND or MB_TOPMOST or MB_ICONHAND) ;
 

The most important piece is the last parameter. The "MB_SYSTEMMODAL or MB_SETFOREGROUND or MB_TOPMOST" ensures the message box is system modal, top most and becomes the foreground window.

  • MB_SYSTEMMODAL flag ensures that the user must respond to the message box before continuing work in the window identified by the hWnd parameter.
  • MB_TOPMOST flag specifies that the message box should be placed above all non-topmost windows and should stay above them, even when the window is deactivated.
  • MB_SETFOREGROUND flag ensures that the message box becomes the foreground window.

Here is the full example code (TForm named "Form1" defined in unit "unit1"):

 unit Unit1;
 
 interfaceuses
   Windows, Messages, SysUtils, Variants, Classes,
   Graphics, Controls, Forms, Dialogs, ExtCtrls;
 
 type
   TForm1 = class(TForm)
   private
     procedure WMTimeChange(var Msg: TMessage) ; message WM_TIMECHANGE;
   public
     { Public declarations }
   end;
 
 var
   Form1: TForm1;
 
 implementation
 {$R *.dfm}
 
 procedure TForm1.WMTimeChange(var Msg: TMessage) ;
 begin
   Windows.MessageBox(
     handle,
     'This is a system modal message'#13#10'from an inactive application',
     'A message from an inactive application!',
     MB_SYSTEMMODAL or MB_SETFOREGROUND or MB_TOPMOST or MB_ICONHAND) ;
 end;
 
 end.
 

Try running this simple application. Make sure the application is minimized -- or at least that some other application is active. Run the "Date and Time Properties" Control Panel applet and change the system time. As soon as you hit the "Ok" button (on the applet) the system modal topmost message box from your inactive application will be displayed.