A Quick Introduction To Win32 Dialogs
written by Fresh
This article:
- Introduction
- Part one - Basic dialog boxes, and basic messages
* Theory
* Implementation
- Part two - Source code
Introduction: A dialog box application - the simplest, most useful form
of Win32 applications
In this article I will talk about creating basic, modal dialog box applications. I will not talk about modeless dialogs, nor custom window classes, sorry...
Usually I prefer using dialog boxes for most of my programs, since dialog boxes are very customizable and very convenient to manipulate, unlike regular windows. I'm sure you'll understand this after making your first dialog box and see how simple it is!
Now, let's get to business...
Part one - Basic dialog boxes, and basic messages
The structure of a dialog application (very roughly)
- WinMain(): The main function of every windows program, accepting 4 parameters, (refer to Cali's introduction to Win32 programming for further explanation)
WinMain() is incharge of -
* General initialization
* (Optional) Registering a custom WNDCLASS(EX)
* Executing DialogBox() (or another dialog function, i.e.
DialogBoxParam)
* The function creates the dialog, accepting 4 parameters:
- HINSTANCE: Handle to the application instance.
- LPCSTR: Identifies dialog box template, you can use the MAKEINTRESOURCE() macro
to make this value.
- HWND: The handle of the parent window. If your dialog has no parent, this value
should be NULL.
- DLGPROC: A pointer to your dialog box procedure.
*** NOTE: In dialog application there's no need for a message loop!
- The dialog box procedure: Handles the messages sent to
your dialog box.
* The procedure is defined as
"LRESULT CALLBACK" (although "LONG FAR PASCAL" still works).
* This procedure is given 4 parameters:
- HWND: A handle to the dialog box that received the message.
- UINT: The
message (WM_* etc.).
- WPARAM:
Message-dependent info.
- LPARAM: More
message-dependent info.
* The procedure's basic structure is just a default handler which returns FALSE, e.g. letting Windows do default actions to handle the message.
* Additional
uses can be:
- Handling
WM_INITDIALOG to initialize the dialog and/or controls.
- Handling WM_COMMAND
to handle messages from controls/menus.
- Handling WM_DESTROY
to do cleanup before quitting.
*** NOTE: If you process those messages you should return TRUE in the end, so Windows knows you have processed it.
Messages
There are hundreds of messages that could be sent to your dialog procedure, most of them handled by Windows' default handler. You'll probably want to handle at least three of the messages:
WM_INITDIALOG: This message is sent immediatly before the dialog box is displayed. This is usually used to initialize controls and carry out any tasks that affect the dialog box appearence.
WM_COMMAND: This message is sent when the user selects a menu, or when a control sends a notification message to its parent window.
WM_DESTROY: This message is sent when the dialog is being destroyed, after removing it from the screen. Use this to uninitialize and deallocate everything.
Controls
The controls are: Check boxes, Radio boxes, Static text, Scroll bars, Edit boxes, Bitmaps, Combo boxes, List boxes, and Group boxes.
Every control has its own unique messages, and some it shares with others. To find the message you're looking for, look in the Win32 Programmer's Reference.
Appendix: Closing the dialog box, and ending the program
After the user chooses to exit, either by using a control or just pressing the X or Alt+F4 (which causes a WM_COMMAND with IDCANCEL message to be sent), you should close the dialog box, then do some clean-up if needed.
Closing - You close the dialog box immediately after receiving the user's message. This is done by EndDialog, given the following parameters:
* HWND: Handle of the dialog box to close.
* int:
Value to return (in 'classic' programming, return zero for failure, non-zero for
success.).
Clean-up - You should do the clean-up (if you need to) only on the WM_DESTROY message. free() any malloc()'ated memory, delete any temporary files, delete device contexts, flush memory to disk and so on.
Okay, time to do something for real!
Create a new project... I'll call it 'TutApp', choose Win32 Application as the type.
*** NOTE: I am using Microsoft Visual C++ 5.0, but I'm sure it'll work with any other compiler as well.
I always start with creating the UI (User Interface) e.g.
the dialog itself.
Now, select Project->Add To Project->New..., create a new Resource Script, I
called it TutApp.rc. Now, go to 'Resources' and insert a new dialog. Edit the properties,
and change the ID into IDD_DIALOG (that's how I called it, of course you can change it but
you need to change all the references in the source code). Also change the caption into
'Dialog Box Example'.
*** NOTE: MSVC++ automatically creates a file called 'resource.h' which includes the resource symbols. If your compiler does not, you'll have to do it manually, by using #define's, for example '#define IDD_DIALOG 101'.
Okay, now rename the OK button into '&Click Me' using the properties dialog. Rename the Cancel button to '&Exit'. Now edit the Click Me to have the ID 'IDC_CLICKME'. Now that we're done with the unimportant stuff ;), we can start coding!
Select Project->Add To Project->New..., and create a new C/C++ source file, and name it 'TutApp.c' (I'm awfully creative today :). The commented source code is right below, no more explanations needed...
Part Two - Source code
/*
TutApp.C
Source code for a skeleton dialog box example
All rights reserved to Fresh (c)
You can use this code for any purpose you want, don't worry ;-)
*/
#include <windows.h> // the basic include file for
all Win32 programs
//#include <windowsx.h> not needed in our case, useful in 'real' programs
#include "resource.h" // the resource symbols file MSVC++ created for us
const char AppName[] = "Dialog Box Example"; // the name of our program
HINSTANCE hInst; // a place to save our instance
// handle, which we may need later.
LRESULT CALLBACK DlgProc(HWND , UINT , WPARAM , LPARAM );
// declaring the dialog
// procedure
int WINAPI WinMain( // WinMain
HINSTANCE hInstance, // handle to the current instance
HINSTANCE hPrevInst, // handle to the previous instance
(Obsolete (0))
LPSTR lpCmdLine, // pointer to command line
int nCmdShow) // show state of window
{
hInst = hInstance; // save our instance handle
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG), NULL,
DlgProc); // start the dialog box
return TRUE; // success
}
LRESULT CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM
wParam, LPARAM lParam)
// the dialog procedure
{
switch(msg)
{
case
WM_INITDIALOG: // our dialog is being shown
MessageBox(hwnd,
"Received WM_INITDIALOG message", AppName, MB_OK | MB_ICONINFORMATION);
break;
case WM_COMMAND: // we got a message from a control/menu
// in this case, a button
switch(LOWORD(wParam))
{
case IDC_CLICKME: // the '&Click Me' button
MessageBox(hwnd, "Received
WM_COMMAND message from button", AppName, MB_OK | MB_ICONINFORMATION);
break;
case IDCANCEL: // user pressed either exit, the X on the top
// right, or used ALT+F4
MessageBox(hwnd, "Received IDCANCEL message.. Seeya!", AppName, MB_OK |
MB_ICONINFORMATION);
EndDialog(hwnd, FALSE); // our job is done, goodbye dear dialog
break;
}
break;
case
WM_DESTROY: // dialog is off the screen by now
MessageBox(hwnd, "Received WM_DESTROY message, time for clean-up...", AppName,
MB_OK | MB_ICONINFORMATION);
break;
default:
// all the messages we don't handle
// are handled by Windows
return
FALSE; // this means we haven't processed it
}
return TRUE; // this one means we have processed the message
}
// EOF