A More Complex Dialog Box

The simple dialog box in ABOUT1 demonstrates the basics of getting a dialog box up and running; now let's try something a little more complex. The ABOUT2 program, shown in Figure 10-3, demonstrates how to manage controls (in this case, radio buttons) within a dialog box procedure and also how to paint on the client area of the dialog box.

ABOUT2.MAK

#----------------------

# ABOUT2.MAK make file

#----------------------

about2.exe : about2.obj about2.def about2.res

link about2, /align:16, NUL, /nod slibcew libw, about2

rc about2.res

about2.obj : about2.c about2.h

cl -c -Gsw -Ow -W2 -Zp about2.c

about2.res : about2.rc about2.h about2.ico

rc -r about2.rc

ABOUT2.C

/*------------------------------------------

ABOUT2.C -- About Box Demo Program No. 2

(c) Charles Petzold, 1990

------------------------------------------*/

#include <windows.h>

#include "about2.h"

long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;

short nCurrentColor = IDD_BLACK,

nCurrentFigure = IDD_RECT ;

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,

LPSTR lpszCmdLine, int nCmdShow)

{

static char szAppName [] = "About2" ;

MSG msg ;

HWND hwnd ;

WNDCLASS wndclass ;

if (!hPrevInstance)

{

wndclass.style = CS_HREDRAW | CS_VREDRAW ;

wndclass.lpfnWndProc = WndProc ;

wndclass.cbClsExtra = 0 ;

wndclass.cbWndExtra = 0 ;

wndclass.hInstance = hInstance ;

wndclass.hIcon = LoadIcon (hInstance, szAppName) ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;

wndclass.lpszMenuName = szAppName ;

wndclass.lpszClassName = szAppName ;

RegisterClass (&wndclass) ;

}

hwnd = CreateWindow (szAppName, "About Box Demo Program",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, nCmdShow) ;

UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

}

void PaintWindow (HWND hwnd, short nColor, short nFigure)

{

static DWORD dwColor [8] = { RGB (0, 0, 0), RGB ( 0, 0, 255),

RGB (0, 255, 0), RGB ( 0, 255, 255),

RGB (255, 0, 0), RGB (255, 0, 255),

RGB (255, 255, 0), RGB (255, 255, 255) } ;

HBRUSH hBrush ;

HDC hdc ;

RECT rect ;

hdc = GetDC (hwnd) ;

GetClientRect (hwnd, &rect) ;

hBrush = CreateSolidBrush (dwColor [nColor - IDD_BLACK]) ;

hBrush = SelectObject (hdc, hBrush) ;

if (nFigure == IDD_RECT)

Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom) ;

else

Ellipse (hdc, rect.left, rect.top, rect.right, rect.bottom) ;

DeleteObject (SelectObject (hdc, hBrush)) ;

ReleaseDC (hwnd, hdc) ;

}

void PaintTheBlock (HWND hCtrl, short nColor, short nFigure)

{

InvalidateRect (hCtrl, NULL, TRUE) ;

UpdateWindow (hCtrl) ;

PaintWindow (hCtrl, nColor, nFigure) ;

}

BOOL FAR PASCAL AboutDlgProc (HWND hDlg, WORD message, WORD wParam, LONG lParam)

