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