DLGCBR32 Sample: Demonstrates Adding a Status Bar and Toolbar to Dialog Boxes

The DLGCBR32 sample demonstrates how to add a status bar and a toolbar to a dialog box. In addition, it shows a number of techniques related to using a modeless dialog box as the main window of an MFC application.

In an MFC application, you can attach control bars such as status bars and toolbars to a frame window. However, for many applications a simple dialog box-based user interface is sufficient. MFC does not provide built-in support for adding control bars to dialog boxes.

Security noteSecurity Note

This sample code is intended to illustrate a concept, and it shows only the code that is relevant to that concept. It may not meet the security requirements for a specific environment, and it should not be used exactly as shown. We recommend that you add security and error-handling code to make your projects more secure and robust. Microsoft provides this sample code "AS IS" with no warranties.

To get samples and instructions for installing them:

To access samples from Visual Studio

  • On the Help menu, click Samples.

    By default, these samples are installed in drive:\Program Files\Microsoft Visual Studio 10.0\Samples\.

  • For the most recent version of this sample and a list of other samples, see Visual Studio Samples on the MSDN Web site.

Building and Running the Sample

To build and run the DLGCBR32 sample

  1. Open the solution Dlgcbr32.sln.

  2. On the Build menu, click Build.

  3. On the Debug menu, click Start Without Debugging.

Adding a Control Bar to a Dialog Box

To add a control bar to a dialog box, create the control bar as usual, and then make room for the control bar within the client area of the dialog box. For the control bar to function properly, the dialog box must duplicate some of the functionality of a frame window. If you want ON_UPDATE_COMMAND_UI handlers to work for the control bars, you also need to derive new control bar classes and handle the WM_IDLEUPDATECMDUI message. If your dialog box is not the main window of your application, you will also need to modify its parent frame window to pass the WM_IDLEUPDATECMDUI message on to the dialog box's control bars.

To make room for a control bar within the client area of the dialog box, follow these steps in your dialog box's OnInitDialog function:

  1. Create the control bars. Figure out how much room the control bars will take by using the reposQuery option of RepositionBars.

    CRect rcClientStart;
    CRect rcClientNow;
    GetClientRect(rcClientStart);
    RepositionBars(AFX_IDW_CONTROLBAR_FIRST,
                   AFX_IDW_CONTROLBAR_LAST,
                   0, reposQuery, rcClientNow);
    
  2. Move the controls in your dialog box to account for the space used by control bars at the top or left of the client area. If your dialog box contains a menu, you also need to account for the space used by the menu.

    CPoint ptOffset(rcClientNow.left - rcClientStart.left,
                    rcClientNow.top - rcClientStart.top);
    CRect rcChild;
    CWnd* pwndChild = GetWindow(GW_CHILD);
    while (pwndChild)
        {
           pwndChild->GetWindowRect(rcChild);
           ScreenToClient(rcChild);
           rcChild.OffsetRect(ptOffset);
           pwndChild->MoveWindow(rcChild, FALSE);
           pwndChild = pwndChild->GetNextWindow();
        }
    
  3. Increase the dialog box window dimensions by the amount of space used by the control bars.

    CRect rcWindow;
    GetWindowRect(rcWindow);
    rcWindow.right += rcClientStart.Width() - rcClientNow.Width();
    rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();
    MoveWindow(rcWindow, FALSE);
    
  4. Position the control bars using RepositionBars.

To update the first pane of a status bar with menu item text, you must handle WM_MENUSELECT, WM_ENTERIDLE, WM_SETMESSAGESTRING, and WM_POPMESSAGESTRING in your dialog box class. You need to duplicate the functionality of the CFrameWnd handlers for these messages. See the CModelessMain class in the sample program for examples of these message handlers.

To display tooltips for the toolbar buttons, it is necessary to handle the TTN_NEEDTEXTW and TTN_NEEDTEXTA notifications.

To allow ON_UPDATE_COMMAND_UI handlers to work for other status bar panes and for toolbar buttons, you must derive new control bar classes and implement a message handler for WM_IDLEUPDATECMDUI. This is necessary because the default control bar implementations of OnUpdateCmdUI assume the parent window is a frame window. However, OnUpdateCmdUI does not do anything but pass the parent-window pointer to a function that requires only a CCmdTarget pointer. Therefore, you can temporarily tell OnUpdateCmdUI that the parent-window pointer you are giving it is a CFrameWnd pointer to meet the compiler requirements. For example:

LRESULT CDlgToolBar::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM lParam)
{
   if (IsWindowVisible())
   {
      CFrameWnd* pParent = (CFrameWnd*)GetParent();
      if (pParent)
         OnUpdateCmdUI(pParent, (BOOL)wParam);
   }
   return OL;
}

To pass WM_IDLEUPDATECMDUI messages on to dialog boxes other than the main window, save dialog pointers in your frame window class and create a WM_IDLEUPDATECMDUI handler in that class. The handler should send the WM_IDLEUPDATECMDUI message on to the dialog child windows by using CWnd::SendMessageToDescendants. Then perform default processing for the message within the frame window.

Note

Some samples, such as this one, have not been modified to reflect the changes in the Visual C++ wizards, libraries, and compiler, but still demonstrate how to complete your desired task.

See Also

Other Resources

MFC Samples