PerfectScript Journal

May 1999: Using Dialog Callbacks to Make Dialogs Interactive

Have you ever noticed how some dialogs in WordPerfect change, based on a selection that was made in that dialog?  You may have asked, "How do they do that?"   It is through the magic of dialog callbacks.

Your macros can also use dialog callbacks in macro dialogs to work interactively, based on the user's selections.

The dialog in the following macro will display a list, based on the radio button selection.  If the user selects Cats, a list of cats is displayed. If the user selects Dogs, a list of dogs is displayed.  This is all done without the dialog being dismissed and redisplayed.

Copy and paste this macro into your copy of WordPerfect, then compile it.  (If you have WPWin 7, change the "EN" to a "US" in the Application line.)

// *****************************************************
// Description: This macro displays a list of dogs or cats.
// Developer: J. Jeppson
// Copyright 1999 All Rights Reserved
//********************************************
// THE PRELIMINARIES
Application(A1; "WordPerfect"; default; "EN")
vCats[]:=GetCatList()
vDogs[]:=GetDogList()
vCat:=1
vDog:=0

// DEFINE AND SHOW THE DIALOG
DialogDefine ("Pets"; 50; 50; 150; 110; Percent!; "Letter Starter")
DialogAddRadioButton ("Pets";"CatRadioBttn"; 10; 10; 55; 10; "Cats"; vCat)
DialogAddRadioButton ("Petsr";"DogRadioBttn"; 75; 10; 54; 10; "Dogs"; vDog)
DialogAddListBox ("Pets"; "ListBx3"; 10; 30; 130; 60; Sorted!; ListBx3)
Switch(1)
Caseof vCat: Fill(vCats[])
Caseof vDog: Fill(vDogs[])
Endswitch
DialogAddPushButton ("Pets"; "OKBttn"; 103; 86; 35; 13; OKBttn!; "Done")
DialogShow ("Pets"; "WordPerfect"; Callback)
CallbackWait
Quit

// THE CALLBACK
Label (Callback)
MacroStatusPrompt(on!; "1="+Callback[1]+" 2="+Callback[2]+" 3="+Callback[3]+ " 4="+Callback[4]+" 5="+Callback[5]+" 6="+Callback[6]+" 7="+Callback[7]+ " 8="+Callback[8]+" 9="+Callback[9]+" 10="+Callback[10]+" 11="+Callback[11]) If(Callback[5]=274 OR Callback[3]="CancelBttn")
CallbackResume
Endif
Switch (Callback[3])
  Caseof "CatRadioBttn": Fill(vCats[])
  Caseof "DogRadioBttn": Fill(vDogs[])
  Caseof "OKBttn": CallbackResume
Endswitch
Return

