CDialogImpl, CAxDialogImpl, and CSimpleDialog

[Previous] [Next]

ATL provides classes that support implementing and using modal and modeless dialog boxes. Depending on the level of interaction you need with the dialog box and the type of controls contained in it, you can choose from one of three classes: CDialogImpl, CAxDialogImpl, and CSimpleDialog. A brief description of each follows.


This class is used as a base class for implementing a modal or modeless dialog box. CDialogImpl provides a dialog box procedure that routes messages to the default message map in your derived class. ActiveX controls are not supported in the dialog box.


This class is also used as a base class for implementing a modal or modeless dialog box. CAxDialogImpl provides a dialog box procedure that routes messages to the default message map in your derived class. ActiveX controls are supported in the dialog box.

The ATL Object Wizard supports adding a CAxDialogImpl-derived class to your project and generates a dialog resource to go with it.


This class implements a modal dialog box given the resource ID of the dialog box as a template parameter. CSimpleDialog has a predefined message map that handles known commands such as IDOK and IDCANCEL, either of which will close the dialog box. CSimpleDialog is used for dialog boxes that are simply displayed and then closed by the user, such as an About box.

Implementing a Dialog Box

The easiest way to create a new dialog box is to use the ATL Object Wizard. Under the category Miscellaneous, you'll see the icon for inserting a dialog box. Running the wizard generates a new class derived from CAxDialogImpl and adds a new dialog resource to your project. Because the class is derived from CAxDialogImpl, it can contain Windows controls and ActiveX controls.

By default, the dialog box is set up for modal use. This is evident in the following implementation of the IDOK and IDCANCEL command handlers:

 LRESULT OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl,     BOOL& bHandled) {     EndDialog(wID);     return 0; } LRESULT OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl,     BOOL& bHandled) {     EndDialog(wID);     return 0; } 

EndDialog is used only for modal dialog boxes. To make this dialog box modeless, you need to modify the existing code to call DestroyWindow instead of EndDialog.

You can add message handlers to the dialog box for Windows controls by right-clicking on the dialog box class in ClassView and choosing Add Windows Message Handler from the context menu, or by right-clicking in the dialog resource in the resource editor and choosing Events from the context menu. You can also use the same procedure to add event handlers for ActiveX controls contained in the dialog box. To see how this is done, let's insert the MS Calendar control in a dialog box and handle an event from it in our derived class. The following steps assume you've already used the Object Wizard to insert a dialog box into your project.

  1. Open the dialog resource in the resource editor, and right-click in the dialog box to bring up the context menu. Choose Insert ActiveX Control from the menu.
  2. Choose Calendar Control from the list, and click OK, which inserts the control into the dialog box. You might need to resize the dialog box to make everything fit. The resulting dialog box should look something like the one shown here:
  3. Right-click on the dialog box, and choose Events from the menu. When the message and event handlers dialog box appears, click on IDC_CALENDAR1 in the lower right-hand list box to see the events that the calendar control can fire.
  4. We'd like to handle the NewMonth event, so click on NewMonth in the list box on the left to select it and then click the Add Handler button. Accept the default method name for the handler.

ATL creates an event sink for the calendar control in the dialog box header file, as shown here:

     VOID _ _stdcall OnNewMonthCalendar1()     {         // TODO : Add Code for event handler.     } public : BEGIN_SINK_MAP(CMyDialog)     // Make sure the Event Handlers have _ _stdcall calling     //  convention     SINK_ENTRY(IDC_CALENDAR1, 0x3, OnNewMonthCalendar1) END_SINK_MAP() 

We won't get any events, however, unless we tell the control about our event sink by advising it. We can use the AtlAdviseSinkMap function to advise all controls that we're sinking events from. In this case, it's only the one control. We can do the advise in the existing WM_INITDIALOG handler and add a WM_DESTROY handler to do the unadvise. The finished functions are shown here:

 LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam,     BOOL& bHandled) {     HRESULT hr = AtlAdviseSinkMap(this, TRUE);     _ASSERTE(SUCCEEDED(hr));     return 1;  // Let the system set the focus. } LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam,     BOOL& bHandled) {     AtlAdviseSinkMap(this, FALSE);     bHandled = FALSE;     return 1; } 

As written, the event handler for OnNewMonth doesn't do anything. Let's add some code to the event handler to read the Month property from the control itself, so we at least know what the month has changed to. Note that ATL has imported the calendar control at the top of the dialog box header file; we can use the interfaces on the control directly. To find out which interfaces and methods are supported, you can use the OLE View utility. Doing so reveals that the control implements an ICalendar interface, which has a Month property we can read. We can get an ICalendar interface pointer for the control using the GetDlgControl function. GetDlgControl retrieves an interface pointer for a contained control based on the control ID. Here's the event handler code:

 VOID _ _stdcall OnNewMonthCalendar1() {     CComPtr<ICalendar> spCal;     HRESULT hr = GetDlgControl(IDC_CALENDAR1, IID_ICalendar,         (void**)&spCal);     if(SUCCEEDED(hr))     {         short month = 0;         hr = spCal->get_Month(&month);         if(SUCCEEDED(hr))             ATLTRACE(_T("Month Change: %d\n"), month);     } } 

The event handler now outputs a trace message that displays the current month when the month changes.

Using a Dialog Box

Creating a dialog box in ATL is probably exactly what you would expect. You can run a modeless dialog box by simply instantiating your dialog box class and calling DoModal, like this:

 #include "mydialog.h"  CMyDialog dlg; dlg.DoModal(); 

The dialog box window is destroyed when EndDialog is called, typically from the IDOK and IDCANCEL command handlers in your dialog box class. The ATL Object Wizard generates this type of dialog box by default. For simple dialog boxes, you can create a dialog box with only a dialog template. There's no reason to derive a class from CDialogImpl or CAxDialogImpl if you just want to get an OK/cancel or yes/no confirmation. You specify the dialog resource as a template parameter to CSimpleDialog, as shown here:

 CSimpleDialog<IDD_MYABOUTBOX> dlgAbout; dlgAbout.DoModal(); 

CSimpleDialog has a second BOOL template parameter (not shown here) that controls centering of the dialog box. The dialog box is centered by default. DoModal also takes a parameter that specifies the parent window handle, which defaults to the current active window.

A modeless dialog box is created using the Create method and typically destroys its window by calling DestroyWindow in the IDOK and IDCANCEL handlers. The following code shows how to create a modeless dialog box from your WinMain function:

 #include "mydialog.h"  CMyDialog dlg; dlg.Create(::GetDesktopWindow()); dlg.ShowWindow(SW_SHOWNORMAL); MSG msg; while (GetMessage(&msg, 0, 0, 0))     DispatchMessage(&msg); 

Inside Atl
Inside ATL (Programming Languages/C)
ISBN: 1572318589
EAN: 2147483647
Year: 1998
Pages: 127 © 2008-2017.
If you may any questions please contact us: