Creating Dynamic Dialog Boxes


A programmer typically creates a dialog box from resources, using GetNewDialog on the Mac or DialogBox on Windows. However, for this technique, I want to build the dialog boxes at run time. The example code available at <www.cuj.com/code> does this (see DialogMac.cpp and DialogWin.cpp), but here’s a brief overview of the steps.

On Windows, use the DialogBoxIndirect call to create the dialog box. The main difference between this call and DialogBox is that DialogBox takes a resource identifier, while DialogBoxIndirect uses a dialog template from memory.

The format of the dialog box template is documented in the MSDN library or can be found online. However, the templates have changed over time, and I’ve been unable to locate one that correctly specifies controls with extended styles. It’s possible to derive the format from trial and error, but this code is very difficult to debug — failing to get the template byte-for-byte correct will usually cause a crash, with no context information to work from.

Luckily, there’s an easier way: create a template just for the dialog header and specify zero controls for it. This makes an “empty” dialog. Then, in the dialog control procedure, wait for a WM_INITDIALOG message. When the message appears, just create the controls you want (in the desired tabbing order) using CreateWindowEx. In the example code, the dialog is created in DialogWin.cpp. Fill in the controls using the control-creation routines in ControlsWin.cpp. Because WM_INITDIALOG is delivered before the dialog is actually shown, but after its window has been created, you have a “last chance” opportunity to populate the dialog.

In the bad old days, Macintosh used to be similar. Using the Dialog Manager, it’s possible to build a DITL resource in memory and use it to create the dialog using NewDialog. If you’ve got an older code base, this may still be necessary. You can find examples of it on Apple’s developer website.

The newer Carbon Event model makes this a lot easier, as demonstrated in the accompanying code: create a window using CreateNewWindow, passing the kMovableModalWindowClass constant to get a window that “looks” like a modal dialog. Install any Carbon Event handlers you want on it (in the code, this is done in WindowMac.cpp’s CreatePlatformDialog routine). On OS 9, it’s necessary to create a root control for the window using CreateRootControl; this is unnecessary but harmless on OS X. Then populate the new window with controls in the same basic fashion as Windows (using the routines in ControlsMac.cpp), and call ShowWindow followed by RunAppModalLoopForWindow. This is done in DialogMac.cpp in the example code.

That’s it. Both platforms provide routines for things such as highlighting, selecting, and specifying default controls; look at Controls.h for some examples.