- Article
- 13 minutes to read
You use dialog boxes to display information and solicit user input. Your application loads and initializes the dialog box, processes user input, and destroys the dialog box when the user completes the task. The process for editing dialogs varies depending on whether the dialog is modal or modeless. A modal dialog requires the user to close the dialog before activating another window in the application. However, the user can activate windows in different applications. A modeless dialog does not require an immediate response from the user. It resembles a main window that contains controls.
The following sections explain how to use both types of dialog boxes.
- Display a message box
- Creating a modal dialog
- Creating a modeless dialog box
- Initialize a dialog box
- Creating an in-memory model
Display a message box
The simplest form of a modal dialog is the message box. Most applications use message boxes to notify the user of errors and ask for instructions on what to do after an error occurs. You create a message box with themessage boxorMessageBoxExFunction that specifies the message and the number and type of buttons to display. The system creates a modal dialog that provides its own dialog template and procedure. After the user closes the message box,message boxorMessageBoxExreturns a value identifying the user-chosen button to close the message box.
In the following example, the application displays a message box prompting the user for action after an error condition occurs. The message box displays the message that describes the error condition and how to resolve it. theMB_JANEINstyle guidesmessage boxProvide two buttons for the user to choose how to proceed:
int DisplayConfirmSaveAsMessageBox(){ int msgboxID = MessageBox( NULL, L"temp.txt already exists.\nDo you want to replace it?", L"Confirm Save As", MB_ICONEXCLAMATION | MB_YESNO ); if (msgboxID == IDYES) { // TODO: add code } return msgboxID; }
The following image shows the output of the previous code sample:
Creating a modal dialog
You create a modal dialog with thedialog boxOccupation. You must supply the identifier or name of a dialog template resource and a pointer to the dialog box procedure. thedialog boxThe function loads the model, displays the dialog, and processes all user input until the user closes the dialog.
In the following example, the application displays a modal dialog when the user clicksDelete itemfrom an application menu. The dialog contains an edit control (where the user enters the name of an item) andOKeCancelKeys. The control identifiers for these controls are ID_ITEMNAME, IDOK, and IDCANCEL, respectively.
The first part of the example consists of the statements that create the modal dialog box. These statements in the window procedure for the main application window create the dialog box when the system receives aWM_COMMANDMessage with menu ID IDM_DELETEITEM. The second part of the example is the dialog box procedure that retrieves the contents of the edit control and closes the dialog box upon receipt of aWM_COMMANDMessage.
The following statements create the modal dialog box. The dialog template is a resource in the application executable and has the resource ID DLG_DELETEITEM.
case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_DELETEITEM: if (DialogBox(hinst, MAKEINTRESOURCE(DLG_DELETEITEM), hwnd, (DLGPROC)DeleteItemProc)==IDOK) { // complete the command; szItemName contains the // name of the item to be deleted. } else { // Cancel the command. } break; } return 0L;
In this example, the application specifies its main window as the window that owns the dialog box. When the system initially displays the dialog box, its position is relative to the upper-left corner of the client area of the owner window. The application uses the return value ofdialog boxto decide whether to continue or abort the operation. The following statements define the dialog box procedure.
char szItemName[80]; // gets the name of the element to be deleted. BOOL CALLBACK DeleteItemProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if (!GetDlgItemText(hwndDlg, ID_ITEMNAME, szItemName, 80)) *szItemName=0; // Stand out. case IDCANCEL: EndDialog(hwndDlg, wParam); returns TRUE; } } returns false; }
In this example, the procedure usesGetDlgItemTextto retrieve the current text of the edit control identified by ID_ITEMNAME. The procedure then calls theEndDialogFunction to set the return value of the dialog to IDOK or IDCANCEL depending on the received message and start the process of closing the dialog. The identifiers IDOK and IDCANCEL correspond to thisOKeCancelKeys. After procedure callsEndDialog, the system sends additional messages to the procedure to destroy the dialog and returns the dialog's return value to the function that created the dialog.
Creating a modeless dialog box
You create a modeless dialog box with theCreateDialogFunction that specifies the identifier or name of a dialog template resource and a pointer to the dialog box procedure.CreateDialogloads the template, creates the dialog box, and optionally displays it. Your application is responsible for retrieving and sending user input messages to the dialog box procedure.
In the following example, the app displays a modeless dialog—if it's not already displayed—when the user clicksGo tofrom an application menu. The dialog box contains an edit control, a check box, andOKeCancelKeys. The dialog template is a resource in the application's executable and has the resource identifier DLG_GOTO. The user enters a line number in the edit control and selects the check box to indicate that the line number is relative to the current line. The control identifiers are ID_LINE, ID_ABSREL, IDOK and IDCANCEL.
The instructions in the first part of the example create the modeless dialog box. These statements in the window procedure for the main application window create the dialog box when the window procedure receives aWM_COMMANDMessage with the menu identifier IDM_GOTO, but only if the global variable does not already contain a valid identifier. The second part of the example is the application's main message loop. The circuit includesIsDialogMessageFunction to ensure that the user can use the dialog keyboard interface in this modeless dialog. The third part of the example is the dialog box procedure. The procedure retrieves the contents of the edit control and check box when the user clicksOKButton. The procedure destroys the dialog box when the user clicks theCancelKnopf.
HWND hwndGoto = NULL; // Handhabung des Dialogfensters ...case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_GOTO: if (!IsWindow(hwndGoto)) { hwndGoto = CreateDialog(hinst, MAKEINTRESOURCE(DLG_GOTO), hwnd, (DLGPROC )GoToProc ); ShowWindow(hwndGoto, SW_SHOW); } brechen; } gib 0L zurück;
In previous statementsCreateDialogonly called ifhwndGoto
does not contain a valid window handle. This ensures that the application does not display two dialogs at the same time. To support this verification method, the dialog method must be defined asNULLif you destroy the dialog box.
The message loop for an application consists of the following statements.
BOOL bRet;while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if (bRet == -1) { // Tratar oder error and possible sair } else if (!IsWindow(hwndGoto) || !IsDialogMessage(hwndGoto, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
The loop checks the window handle for the dialog for validity and only calls theIsDialogMessageFunction if identifier is valid.IsDialogMessageprocesses the message only if it belongs to the dialog box. Otherwise it returnsNOT CORRECTand the loop sends the message to the appropriate window.
The following statements define the dialog box procedure.
int iLine; // Get row number.BOOL fRelative; // Get the status of the checkbox. BOOL CALLBACK GoToProc (HWND hwndDlg, Message UINT, WPARAM wParam, LPARAM lParam) { BOOL fError; switch (message) { case WM_INITDIALOG: CheckDlgButton(hwndDlg, ID_ABSREL, fRelative); returns TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: fRelative = IsDlgButtonChecked(hwndDlg, ID_ABSREL); iLine = GetDlgItemInt(hwndDlg, ID_LINE, &fError, fRelative); if (fError) { MessageBox (hwndDlg, SZINVALIDNUMBER, SZGOTOERR, MB_OK); SendDlgItemMessage(hwndDlg, ID_LINE, EM_SETSEL, 0, -1L); } else // Notifies the window owner to run the task. returns TRUE; case IDCANCEL: DestroyWindow(hwndDlg); hwndGoto = NULL; returns TRUE; } } returns false; }
In the previous statements, the procedure handles theWM_INITDIALOGeWM_COMMANDposts. DuringWM_INITDIALOGOn processing, the procedure initializes the check box by passing the current value of the global variable toCheckDlgButton. The procedure then returnsTRUTHto tell the system to set the default input focus.
DuringWM_COMMANDProcessing, the procedure closes the dialog box only when the user clicks the buttonCancelbutton — i.e. the button with the identifier IDCANCEL. The procedure must callDestroyWindowto close a modeless dialog box. Note that the procedure also defines the variable asNULLto ensure that other statements that depend on this variable work correctly.
When the user clicks on theOKbutton, the procedure retrieves the current state of the check box and assigns it to thefRelativoVariable. It then uses the variable to get the line number of the edit control.GetDlgItemIntconverts the text in the edit control to an integer. The value offRelativodetermines whether the function interprets the number as a signed or unsigned value. If the text of the edit control is not a valid number,GetDlgItemIntDefine o braveryfErroVariable on non-zero. The procedure checks this value to determine whether to display an error message or run the task. On error, the dialog procedure sends a message to the edit control, instructing it to select the text in the control so the user can easily replace it. ifGetDlgItemIntreturns no error, the procedure can perform the requested task itself or send a message to the owning window instructing it to perform the operation.
Initialize a dialog box
You initialize the dialog box and its contents while processing theWM_INITDIALOGMessage. The most common task is to initialize the controls to reflect the current dialog box settings. Another common task is to center a dialog on the screen or in the owner window. A useful task for some dialog boxes is to set the input focus to a specific control instead of accepting the default input focus.
In the following example, the dialog box procedure centers the dialog box and sets the input focus when processingWM_INITDIALOGMessage. To center the dialog, the procedure retrieves the window rectangles for the dialog and the owner window and calculates a new position for the dialog. To set the input focus, the procedure checks thewParamparameter to specify the identifier of the default input focus.
HWND hwndOwner; RECT rc, rcDlg, rcOwner; .... case WM_INITDIALOG: // Get the owner window and rectangles of the dialog. if ((hwndOwner = GetParent(hwndDlg)) == NULL) { hwndOwner = GetDesktopWindow(); } GetWindowRect(hwndOwner, &rcOwner); GetWindowRect(hwndDlg, &rcDlg); CopyRect(&rc, &rcOwner); // Move the owner and the dialog's rectangles so that the right and bottom values // represent the width and height, and then move the owner again // to discard the space occupied by the dialog. OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); OffsetRect(&rc, -rc.left, -rc.top); OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); // The new position is the sum of half the remaining space and // the owner's original position. SetWindowPos(hwndDlg, HWND_TOP, rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2), 0, 0, // ignore size arguments. SWP_NOSIZE); if (GetDlgCtrlID((HWND) wParam) != ID_ITEMNAME) { SetFocus(GetDlgItem(hwndDlg, ID_ITEMNAME)); returns false; } return TRUE;
In the previous instructions, the procedure uses theGetParentFunction to get the owner window handle for a dialog box. The function returns the owner window handle for dialogs and the main window handle for secondary windows. Because an application may create an unowned dialog box, the procedure examines the returned identifier and uses theGetDesktopWindowto get the desktop window handle if needed. After calculating the new position, the procedure uses theSetWindowPosto move the dialog box by specifying the HWND_TOP value to ensure the dialog box stays on top of the owner window.
Before setting input focus, the procedure checks the default input focus control handle. The system passes the default input focus window handle to thewParamParameter. DieGetDlgCtrlIDThe function returns the handle to the control identified by the window handle. If the identifier does not match the correct identifier, the procedure uses theDefinirFocoFunction to set the input focus. theGetDlgItemThe function is needed to get the window handle of the desired control.
Creating an in-memory model
Applications sometimes adjust or modify the contents of dialog boxes depending on the current state of the data being processed. In these cases, it is impractical to provide all possible dialog templates as resources in the application executable. However, creating in-memory templates gives the application more flexibility to adapt to any circumstance.
In the following example, the application creates an in-memory model for a modal dialog box that contains a message andOKeHelpKeys.
In a dialog template, all strings such as dialog and button titles must be Unicode strings. This example uses theMultiByteToWideChar-Function to generate these Unicode strings.
ÖDLGITEMTEMPLATEStructures in a dialog template must be alignedDWORDlimits. To align these structures, this example uses a helper routine that takes an input pointer and returns the next pointer that aligns with aDWORDBorder.
#define ID_HELP 150#define ID_TEXT 200LPWORD lpwAlign(LPWORD lpIn){ ULONG ul; ul = ( LONG ) lpIn ; ul++; ul >>=1; ul <<=1; return ( LPWORD ) ul ; } LRESULT DisplayMyMessage ( HINSTANCE hinst , HWND hwndOwner , LPSTR lpszMessage ) { HGLOBAL hgbl ; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTRlpwsz; LRESULT right; int character; hgbl = GlobalAlloc(GMEM_ZEROS, 1024); see (!hgbl) return -1; lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Define a dialog box. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION; lpdt->cdit = 3; // number of checks lpdt->x = 10; lpdt -> y = 10 ; lpdt->cx = 100; lpdt -> cy = 100 ; lpw = (LPWORD)(lpdt+1); *lpw++ = 0; // sem menu *lpw++ = 0; // Predefined dialog box class (by pattern) lpwsz = (LPWSTR)lpw; nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "My Dialog", -1, lpwsz, 50); lpw += characters; //------------------------------------ // Define an OK button. //------------------------------------ lpw = lpwAlign(lpw); // define DLGITEMPLATE without limit DWORD lpdit = (LPDLGITEMPLATE)lpw; lpdit->x = 10; lpdit -> y = 70 ; lpdit->cx = 80; lpdit -> cy = 20 ; lpdit->id = ID; // identifier of the OK button lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR)lpw; nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "OK", -1, lpwsz, 50); lpw += characters; *lpw++ = 0; // No rolling //---------------------- // Define a help button. //------------------------------------ lpw = lpwAlign(lpw); // define DLGITEMPLATE without limit DWORD lpdit = (LPDLGITEMPLATE)lpw; lpdit->x = 55; lpdit -> y = 10 ; lpdit->cx = 40; lpdit -> cy = 20 ; lpdit->id = HELP_ID; // Help button identifier lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class atom lpwsz = (LPWSTR)lpw; nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "help", -1, lpwsz, 50); lpw += characters; *lpw++ = 0; // No parent cubes //------------------------------- // Defines a static text control. //------------------------------------ lpw = lpwAlign(lpw); // define DLGITEMPLATE without limit DWORD lpdit = (LPDLGITEMPLATE)lpw; lpdit->x = 10; lpdit -> y = 10 ; lpdit->cx = 40; lpdit -> cy = 20 ; lpdit->id = TEXT_ID; // Text identifier lpdit->style = WS_CHILD | WS_VISIBLE | SS_SQUARE; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // Static class for (lpwsz = (LPWSTR)lpw;*lpwsz++=(WCHAR)*lpszMessage++;); lpw = ( LPWORD ) lpwsz ; *lpw++ = 0; // Sem Breeding Cube GlobalUnlock(hgbl); ret = DialogBoxIndirect(hint, (LPDLGTEMPLATE)hgbl, handOwner, (DLGPROC)DialogProc); GlobalFree ( hgbl ); return ret; } }