May 98 - Getting Started
Volume Number: 14
Issue Number: 5
Column Tag: Getting Started
Handling Modeless Dialogs
by Dave Mark
Looking deeper into the Dialog Manager
Over the last few columns, we've explored the mysteries of the Dialog Manager via a
program called Dialogger. As promised, the next few columns will go deeper into the
Dialog Manager, presenting a program called Modeless. Modeless implements a
modeless dialog, a dialog that looks and acts like a regular window, but retains the
benefits of being managed by the Dialog Manager.
Modeless dialogs require a change in the usual modal programming strategy. Modal
dialog handling code is usually pretty self-contained. Modeless code tends to be larger
and more spread out, as you'll see when we get to the code.
Creating the Modeless Resources
Most of the resources we'll need for this month's column can be copied from last
month's resource file, Dialogger.rsrc. Start by creating a new folder in your
Development folder named Modeless. Next, duplicate the file Dialogger.rsrc and drag
the copy into the Modeless folder. Change the name of this file to Modeless.rsrc.
Next, launch ResEdit by double-clicking the file Modeless.rsrc. The Modeless.rsrc
window should look similar to the one shown in Figure 1.
Figure 1. Modeless.n.rsrc, before surgery.
Your first mission is to edit the ALRT, replacing any references to Dialogger with the
appropriate reference to Modeless. Double-click on the ALRT icon. When the
ALRT-picker window appears, double-click the only ALRT listed, the one with a
resource ID of 129. When the ALRT editor appears, double-click the ALRT window so
the DITL editor appears. Finally, double-click the static text item and, when the static
text editor appears, make your changes. Mine are shown in Figure 2.
Figure 2. A new version of the About... ALRT.
When you're happy with your About message, close all the windows until you are back
at the main window. Next, you'll change the About Dialogger item in the Apple menu to
read About Modeless.
Double-click the MENU icon to bring up the MENU picker window. Next, double-click
the Apple MENU, bringing up the MENU editing window. Click the About Dialogge. item
and change it so it says About Modeless, as shown in Figure 3.
Figure 3. A new version of the MENU resource.
Close the Apple MENU editing window, then double-click the File menu, bringing up
the File MENU editing window. Click the Settings item and then click in the Cmd-key:
field. Type the letter S in the Cmd-key: field. This ties the command-key equivalent S
to the Settings item in the File menu. My File MENU editing window is shown in
Figure 4.
Figure 4. A new version of the File MENU resource.
Once you are done, close all the windows leaving just the main window open. Our final
chore is to edit the DLOG and DITL resources that made up Dialogger's modal dialog,
changing them to reflect the look of a modeless dialog.
Double-click the DLOG icon to bring up the DLOG-picker window. Next, double-click
the only DLOG listed, the one with the resource id of 128. The Settings DLOG editing
window should appear. First, click the Initially visible check box, making sure it is
unchecked.
Next, click the second window icon from the left, at the top of the editing window. The
DLOG window should change to reflect your new selection. Modeless dialogs don't have
the traditional double-border of their modal cousins. Instead, they look like regular
windows. In this case, we want to give our dialog window a close box, so make sure the
Close box check box is checked.
We also want to give our dialog window a title. Select Set 'DLOG' Characteristics from
the DLOG menu. When the 'DLOG' Characteristics dialog appears, type the text Fred
Settings in the Window title: field and click OK. Your new title should be reflected in
the DLOG editing window. Figure 5 shows my DLOG editing window at this point in the
process.
Figure 5. The DLOG editing window, at the half-way point.
Next, we'll edit the DITL associated with this DLOG. Double click the DLOG window
(within the editing window) so the DITL editing window appears. You are now going to
delete all the items in the DITL except the Pick one: static text item and the three radio
buttons.
Click the OK button and press the delete key. Click the Cancel button and press the
delete key. Click the Show preview check box and press the delete key. Finally, click
the user item (the grey rectangle) and press delete.
Next, you'll change the positioning of the remaining four items. Double-click the Pick
one: static text item and change its coordinates to the ones shown in Figure 6. Close
the window when you are done.
Figure 6. New coordinates for the Pick one: static text item.
Double-click the Afghan radio button and change its coordinates to the ones shown in
Figure 7. Close the window when you are done.
Figure 7. New coordinates for the Afghan radio button.
Double-click the Elephant radio button and change its coordinates to the ones shown in
Figure 8. Close the window when you are done.
Figure 8. New coordinates for the Elephant radio button.
Double-click the Squirrel radio button and change its coordinates to the ones shown in
Figure 9. Close the window when you are done.
Figure 9. New coordinates for the Squirrel radio button.
Now we're almost done. Close the DITL editing window, leaving you back in the DLOG
editing window. The last thing left to do is to resize the DLOG to reflect its slimmed
down and rearranged DITL. Change the Bottom: to 123 and the Right: to 234. The final
version of our DLOG is shown in Figure 10.
Figure 10. The final version of our DLOG.
Quit ResEdit, being sure to save your changes. Now we're ready to enter our source
code.
Creating the Modeless Project
Launch CodeWarrior and create a new project based on the MacOS:C/C++:Basic Toolbox
68k stationary. Turn off the Create Folder check box. Name the project Modeless.mcp
and place it in your Modeless folder. Remove SillyBalls.c and SillyBalls.rsrc from the
project; we will not be using these files. From the Finder, drag and drop your
Modeless.rsrc file into the project window. You also can remove the ANSI Libraries
group from the project, because we won't need them, either.
Select New from the File menu to create a new window. Save it with the name
Dialogger.c in your Modeless folder. Select Add Window from the Project menu to add
Dialogger.c to the project. Your project window should look something like Figure
11.
Figure 11. Dialogger project window.
Rather than print the code here twice, we'll go straight to the walk-through. You can
type in the code as we discuss it below and you will end up with the complete program,
or you can save your fingers some effort and get the complete project from MacTech's
ftp site ftp://ftp.mactech.com/src/.
Walking Through the Source Code
Much of the Modeless source code will look familiar to you from earlier programs. As
usual, Modeless starts off #including necessary header files, then it begins a series of
#defines. The first three define the base resource ID, and the resource IDs for the
ALRT and DLOG resources.
#include
#include
#include
#include
#include
#define kBaseResID 128
#define kAboutALRTid 129
#define kDialogResID 128
kVisible, kMoveToBack, kMoveToFront, and kNoGoAway are used in the calls to
NewWindow() and GetNewDialog(). kSleep, as usual, is passed to WaitNextEvent().
#define kVisible true
#define kMoveToBack NULL
#define kMoveToFront (WindowPtr)-1L
#define kNoGoAway false
#define kSleep 7L
kOn and kOff are passed to SetControlValue() to turn a radio button on and off.
#define kOn 1
#define kOff 0
These three #defines define the item IDs for the three radio buttons that appear in the
modeless dialog.
#define iAfghan 1
#define iElephant 2
#define iSquirrel 3
kLeftMargin and kTopMargin determine the position of the My Pet Fred window on the
screen.
#define kLeftMargin 5
#define kTopMargin 40
kFirstRadio defines the ID of the first radio button in the modeless dialog. kLastRadio
defines the ID of the last radio button in the set.
#define kFirstRadio 1
#define kLastRadio 3
The remainder of the #defines represent the Modeless menus and menu items.
#define mApple kBaseResID
#define iAbout 1
#define mFile kBaseResID+1
#define iSettings 1
#define iQuit 3
Modeless makes use of four global variables. gDone is set to true until the program is
ready to exit. gCurrentPICT contains the ID of the current My Pet Fred PICT.
gSettingsDLOG is a pointer to the modeless dialog. We made this a global so we could
keep the modeless dialog settings around, even if we close the dialog. gFredWindow
points to the My Pet Fred window. We'll take advantage of this pointer when we delete
the My Pet Fred window and create a new one.
Boolean gDone;
short gCurrentPICT = kBaseResID;
DialogPtr gSettingsDLOG = NULL;
WindowPtr gFredWindow = NULL;
As always, we created a function prototype for each of the Modeless functions.
void ToolBoxInit( void );
PicHandle LoadPICT( short picID );
void CreateWindow( void );
void MenuBarInit( void );
void EventLoop( void );
void DoEvent( EventRecord *eventPtr );
void DoDialogEvent( EventRecord *eventPtr );
void HandleMouseDown( EventRecord *eventPtr );
void HandleMenuChoice( long menuChoice );
void HandleAppleChoice( short item );
void HandleFileChoice( short item );
void DoUpdate( EventRecord *eventPtr );
void CreateDialog( void );
void FlipControl( ControlHandle control );
void SwitchPICT( void );
main() starts off by initializing the Toolbox. Next, the menu bar is set up and the My
Pet Fred window is created. Finally, we begin the main event loop.
/********** main **********/