VC++ Workshop
Session 6
R. Eckert
DIALOG BOXES
Dialog box--
Popup child window created by Windows
Used for special-purpose input
Beyond what can be easily managed with a menu
Contains several child window controls
Layout & what it does is are predefined (template--a resource)
How it does it is determined by a "Dialog box procedure"
Destroyed immediately after use
Programmer must:
1. Set up the template in the resources (.rc file)
Specifies controls used, their style/layout
Can be prepared "visually" w/ Dev Studio dialog box editor
Or "manually" with a text editor
2. Write the dialog box procedure
Code to carry out dialog box's tasks
Placed in .cpp file
Provides message-processing capability
Msgs from controls inside go to this procedure
A callback function like main window procedure
But not the same
Part of callback inside Windows
It interprets some keystrokes (tab)
It calls our procedure
Rule of thumb--
Dialog box: for simple popup windows using normal window controls
Popup/child windows: extensive painting or nonstandard behavior needed
Main advantage of dialog boxes--
Ease of construction with the dialog box editor
Types of dialog boxes:
Modal--
While visible, user can't switch back to parent window
(can change to other apps)
User must explicitly end dialog box
Typically by clicking "OK" or "CANCEL" buttons inside
Most common type of dialog box
Example: "About" box available with most Windows apps
System Modal--
A variety of modal dialog box
With these user can't switch to other apps while dialog box is active
Modeless--
User can switch between dialog box and the parent window
More like popup windows
Used when dialog box must be visible while user interacts w/ parent
Example: dialog box resulting from "Find" or "Replace" menu item
of many Windows apps
Steps in Designing, Creating, Using a Modal Dialog Box--
1. Determine child window controls needed inside
2. Design dialog box template (easiest with dialog box editor)
3. Write message-processing function
4. Activate dialog box by calling DialogBox()
(Typically in response to menu item selection in WndProc()
5. Resulting dialog box stays on screen until call to EndDialog()
(from inside dialog box function)
DLG1: A Simple Example--
User Clicks "Dialog Box" on program's main menu
Modal dialog box ("FIRSTDIALOG") appears
Contains: a static text control (IDC_STATIC)
an icon (IDC_ICON1)
an "OK" button (IDC_OK)
a "Not OK" button (IDC_NOTOK)
User clicks "OK" buttonback to parent window
User clicks "Not OK" buttonbeep
Using Developer Studio to Design DLG1's Resources (.rc file)--
Resources:
The dialog box ("FIRSTDIALOG")
An icon ("DIALG1")
A menu ("MYMENU") with items:
"&Dialog Box" (IDM_DIALOG)
"&Quit" (IDM_QUIT
Steps to Follow:
Get into Developer Studio, open new DLG1 workspace
Enter or copy DLG1.CPP source file, add to project
Must declare WndProc() and DialogProc() callback functions
Must #include "resource.h" file
"Insert | Resource", "Icon | New" to bring up Icon Editor
Draw icon, and hit <Enter>
Fill in resulting dialog box
ID: "DIALG1"
File name: dialg1.ico
Iconify or close Icon Editor
Resources will look like:
Script1
Icon "DIALG1"
"Insert | Resource", "Menu | New" to bring up Menu Editor
Generate menu items:
&Dialog Box (ID = IDM_DIALOG)
&Quit (ID = IDM_QUIT)
Iconify the Menu Editor
Resource script will now look like:
Script1
Icon "DIALG1"
Menu IDR_MENU1
Right click on IDR_MENU1, select Properties
Change ID to "MYMENU"
The script will now look like:
Script1
Icon "DIALG1"
Menu "MYMENU"
"Insert | Resource", "Dialog | New" to bring up dialog box editor
Use righthand tool bar to modify and fill lefthand dialog box template
At any time, double click unoccupied point inside dialog box template
A "Dialog Properties" dialog box
Can be used to change many parameters associated with dialog box
Click on "Cancel" button in dialog box template area
Press <Delete> from the keyboard (Don't want that button)
Drag "OK" button to lower righthand corner of template area
Double click and change ID to IDC_OK
Leave default caption "OK" as is
Drag Button Tool (little rectangle on tool bar) to area below "OK" button
Double click "button1" button that appears
Set its ID to IDC_NOTOK
Set its caption to "Not OK"
Drag Static Text Control Tool (Aa) to top, righthand area of template area
Click and drag edge or corner of resulting rectangle to widen it
Double click, set ID to IDC_STATIC (default) and caption to "Static Control"
Drag Picture tool (box w/ tiny pictures) underneath & left of static control
Double click border of rectangle that appears
Choose "General" tab (if it doesn't appear)
Set ID to IDC_ICON1
Choose "Icon" from frame list box
Set Image: to "DIALG1"
Iconify Dialog box editor
Resource script should now look like:
Script1
Dialog IDD_DIALG1
Icon "DIALG1"
Menu "MYMENU"
Right click IDD_DIALG1 and choose Properties
Change the ID to "FIRSTDIALOG"
"File | Save As"
Enter the File name: dlg1
Make sure the file type is .rc
"Project | Add to Project" and "Files" | dlg1.rc
Resource script should now look like:
dlg1.rc
Dialog "FIRSTDIALOG"
Icon "DIALG1"
Menu "MYMENU"
Build the project
Dialog Box Editor has tools to create:
list boxes, combo boxes, edit controls, many others
Dialog Box Template Formats (used in .rc file)--
Syntax:
ResourceNameID DIALOG x, y, w, h
[Options--e.g., STYLE, CAPTION...]
BEGIN
Dialog Box Item specifications (of window controls inside)
END
ResourceNameID--
String used in call to DialogBox()
Function that creates the dialog box
x,y,w,h--
Position, size of dialog box
Relative to upperleft corner of parent window
Dialog "base units" used
x,w in units of 1/4 average character width
y,h in units of 1/8 average character height)
Look of dialog box same regardless of video display, font
(Default system font x-axis, y-axis units about the same)
Options--
STYLE is the most important one
All WS_*** and DS_*** constants can be used
CAPTION also important
Example:
FIRSTDIALOG DIALOG 10,10,200,200
CAPTION "Dialog"
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
BEGIN
/* Dialog Box Item Specifications go here */
END
Dialog Box Item Specifications (for controls inside): General Syntax--
CONTROL_ITEM_NAME [item-dependent stuff], id, x, y, w, h, [style]
Some Examples:
CTEXT "Centered Text", DLI_STATIC, 10, 10, 100, 8
DEFPUSHBUTTON "Cancel", IDC_CANCEL, 40, 10, 40, 15, WS_TABSTOP
EDITTEXT IDC_EDIT, 10, 20, 30, 40, WS_HSCROLL
LISTBOX IDC_LIST, 10, 10, 50, 100, LBS_NOTIFY | WS_VSCROLL | WS_BORDER
SCROLLBAR DLI_SCROLL, 50, 20, 10, 50, SBS_VERT
DLG1.CPP Example Source Program--
WinMain()--
No extra window classes defined (not needed with dialog boxes)
WndProc()--
User clicks "Dialog Box" on menu (WM_COMMAND, IDM_DIALOG)
Pgm calls DialogBox()
Creates modal dialog box from app's dialog box template resources
Displays dialog box
Switches msg-processing to dialog box
Control returned when msg-processing function terminates dialog box
with a call to EndDialog()
DialogBox() parameters:
1. App's instance handle
2. Dialog box ID name
Specified in dialog box template when .rc file created
3. Handle of dialog box's parent window
4. Address of dialog box function that will process its messages
A callback function (as with timer)
Under Windows 95/NT, use name of callback function
If C++ compiler used, must be type cast to DLGPROC
Example (name of dialog box function is: DialogProc)--
HINSTANCE hInstance;
hInstance = (HINSTANCE)GetWindowLong (hWnd,
GWL_HINSTANCE);
DialogBox(hInstance, "FIRSTDIALOG", hWnd,
(DLGPROC)DialogProc);
Dialog box message-processing function (DialogProc() in DLG1.CPP)--
A callback function called by Windows
Takes same parameters as the app's WndProc()
Returns a Boolean (TRUE or FALSE) to Windows
TRUE should be returned if the message was processed by dialog proc
FALSE if not
Messages not passed to DefWindowProc() if not processed
Returning FALSE lets Windows know message wasn't processed
Then default message processing will happen automatically
Should always return TRUE after WM_INITDIALOG message
WM_INITDIALOG message:
Like ordinary an window's WM_CREATE message
Processed before window (dialog box) is made visible
Good place to put initialization code
EndDialog()
Destroys dialog box
Returns control to function that called DialogBox()
Parameters:
1. window handle passed to dialog box function (hDlg)
2. integer value returned by DialogBox()
Way of getting info from dialog box function to calling program
A dialog box can be used like any other window--
Use hDlg to get a DC for painting on the dialog box
Could be used to create another dialog box (nested dialogs)
User Interaction with Dialog Box Controls
WM_COMMAND message
LOWORD(wParam) contains control ID (as usual)
If dialog box has menu, WM_COMMAND messages from it
lParam, wParam contain message data (as usual)
DLG1 Dialog Box Message Processing--
Dialog box is created (WM_INITDIALOG)
Not action taken, no initialization in this dialog box
User clicks "OK" button in dialog box (WM_COMMAND, IDC_OK)
DialogProc() calls EndDialog()
Causes destruction of dialog box
Control transferred back to main window's WndProc()
User clicks on the "Not OK" button (WM_COMMAND, IDC_NOTOK)
DialogProc() calls MessageBeep() beep
Dialog box continues to be displayed
Exchanging Data with a Dialog Box--
Problems in using dialog boxes that do something:
1. Exchanging data between dialog box function and controls inside
2. Exchanging data between dialog box function and app's WndProc()
(1) SendMessage() could be used to send message to control inside, BUT:
Need to know control's handle
Not known since Windows creates them
IDs are known--specified in resource template
Use GetDlgItem() to get control's handle:
hControl = GetDlgItem(hDlg, controlID);
Then SendMessage() can be used to send msg to control:
SendMessage(hControl, Msg, wParam, lParam);
Functions can be combined using SendDlgItemMessage():
SendDlgItemMessage(hDlg, controlID, Msg, wParam, lParam);
Sends message Msg to control whose ID is controlID
(2) Easiest way to exchange info between dialog box ftn and WndProc()--
Use global variables
(Only way prior to Windows 3.0)
Alternative--
Start dialog box with DialogBoxParam(), not DialogBox():
DialogBoxParam(hInst,resource_name,hParent,dlgproc,lParamInit);
First four parameters same as those used in DialogBox()
Last parameter passed in lParam of dialog box function
Received in lParam of WM_INITDIALOG message
App usually makes it a pointer to some sort of structure
Complex data can be passed
DLG2: Dialog Box That Actually Does Something--
User clicks "Get Info" main menu item
Modal dialog box appears, contains:
Edit control for entering a person's name
List box containing four salary ranges.
User enters name, selects salary range, click dialog box's "OK" button
Dialog box disappears
Main window's client area displays:
Name entered by user
String indicating salary level
Situation after user entered name/salary range in dialog box:
Situation after user hits dialog box "OK" button:
User clicks dialog box's "Cancel" button
Main window's client area displays:
"No Response!"
Creating the DLG2 Dialog Box Template --
Procedure similar to that used for DLG1
Dialog box:
Static controls:
Used as labels for the edit control and the listbox
Captions: "Name:" and "Salary:"
ID: IDC_STATIC for both
Single-line edit control
Edit Control Creation Tool: has "ab|" icon
ID: IDC_EDITNAME
Listbox control
Creation Tool: icon w/ tiny list on left side, scroll arrows on right side
ID: IDC_LISTSALARY
"ListBox Properties": Change default "sort" style--
Select "Style" tab, Click "Sort" check button to remove check mark
Default "OK" and "Cancel" buttons
Leave with default IDs (IDOK, IDCANCEL)
Give dialog box the name: "INFODLG"
Caption: Information
Menu:
Menu Name: "MYMENU"
Menu Items: &Get Info, ID=IDM_GET
&Quit, ID=IDM_QUIT
DLG2.CPP Source File--
A. Global variables and Function Declarations:
To exchange info between WndProc() & dialog box function
name[]: Name entered by the user
nCurSel: position in list box (0, 1, 2, or 3) of salary range selected
WndProc() declared as main window procedure
InfoDlgProc() declared as dialog box function
[Possible alternative:
Set up a structure with these members
Use DialogBoxParam() (instead of DialogBox()) to invoke dialog box
Last parameter: pointer to structure
B. The WndProc()--
User clicks "Get Info" menu item (IDM_GET)
WndProc(): calls DialogBox() to invoke dialog box
Dialog box procedure name: InfoDlgProc
Return value saved in variable nRetVal
InfoDlgProc() will return 1 if user hits "OK", 0 if "Cancel"
Gets a DC, draw an empty rectangle to erase display area
If nRetVal is 1:
switch/case statement on nCurSel (set in InfoDlgProc())
Determines which list box position was selected
Copies appropriate salary message into string cBuf w/ lstrcpy()
Calls TextOut() to display name & appropriate salary message
If nRetVal is 0:
Calls TextOut() to display "No Response!" string
C. The InfoDlgProc() dialog box procedure--
Dialog box created by WndProc()'s call to DialogBox()
WM_INITDIALOG message to dialog box window
InfoDlgProc():
Calls SendDlgItemMessage() to send following messages:
RESETCONTENT to IDC_LISTSALARY listbox
Assures it's empty initially
lParam and the wParam both 0
four LB_ADDSTRING messages to listbox
lParam = each of four strings in a salary[][] array
Will be items appearing in listbox when dialog box appears
User clicks dialog box "OK" button
WM_COMMAND message, ID=IDOK to dialog box
Want to get contents of edit control and list box item selected:
InfoDlgProc():
Calls SendDlgItemMessage() to send message:
EM_GETLINE to IDC_EDITNAME edit control
(Gets text from edit control & copies into local cBuf)
Calls lstrcpy() to copy it into name[] global variable
Calls SendDlgItemMessage() to send message:
LB_GETCURSEL to IDC_LISTSALARY list box
(Returns position of currently-selected list box item)
Stores value in nCurSel global variable
Calls EndDialog()
Second parameter = 1, returned to WndProc()
Terminates and destroys dialog box
User clicks dialog box "Cancel" button
WM_COMMAND message, IDCANCEL to dialog box
InfoDlgProc() calls EndDialog()
Second parameter = 0, returned to WndProc()
Terminates and destroys dialog box
List box and edit control data: purely strings
To store non-string data--must format it:
Can use wsprintf()
Example: value of n to edit control IDC_EDIT in dialog box w/ handle hDlg--
int n=95;
char cBuf[]=" "; // A temporary string buffer
wsprintf(cBuf,"%3d",n); // Format n as a string in cBuf
SendDlgItemMessage(hDlg, IDC_EDIT, WM_SETTEXT,
0, (LPARAM)cBuf); //send it
wsprintf() can't format floating point or double precision variables
Use C library function sprintf()
Example: Edit control IDC_EDIT in dialog box w/ handle hDlg--
Supposedly contains a "decimal integer" (e.g., a test grade)
Want to extract contents of edit control & store as integer (grade)--
int grade;
char cBuf=" ";
SendDlgItemMessage(hDlg, DLI_EDIT, EM_GETLINE,
0, (LPARAM)cBuf); // get string
sscanf(cBuf,"%3d",&grade); // convert to integer
MODELESS DIALOG BOXES--
Popup windows that remain on screen for extended periods
Allow user to switch to other windows
Frequently used for small "tool" windows, movable on screen
Defined in a resource template (like modal dialog box)
(No special style)
Use different functions to create dialog box and make it visible on screen:
CreateDialog() instead of DialogBox()
CreateDialogParam() instead of DialogBoxParam()
Messages for modeless dialog boxes sent to the parent window
Modify main program's msg loop to divert messages to dialog box function
(if the message is intended for the dialog box)
IsDialogMessage(hDlg, &msg) does diverting
Determines if message is intended for specified dialog box
If so, dispatches it to dialog box's message-processing function
Returns TRUE if message was processed by dialog box function
Message should not be dispatched to the main window's WndProc()
So main message loop should be modified--
HWND hModeless=NULL; /* modeless dialog box window handle */
while (GetMessage(&msg, NULL, 0, 0))
if (hModeless == NULL || !IsDialogMessage(hModeless, &msg))
{
TranslateMessage(&msg);
DispatchMessage (&msg);
}
To remove a modeless dialog box--
Use DestroyWindow() instead of EndDialog()
Modeless dialog boxes should contain a system menu button
User can close by double clicking that button
Sends a WM_CLOSE message to dialog box function
To make the modeless dialog vanish:
Call DestroyWindow()--
case WM_CLOSE:
DestroyWindow(hDlg);
hModeless = NULL;
return(TRUE);
COMMON DIALOG BOXES--
Standard dialog boxes in Windows that do things like:
Opening/saving files
Searching/replacing text
Choosing colors
Choosing fonts
Getting/changing information on printers
Windows contains a library of functions that invoke these dialog boxes
To display a common dialog box:
Call single function from library
Don't have to set up a .rc template
Don't have to write a dialog box procedure
COMMDLG.DLL provides:
Standard dialog box template
Default dialog box procedure
Processes messages from the dialog box controls
COMMDLG.H header file must be included
Defines the common dialog box functions
Structures necessary to use dialog boxes
Steps in Setting Up and Using a Common Dialog box--
(All common dialog box library functions used in the same way)
-Initialize fields of a structure with data needed by dialog box
-Set up pointer to structure in library function
-Call library function, passing it the pointer
-Library function creates/displays dialog box
-User interacts with dialog box and causes it to be removed
-Library function returns control to application
-Application retrieves information returned in structure
Some Common Dialog Box functions (check online help for details):
ChooseColor(CHOOSECOLOR* cc)--
Displays dialog box with palette of available colors
Allows user to choose one and/or create a new one
rgbResult member of cc will contain the RGB values of color selected
ChooseFont(CHOOSEFONT* cf)--
Displays dialog box with lists of available fonts, point sizes
User selects font, sample text is displayed
Member variables of cf will contain information on font selected
GetOpenFileName(OPENFILENAME* ofn) / GetSaveFileName(OPENFILENAME* ofn)--
Each displays dialog box with list of file names, directories, drives
(in familiar Windows "Open"/"Save" format)
User indicates which file to open/save
lpstrFile member of ofn will contain:
drive designator, path, filename, extension of selected file
(Example later)
FindText(FINDREPLACE* ft)--
Displays dialog box with an edit control
User can use it to search for (and optionally replace) a string
See the Petzold COLORS3.C for simple example of using ChooseColor common dialog box