65.9K
CodeProject is changing. Read more.
Home

Implementing Modal Message Loops

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (4 votes)

Feb 28, 2000

viewsIcon

85580

An introduction to creating modal windows

SUMMARY

The phrase modal window is used to describe a message or dialog box, that pops up over an applications frame window. While the modal window is present the application window cannot be used. The system provides the following functions to allow the creation of modal windows: MessageBox, DialogBox, DialogBoxParam, DialogBoxIndirect and DialogBoxParamIndirect.

MORE INFORMATION

There are two aspects to the implementation of a modal window. First, the parent window must be disabled, so as to prevent user interaction. Second, the modal message loop - a modal window is implemented with its own message loop. A typical implementation might look something like this:

BOOL fDone;
INT  nResult;

int RunModalWindow(
  HWND hwndDialog,
  HWND hwndParent)
{
  if(hwndParent != NULL)
    EnableWindow(hwndParent,FALSE);

  MSG msg;
  
  for(fDone=FALSE;fDone;WaitMessage())
  {
    while(PeekMessage(&msg,0,0,0,PM_REMOVE))
    {
      if(msg.message == WM_QUIT)
      {
        fDone = TRUE;
        PostMessage(NULL,WM_QUIT,0,0);
        break;
      }

      if(!IsDialogMessage(hwndDlg,&msg))
      {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
      }
    }
  }

  if(hwndParent != NULL)
    EnableWindow(hwndParent,TRUE);

  DestroyWindow(hwndDialog);

  return nResult;
}

Note some important features of the loop:
The modal message loop cannot be terminated by calling PostQuitMessage as that function is used to terminate a UI thread. All windows owned by the thread must be destroyed. Thus, if WM_QUIT is picked up, it must be manually reposted.

The modal window is properly closed by calling a special function that sets a flag associated with the window. In the example code termination flag is fDone, and would usually be stored in a WindowLong. Usually a modal window also allows a return code - the example code uses nResult for this purpose.

Also note the order of the call to destroy the dialog and to enable the parent. The parent must be enabled before the dialog is destroyed, as disabled windows cannot recieve focus or activation. DestroyWindow will want to assign activation to a window - if the parent is disabled another top-level window will be chosen and activated - normally not the desired result.