Once the dialog has been created, we can add controls to it. For our example, we will add a text box to let the user type in their name, and also add two BUTTON controls ("OK" and "Cancel"):
CONTROL ADD TEXTBOX, hDlg, IdText&, "", 14, 21, 134, 12, Style&, exStyle&
CONTROL ADD BUTTON, hDlg, 1, "&OK", 44, 38, 40, 14, %BS_DEFAULT or %WS_TABSTOP CALL Ok
CONTROL ADD BUTTON, hDlg, 2, "&Cancel", 90, 38, 40, 14 CALL Cancel
hDlg refers to the handle of the dialog you're adding the control to, as returned by the DIALOG NEW statement.
The next parameter IdText&, 1, and 2 in the example lines above) is the unique numeric identifier (ID) for the control. Whereas dialog handles are determined by Windows at run-time, controls use ID values that are specified by the programmer. By knowing the dialog handle and a control ID, we can identify and interact programmatically with any control on a DDT dialog using any of the control-related DDT statements.
In general, ID values should be kept within in the range 100 to 65535. It should also be noted that some values below 100 are reserved by Windows for special purposes. For example, the special ID value 1 (%IDOK) is usually assigned to a Button control that is to be activated when the ENTER key is pressed (this would typically be the "OK" button on a dialog). Similarly, the special ID value of 2 (%IDCANCEL) is usually assigned to a Button control that is to be activated when the ESCAPE key is pressed (typically this would be the "Cancel" button).
In general, two controls on a given dialog should not use the same ID value, as it prevents them from being identified uniquely. However, it is common to assign the special value -1& to plain Label (static) controls that will not have their content, style, or color changed at run-time.
It is always a good idea to plan the values of control identifiers carefully. For example, a set of related Option (radio) controls should use ID values that are ordered sequentially, as this makes it very easy to manipulate them as a group with the CONTROL SET OPTION statement, etc. Another common scheme is keep all the ID numbers for the controls in a specific range. For example, the first dialog in a program might use controls whose ID values are in the range 100 to 199, the second dialog might use the range 200 to 299, etc.
The identifier parameter is followed by the caption text for the control. The ampersand symbols "&" within the caption text fields is surprisingly helpful - the letter that follows the symbol specifies a command accelerator (hot-key). At run-time, the accelerator character is drawn underscored: OK and Cancel. In this case, the underscored character informs the user that pressing the ALT+O keys has the same effect as using the mouse to click the "OK" button. Similarly, the ALT+C combination will trigger the "Cancel" button.
Coordinates used in the
Each type of control has its own unique set of style options.
Most of the equates have been predefined in the DDT.INC and WIN32API.INC
files supplied with PowerBASIC. |
The CONTROL ADD statement for the "OK" button includes the keyword CALL. This tells Windows to call the "OK" function each time the "OK" button is pressed. The "OK" function is simply a Callback Function that contains the code you want to execute when the button is pressed (or when some other control-related event occurs).
In this example, we want to assign the text from the text box control to a global string, and then close the dialog box. However, we first must check that our code is executed only in response to a "click" event - we would not want our dialog to end if some other notification message was sent to the callback! We do this by testing the values of the message parameters held in the CB.HNDL, CB.MSG, and CB.CTLMSG system variables:
CALLBACK FUNCTION Ok() AS LONG
IF CB.MSG = %WM_COMMAND AND CB.CTLMSG = %BN_CLICKED THEN
CONTROL GET TEXT CB.HNDL, %IDTEXT TO gsUserName
DIALOG END CB.HNDL, 1 ' Return 1
FUNCTION = 1
END IF
END FUNCTION
Similarly, we provide a Callback Function for the "Cancel" button, which will close the dialog box, ignoring any text entered into the text box:
CALLBACK FUNCTION Cancel() AS LONG
IF CB.MSG = %WM_COMMAND AND CBCTLMSG = %BN_CLICKED THEN
DIALOG END CB.HNDL, 0 ' Return 0
FUNCTION = 1
END IF
END FUNCTION
Once the dialog has been created and the controls added, we are ready to display the dialog on the screen. In this example, we will create it as a Modal dialog. That means that when the DIALOG SHOW MODAL statement is executed, the execution of this portion of our program will block (halt) until the dialog is closed: (see Modal vs. Modeless below for more information on modal and modeless dialogs)
LOCAL lResult AS LONG
...
DIALOG SHOW MODAL hDlg TO lResult
During the time that the "main" part of our code is blocked by the modal dialog, DDT may call the code in the Callback Functions in response to user interaction, etc. If no events occur, our code is not executed at all, and therefore uses no CPU time. In this example, the dialog only closes when the user eventually clicks the OK or the Cancel button (or presses the ENTER or ESCAPE keys).
Once the dialog is closed, the lResult variable will contain the value set using the DIALOG END statement, and execution of the statements following the DIALOG SHOW statement will resume. In our example, we use a return value of one (1) to indicate that the user clicked the OK button, and a return value of 0 to indicate the user clicked the Cancel button.
The complete example code can be found in the HELLODDT.BAS file in the \PB\SAMPLES\DDT\HELLODDT folder:
#COMPILE EXE
#INCLUDE "DDT.INC"
%IDOK = 1
%IDCANCEL = 2
%IDTEXT = 100
%BS_DEFAULT = 1
' Global variable to receive the user name
GLOBAL gsUserName AS STRING
CALLBACK FUNCTION OkButton()
IF CB.MSG = %WM_COMMAND AND CB.CTLMSG = %BN_CLICKED THEN
CONTROL GET TEXT CB.HNDL, %IDTEXT TO gsUserName
DIALOG END CB.HNDL, 1
FUNCTION = 1
END IF
END FUNCTION
CALLBACK FUNCTION CancelButton()
IF CB.MSG = %WM_COMMAND AND CB.CTLMSG = %BN_CLICKED THEN
DIALOG END CB.HNDL, 0
FUNCTION = 1
END IF
END FUNCTION
FUNCTION PBMAIN() AS LONG
LOCAL hDlg AS DWORD
LOCAL lResult AS LONG
' ** Create a new dialog template
DIALOG NEW 0, "What is your name?", ,, 160, 50, 0, 0 TO hDlg
' ** Add controls to it
CONTROL ADD TEXTBOX, hDlg, %IDTEXT, "", 14, 12, 134, 12
CONTROL ADD BUTTON, hDlg, %IDOK, "OK", 34, 32, 40, 14, %BS_DEFAULT OR %WS_TABSTOP CALL OkButton
CONTROL ADD BUTTON, hDlg, %IDCANCEL, "Cancel", 84, 32, 40, 14 CALL CancelButton
' ** Display the dialog
DIALOG SHOW MODAL hDlg TO lResult
' ** Check the dialog return result
IF lResult THEN
MSGBOX "Hello " & gsUserName, &H00002000& ' = %MB_TASKMODAL
END IF
END FUNCTION
See Also