{

static HWND hCtrlBlock ;

static short nColor, nFigure ;

switch (message)

{

case WM_INITDIALOG :

nColor = nCurrentColor ;

nFigure = nCurrentFigure ;

CheckRadioButton (hDlg, IDD_BLACK, IDD_WHITE, nColor) ;

CheckRadioButton (hDlg, IDD_RECT, IDD_ELL, nFigure) ;

hCtrlBlock = GetDlgItem (hDlg, IDD_PAINT) ;

SetFocus (GetDlgItem (hDlg, nColor)) ;

return FALSE ;

switch (message)

{

case WM_CREATE :

hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;

lpfnAboutDlgProc = MakeProcInstance (AboutDlgProc, hInstance) ;

return 0 ;

case WM_COMMAND :

switch (wParam)

{

case IDM_ABOUT :

if (DialogBox (hInstance, "AboutBox", hwnd,

lpfnAboutDlgProc))

InvalidateRect (hwnd, NULL, TRUE) ;

return 0 ;

}

break ;

case WM_PAINT :

BeginPaint (hwnd, &ps) ;

EndPaint (hwnd, &ps) ;

PaintWindow (hwnd, nCurrentColor, nCurrentFigure) ;

return 0 ;

case WM_DESTROY :

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, message, wParam, lParam) ;

}

ABOUT2.RC

/*---------------------------

ABOUT2.RC resource script

---------------------------*/

#include <windows.h>

#include "about2.h"

about2 ICON about2.ico

About2 MENU

{

POPUP "&Help"

{

MENUITEM "&About About2...", IDM_ABOUT

}

}

#define TABGRP (WS_TABSTOP | WS_GROUP)

AboutBox DIALOG 20, 20, 140, 188

STYLE WS_POPUP | WS_DLGFRAME

{

CTEXT "About2" -1, 0, 12, 140, 8

ICON "About2" -1, 8, 8, 0, 0

CTEXT "About Box Demo Program" -1, 4, 36, 130, 8

CTEXT "" IDD_PAINT, 68, 54, 60, 60

GROUPBOX "&Color" -1, 4, 50, 54, 112

RADIOBUTTON "&Black" IDD_BLACK, 8, 60, 40, 12, TABGRP

RADIOBUTTON "B&lue" IDD_BLUE, 8, 72, 40, 12

RADIOBUTTON "&Green" IDD_GREEN, 8, 84, 40, 12

RADIOBUTTON "Cya&n" IDD_CYAN, 8, 96, 40, 12

RADIOBUTTON "&Red" IDD_RED, 8, 108, 40, 12

RADIOBUTTON "&Magenta" IDD_MAGENTA, 8, 120, 40, 12

RADIOBUTTON "&Yellow" IDD_YELLOW, 8, 132, 40, 12

RADIOBUTTON "&White" IDD_WHITE, 8, 144, 40, 12

GROUPBOX "&Figure" -1, 68, 120, 60, 40, WS_GROUP

RADIOBUTTON "Rec&tangle" IDD_RECT, 72, 134, 50, 12, TABGRP

RADIOBUTTON "&Ellipse" IDD_ELL, 72, 146, 50, 12

DEFPUSHBUTTON "OK" IDOK, 20, 168, 40, 14, WS_GROUP

PUSHBUTTON "Cancel" IDCANCEL, 80, 168, 40, 14, WS_GROUP

}

ABOUT2.H

/*----------------------

ABOUT2.H header file

----------------------*/

#define IDM_ABOUT 1

#define IDD_BLACK 10

#define IDD_BLUE 11

#define IDD_GREEN 12

#define IDD_CYAN 13

#define IDD_RED 14

#define IDD_MAGENTA 15

#define IDD_YELLOW 16

#define IDD_WHITE 17

#define IDD_RECT 20

#define IDD_ELL 21

#define IDD_PAINT 30

ABOUT2.ICO

FIG 1003.EPB

ABOUT2.DEF

;-----------------------------------

; ABOUT2.DEF module definition file

;-----------------------------------

NAME ABOUT2

DESCRIPTION 'About Box Demo No. 2 (c) Charles Petzold, 1990'

EXETYPE WINDOWS

STUB 'WINSTUB.EXE'

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE MULTIPLE

HEAPSIZE 1024

STACKSIZE 8192

EXPORTS WndProc

AboutDlgProc

The About box in ABOUT2 has two groups of radio buttons. One group is used to select a color, and the other group is used to select either a rectangle or an ellipse. The rectangle or ellipse is shown in the dialog box with the interior colored with the current color selection. If you press the OK button, the dialog box is ended, and the program's window procedure draws the selected figure on its own client area. If you press Cancel, the client area of the main window remains the same. The dialog box is shown in Figure 10-4 on the following page. Although the ABOUT2 dialog box uses the predefined identifiers IDOK and IDCANCEL for the two push buttons, each of the radio buttons has its own identifier beginning with the letters IDD (”ID for dialog box control“). These identifiers are defined in ABOUT2.H.