// SUPPORTING FUNCTIONS
FUNCTION GetCatList()
vCats[]:= {"Siamese";"Angoran"; "Norwegian Forest"; ot;Tabby"; "Himalayan"; "Persion"}
Return (vCats[])
ENDFUNC

FUNCTION GetDogList()
vDogs[]:= {"Poodle"; "German Shepherd"; "Pointer"; "Chihuahua"; "St. Bernard"; "Maltese"}
Return (vDogs[])
ENDFUNC

PROCEDURE Fill(vList[])
RegionResetList("Pets.ListBx3")
Fornext(x; 1; vList[0])
DialogAddListItem("Pets"; "ListBx3"; vList[x])
Endfor
ENDPROC

Supporting Functions

First, lets look at the FUNCTIONs and PROCEDURE at the bottom.  I like to use FUNCTIONS and PROCEDURES because they allow me to reuse code easily.  (See Creating your Own Custom Macro Commands for more info.) . 

The first function, GetCatList, creates an array variable that contains the breed names of several cats.  The second FUNCTION, GetDogList, creates an array variable that contains the breed names of several dogs.

The PROCEDURE Fill clears the contents of the list and inserts new list items.

The Preliminaries Section

Now back to the top of the macro:

Before we can display the dialog, we must first call the functions that create the array variables with the lists of cats and dogs. Placing the names in array lists makes adding the names to the list box fast and easy.  We then determine whether Cats or Dogs will be automatically selected by setting a value of 1 or 0 to the radio button variables. In this case, we set the Cat radio button as On (1), and the Dog radio button as Off (0).

Define and Show the Dialog

Next we define the dialog with DialogDefine.  We add two radio buttons (DialogAddRadioButton), and a list box (DialogAddListBox). Notice that after the DialogAddListBox comand, we test whether the Cats radio button or Dogs radio button is selected (based on the settings we created above), then call the Fill routine to insert the list items. Then we add the OK button with DialogAddPushButton.

The DialogShow command serves 2 functions:  it displays the dialog, and defines a callback.  In this case, I named the callback simply "Callback." But if you have several dialogs with callbacks in your macro, you'll need to be more imaginative than that.

After the DialogShow, we have a CallbackWait command.  This command acts like a loop (similar to a WHILE(Flag=1) Endwhile loop), and causes execution to stay at that point in the macro, just waiting for a command that will break out of that callback loop. 

When a callback event happens, such as the user clicking a button on the dialog, then execution moves to the Callback label.  The callback label executes once, then execution returns to the CallbackWait command.  The macro stays in ths callback loop until an event breaks out of the loop.

The Callback

Now look at the Callback itself. This is the section that begins with LABEL (Callback). When execution moves to the callback, a callback array is created. (In simple terms, an array is variable that contains multiple values.) 

I've included a MacroStatusPrompt command in the callback label that will display the array values. If you play the macro, you will see some values on the Status Bbar at the bottom of the screen each time you click on an item on the dialog.  These are the values that are stored in the callback array.

Eleven callback elements are defined:

[1] Callback type:  For dialogs callbacks, this is always 3

[2] Dialog name:  in this case,  this will always be "Pets"

[3] ID of the control that was clicked on:  we check this to determine which radio button was clicked

[4] Window handle of the dialog

[5] Windows message ID: (we check for 274, which is Alt+F4, or close)

[6] thru [11] are values that may pass through based on the control that was clicked.  

Generally, you will only be concerned about elements [3] and [5].

The first thing we do in the callback label is to check Callback[5] to see if the user clicked the X in the upper right corner of the dialog, pressed Alt+F4, or clicked a Cancel button.  If they did one of these things, Callback[5] will equal 274, we end the CallbackWait with a CallbackResume, and the macro ends.

Then we check Callback[3] to see if the user clicked a radio button or the OK button. If the user clicked the Cat radio button, we call the Fill routine, which removes current items from the list and inserts the cat names.   Likewise, if the user clicked the Dog radio button, we call the Fill routine, which removes current items from the list and inserts the dog names.

And if the click the OK button, we end the CallbackWait with another CallbackResume command and the macro ends.

Summary

Dialog callbacks help you create interactive dialogs. In the callback routine, we check which control is clicked, then act upon the selection.

Somewhere within the callback routine must be an exit route -- for example, an OK button on the dialog causes the CallbackResume command to be invoked, so that we get out of the CallbackWait.

The callback array elements you will most often use are Callback[3], which contains the ID of the control that was clicked on, and Callback[5], which allows you to test if the user clicked the Cancel or [X] button.

Other callback array elements allow you to test for other values, such as if a scroll box was moved, etc. Information about these array elements can be found in the WordPerfect online help, or in my  book.

 

                           
Copyright Notice: The information included in the PerfectScript Journal is protected by US Copyright. The author grants you the right to use the routines in your own macros as needed. You may not sell, distribute, or publish them in any form.
If you choose to use the information here, you do so entirely at your own risk. No representations are made regarding the fitness of this information for your particular purpose, or for your ability or inability to use the information. You are advised to make backups of all relevant files before implementing any suggestion or technique.
© Copyright 1999 by J. Jeppson.