Introduction
The Problem
- Edit the parameters
- Start/Restart the simulation
- Maybe stop the simulation before it ends
- Go back to steps 1 or 2 or Quit.
Analysis
The New Dialog Box Demo
Re-source¹ | Fields.. [Close Window] | Info².. [Close, Close] |
---|---|---|
DITL [OK] | (see image below. Start with the Save, then Cancel buttons, then the other fields) |
ID=400, Name="Alarm", Purgeable (only) |
DITL [OK] | (see image below. Start with the OK button, then the text field) |
ID=401, Name="About", Purgeable (only) |
ALRT [OK] | TOP=40, Bottom=142, Left=40, Right=332, DITL=401, Default Color | ID=401, Name="About", Purgeable (only) |
DLOG [OK] | TOP=40, Bottom=200, Left=60, Right=320, DITL=400, Default Color, Standard double-border Dialog style, Not Initially visible, No close box | ID=400, Name="Alarm", Purgeable (only) |
MENU [OK] | [X] Enabled, Title=• Apple Menu[ENTER], [X] Enabled, Title="About..."[ENTER] [ ]Enabled, • Separator line | ID=400, No attributes. |
MENU [OK] | [X] Enabled, Title="File"[ENTER], [X] Enabled, Title="Settings..", Cmd-Key:S[ENTER], Title="Run", Cmd-Key:R[ENTER], Title="Quit", Cmd-Key:Q[ENTER] | ID=401, No attributes. |
MENU [OK] | [X] Enabled, Title="Edit"[ENTER], no options [ ] Enabled: Title="Undo", Cmd-Key:Z[ENTER], Separator Line[Enter], Title="Cut", Cmd-Key:X[ENTER], Title="Copy", Cmd-Key:C[ENTER], Title="Paste", Cmd-Key:V[ENTER], Title="Clear", Cmd-Key:none[ENTER] | ID=402, No attributes. |
MBAR [OK] | Each time, click in '****', choose Resource:Insert New Field(s) for Menu Res IDs 400, 401, 402. Top should say "# of menus 3 at the end." | ID=400, No attributes. |
WIND [OK] | Close, then choose Resource:Open Using Template [WIND] [OK]. Bounds Rect= 70, 36, 106, 156 [Set], Proc ID=0, Visible=false, GoAway=false, RefCon=0, Title="Countdown", Auto Position=$0000. | ID=400, Name="Countdown", Purgeable (only) |
Parameters Ditl
About Ditl
When you've finished, close the .rsrc file. ResEdit will ask you to save it - save it. Then open up the Dlog.π project. Choose File:New and create a stub of a C program:
int main(void)
{
return 0;
}
Choose File:Save to save it as Dlog.c. Choose Project:Add "Dlog.c" to add the file to the project. You don't need to do anything clever to add the rsrc file to the project, THINK C will automatically associate the .rsrc with the same prefix as your application.
Now you want to replace the dummy program with the rest of file. When you've finished...
Dlog.h
* @file: Reminder.h
*/
#ifndef Reminder_h
#define Reminder_h
#define kBaseResId 400
#define kAboutAlert 401
#define kBadSysAlert 402
#define kSleep 60
#define kSaveButton 1
#define kCancelButton 2
#define kTimeField 4
#define kSOrMField 5
#define kSoundOnBox 6
#define kIconOnBox 7
#define kAlertOnBox 8
#define kSecsRadio 10
#define kMinsRadio 11
#define kDefaultSecsId 401
#define kDefaultMinsId 402
#define kOff 0
#define kOn 1
#define kSecondsPerMinute 60
#define kTop 25
#define kLeft 12
#define kMarkApplication 1
#define kAppleMenuId (kBaseResId)
#define kFileMenuId (kBaseResId+1)
#define kAboutItem 1
#define kChangeItem 1
#define kStartStopItem 2
#define kQuitItem 3
#define kSysVersion 2
typedef enum{
kBoolFalse=0,
kBoolTrue=1
}tBool;
typedef enum {
kTimeUnitSeconds=0,
kTimeUnitMinutes=1
}tTimeUnit;
typedef struct {
long iTime;
int iSound, iIcon, iAlert;
tTimeUnit iUnit;
}tSettings;
extern Handle DlogItemGet(DialogPtr aDialog, int aItem);
extern void CtlSet(DialogPtr aDialog, int aItem, int aValue);
extern int CtlGet(DialogPtr aDialog, int aItem);
extern void CtlFlip(DialogPtr aDialog, int aItem);
extern void ITextSet(DialogPtr aDialog, int aItem, Str255 *aStr);
extern void StartCountDown(long aNumSecs);
extern void HandleCountDown(void);
extern void UpdateCountDown(void);
extern void RestoreSettings(DialogPtr aSettingsDialog);
extern void SaveSettings(DialogPtr aSettingsDialog);
extern void HandleDialog(void);
extern void HandleFileChoice(int aTheItem);
extern void HandleAppleChoice(int aTheItem);
extern void HandleMenuChoice(long aMenuChoice);
extern void HandleMouseDown(void);
extern void HandleEvent(void);
extern void MainLoop(void);
extern void MenuBarInit(void);
extern void DialogInit(void);
extern void WinInit(void);
extern tBool Sys6OrLater(void);
extern void ToolboxInit(void);
extern int main(void);
#endif // Reminder_h
Dlog.c
* Dlog.c
*/
#include "Dlog.h"
tBool gDone;
EventRecord gTheEvent;
tSettings gSavedSettings;
WindowPtr gCountDownWindow;
long gTimeout, gOldTime;
tBool gIsCounting;
Handle DlogItemGet(DialogPtr aDialog, int aItem)
{
int itemType;
Rect itemRect;
Handle itemHandle;
GetDItem(aDialog, aItem, &itemType, &itemHandle, &itemRect);
return itemHandle;
}
void CtlSet(DialogPtr aDialog, int aItem, int aValue)
{
Handle itemHandle=DlogItemGet(aDialog, aItem);
SetCtlValue((ControlHandle)itemHandle, aValue);
}
int CtlGet(DialogPtr aDialog, int aItem)
{
Handle itemHandle=DlogItemGet(aDialog, aItem);
return GetCtlValue((ControlHandle)itemHandle);
}
/*
void ITextSet(DialogPtr aDialog, int aItem, Str255 *aStr)
{
Handle itemHandle=DlogItemGet(aDialog, aItem);
SetIText(itemHandle, aStr);
}
*/
void CtlFlip(DialogPtr aDialog, int aItem)
{
Handle itemHandle=DlogItemGet(aDialog, aItem);
SetCtlValue((ControlHandle)itemHandle,
(GetCtlValue((ControlHandle)itemHandle)==kOn)? kOff:kOn);
}
void StartCountDown(long aNumSecs)
{
GetDateTime(&gOldTime);
if(gSavedSettings.iUnit==kTimeUnitMinutes) {
aNumSecs*=kSecondsPerMinute;
}
gTimeout=gOldTime+aNumSecs; // this is the timeout.
gIsCounting=kBoolTrue;
}
// Called on Null event.
void HandleCountDown(void)
{
if(gIsCounting==kBoolTrue) {
long myTime;
GetDateTime(&myTime);
if(myTime!=gOldTime) {
GrafPtr oldPort;
gOldTime=myTime; // gTimeout-gOldTime==remaining seconds.
// gen update, but how?
GetPort(&oldPort);
SetPort((GrafPtr)gCountDownWindow);
InvalRect(&gCountDownWindow->portRect);
SetPort(oldPort);
}
}
}
void UpdateCountDown(void)
{
//
WindowPtr win=(WindowPtr)gTheEvent.message;
if(win==gCountDownWindow) {
long remaining=gTimeout-gOldTime;
Str255 myTimeString;
BeginUpdate(win);
MoveTo(kLeft, kTop);
if(remaining<=0 || gIsCounting==kBoolFalse) {
remaining=0;
gIsCounting=kBoolFalse;
}
NumToString(remaining, myTimeString);
EraseRect(&(gCountDownWindow->portRect));
DrawString(myTimeString);
EndUpdate(win);
}
}
void RestoreSettings(DialogPtr aSettingsDialog)
{
Handle itemHandle;
Str255 timeString;
tBool isInSeconds=(gSavedSettings.iUnit==kTimeUnitSeconds)?
kBoolTrue:kBoolFalse;
itemHandle=DlogItemGet(aSettingsDialog, kTimeField);
NumToString(gSavedSettings.iTime, &timeString);
SetIText(itemHandle, timeString);
CtlSet(aSettingsDialog, kSoundOnBox, gSavedSettings.iSound);
CtlSet(aSettingsDialog, kIconOnBox, gSavedSettings.iIcon);
CtlSet(aSettingsDialog, kAlertOnBox, gSavedSettings.iAlert);
CtlSet(aSettingsDialog, kSecsRadio, (isInSeconds==kBoolTrue)?kOn:kOff);
CtlSet(aSettingsDialog, kMinsRadio, (isInSeconds==kBoolFalse)?kOn:kOff);
itemHandle=DlogItemGet(aSettingsDialog, kSOrMField);
SetIText(itemHandle,(gSavedSettings.iUnit==kTimeUnitSeconds)?
"\pseconds":"\pminutes");
}
void SaveSettings(DialogPtr aSettingsDialog)
{
Handle itemHandle;
Str255 timeString;
itemHandle=DlogItemGet(aSettingsDialog, kTimeField);
GetIText(itemHandle, &timeString);
StringToNum(timeString, &gSavedSettings.iTime);
gSavedSettings.iSound=CtlGet(aSettingsDialog, kSoundOnBox);
gSavedSettings.iIcon=CtlGet(aSettingsDialog, kIconOnBox);
gSavedSettings.iAlert=CtlGet(aSettingsDialog, kAlertOnBox);
gSavedSettings.iUnit=(CtlGet(aSettingsDialog, kSecsRadio)==kOn)?
kTimeUnitSeconds:kTimeUnitMinutes;
}
void HandleDialog(void)
{
tBool dialogDone;
int itemHit;
long alarmDelay;
Handle itemHandle;
DialogPtr settingsDialog;
settingsDialog=GetNewDialog(kBaseResId, NULL, (WindowPtr)-1);
ShowWindow(settingsDialog);
RestoreSettings(settingsDialog);
dialogDone=kBoolFalse;
while(dialogDone==kBoolFalse) {
ModalDialog(NULL, &itemHit);
switch(itemHit) {
case kSaveButton:
SaveSettings(settingsDialog); // update them.
dialogDone=kBoolTrue;
break;
case kCancelButton:
dialogDone=kBoolTrue;
break;
case kSoundOnBox:
case kIconOnBox:
case kAlertOnBox:
CtlFlip(settingsDialog, itemHit);
break;
case kSecsRadio:
CtlSet(settingsDialog, kSecsRadio, kOn);
CtlSet(settingsDialog, kMinsRadio, kOff);
itemHandle=DlogItemGet(settingsDialog, kSOrMField);
SetIText(itemHandle, "\pseconds");
break;
case kMinsRadio:
CtlSet(settingsDialog, kSecsRadio, kOff);
CtlSet(settingsDialog, kMinsRadio, kOn);
itemHandle=DlogItemGet(settingsDialog, kSOrMField);
SetIText(itemHandle, "\pminutes");
break;
}
}
DisposeDialog(settingsDialog);
}
void HandleFileChoice(int aTheItem)
{
switch(aTheItem) {
case kChangeItem:
HandleDialog();
break;
case kStartStopItem:
HiliteMenu(0);
StartCountDown(gSavedSettings.iTime);
break;
case kQuitItem:
gDone=true;
break;
}
}
void HandleAppleChoice(int aTheItem)
{
Str255 accName;
int accNumber, itemNumber, dummy;
MenuHandle appleMenu;
switch(aTheItem) {
case kAboutItem:
NoteAlert(kAboutAlert, NULL);
break;
default:
appleMenu=GetMHandle(kAppleMenuId);
GetItem(appleMenu, aTheItem, &accName);
OpenDeskAcc(accName);
break;
}
}
void HandleMenuChoice(long aMenuChoice)
{
int theMenu, theItem;
if(aMenuChoice!=0) {
theMenu=HiWord(aMenuChoice);
theItem=LoWord(aMenuChoice);
switch(theMenu) {
case kAppleMenuId:
HandleAppleChoice(theItem);
break;
case kFileMenuId:
HandleFileChoice(theItem);
break;
}
HiliteMenu(0);
}
}
void HandleMouseDown(void)
{
WindowPtr whichWindow;
int thePart;
long menuChoice, windSize;
thePart=FindWindow(gTheEvent.where, &whichWindow);
switch(thePart) {
case inMenuBar:
menuChoice=MenuSelect(gTheEvent.where);
HandleMenuChoice(menuChoice);
break;
case inSysWindow:
SystemClick(&gTheEvent, whichWindow);
break;
case inDrag:
DragWindow(whichWindow, gTheEvent.where, &screenBits.bounds);
break;
case inGoAway:
gDone=kBoolTrue;
break;
}
}
void HandleEvent(void)
{
char theChar;
tBool dummy;
WaitNextEvent(everyEvent, &gTheEvent, kSleep, NULL);
switch(gTheEvent.what){
case mouseDown:
HandleMouseDown();
break;
case keyDown: case autoKey:
theChar=(char)(gTheEvent.message & charCodeMask);
if((gTheEvent.modifiers & cmdKey)!=0) {
HandleMenuChoice(MenuKey(theChar));
}
break;
case nullEvent:
HandleCountDown();
break;
case updateEvt:
UpdateCountDown();
break;
}
}
void MainLoop(void)
{
gDone=kBoolFalse;
while(gDone==kBoolFalse) {
HandleEvent();
}
}
void MenuBarInit(void)
{
Handle myMenuBar;
MenuHandle aMenu;
myMenuBar=GetNewMBar(kBaseResId);
SetMenuBar(myMenuBar);
DisposHandle(myMenuBar);
aMenu=GetMHandle(kAppleMenuId);
AddResMenu(aMenu, 'DRVR');
DrawMenuBar();
}
void WinInit(void)
{
gCountDownWindow=GetNewWindow(kBaseResId, NULL, (WindowPtr)-1);
gIsCounting=kBoolFalse;
SetPort(gCountDownWindow);
TextFace(bold); // it's the same in THINK C.
TextSize(24);
ShowWindow(gCountDownWindow);
}
void DialogInit(void)
{
gSavedSettings.iTime=12;
gSavedSettings.iSound=kOn;
gSavedSettings.iIcon=kOn;
gSavedSettings.iAlert=kOn;
gSavedSettings.iUnit=kTimeUnitSeconds;
}
tBool Sys6OrLater(void)
{
OSErr status;
SysEnvRec SysEnvData;
int dummy;
tBool result=kBoolTrue;
status=SysEnvirons(kSysVersion, &SysEnvData);
if(status!=noErr || SysEnvData.systemVersion<0x600) {
StopAlert(kBadSysAlert, NULL);
result=kBoolFalse;
}
return result;
}
void ToolboxInit(void)
{
InitGraf(&thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(NULL);
MaxApplZone();
}
int main(void)
{
ToolboxInit();
if(Sys6OrLater()) {
DialogInit();
MenuBarInit();
WinInit();
InitCursor();
MainLoop();
}
return 0;
}