一、Windows模态对话框—更复杂的对话框
ABOUT1中的简单对话框展示了设计和执行一个对话框的要点,现在让我们来看一个稍微复杂的例子。程序11-2给出的ABOUT2程序展示了如何在对话框程序中管理控件(这里用单选按钮)以及如何在对话框的显示区域中绘图。
        
ABOUT2.C
        
/*--------------------------------------------------------------------------
        
  ABOUT2.C --     About Box Demo Program No. 2
        
                                        (c) Charles Petzold, 1998
        
---------------------------------------------------------------------------*/
        
#include <windows.h>
        
#include "resource.h"
        
LRESULT     CALLBACK WndProc                     (HWND, UINT, WPARAM, LPARAM) ;
        
BOOL               CALLBACK AboutDlgProc         (HWND, UINT, WPARAM, LPARAM) ;
        
   
        
int iCurrentColor         = IDC_BLACK,
        
   iCurrentFigure        = IDC_RECT ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                                                 PSTR szCmdLine, int iCmdShow)
        
{
        
           static TCHAR          szAppName[] = TEXT ("About2") ;
        
           MSG                                          msg ;
        
           HWND                                         hwnd ;
        
           WNDCLASS                             wndclass ;
        
   
        
           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                       = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
        
           wndclass.lpszMenuName                        = szAppName ;
        
           wndclass.lpszClassName                       = szAppName ;
        
   
        
           if (!RegisterClass (&wndclass))
        
           {
        
                  MessageBox (  NULL, TEXT ("This program requires Windows NT!"),
        
                                         szAppName, MB_ICONERROR) ;
        
            return 0 ;
        
    }
        
   
        
           hwnd = CreateWindow ( szAppName, TEXT ("About Box Demo Program"),
        
                                 WS_OVERLAPPEDWINDOW,
        
                                  CW_USEDEFAULT, CW_USEDEFAULT,
        
                                  CW_USEDEFAULT, CW_USEDEFAULT,
        
                                  NULL, NULL, hInstance, NULL) ;   
        
           ShowWindow (hwnd, iCmdShow) ;
        
           UpdateWindow (hwnd) ;
        
   
        
           while (GetMessage (&msg, NULL, 0, 0))
        
           {
        
                          TranslateMessage (&msg) ;
        
                          DispatchMessage (&msg) ;
        
    }
        
  return msg.wParam ;
        
}
        
void PaintWindow (HWND hwnd, int iColor, int iFigure)
        
{
        
           static COLORREF crColor[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 (crColor[iColor - IDC_BLACK]) ;
        
           hBrush = (HBRUSH) SelectObject (hdc, hBrush) ;
        
   
        
           if (iFigure == IDC_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, int iColor, int iFigure)
        
{
        
           InvalidateRect (hCtrl, NULL, TRUE) ;
        
           UpdateWindow (hCtrl) ;
        
           PaintWindow (hCtrl, iColor, iFigure) ;
        
}
        
LRESULT CALLBACK WndProc ( HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
        
{
        
           static HINSTANCE              hInstance ;
        
           PAINTSTRUCT                          ps ;
        
   
        
           switch (message)
        
    {
        
           case   WM_CREATE:
        
                  hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
        
                  return 0 ;
        
        
        
           case   WM_COMMAND:
        
                  switch (LOWORD (wParam))
        
                  {
        
                  case IDM_APP_ABOUT:
        
                                         if (DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc))
        
                                                 InvalidateRect (hwnd, NULL, TRUE) ;
        
                                         return 0 ;
        
                  }
        
                  break ;
        
        
        
           case   WM_PAINT:
        
                  BeginPaint (hwnd, &ps) ;
        
                  EndPaint (hwnd, &ps) ;
        
             
        
                  PaintWindow (hwnd, iCurrentColor, iCurrentFigure) ;
        
                  return 0 ;
        
             
        
           case   WM_DESTROY:
        
                  PostQuitMessage (0) ;
        
                  return 0 ;
        
           }
        
  return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        
BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
        
{
        
           static HWND   hCtrlBlock ;
        
           static int            iColor, iFigure ;
        
   
        
           switch (message)
        
           {
        
           case   WM_INITDIALOG:
        
                  iColor               = iCurrentColor ;
        
                  iFigure               = iCurrentFigure ;
        
                  CheckRadioButton (hDlg, IDC_BLACK, IDC_WHITE,   iColor) ;
        
                  CheckRadioButton (hDlg, IDC_RECT,  IDC_ELLIPSE, iFigure) ;
        
        
        
                  hCtrlBlock = GetDlgItem (hDlg, IDC_PAINT) ;
        
       
        
                 SetFocus (GetDlgItem (hDlg, iColor)) ;
        
                  return FALSE ;
        
        
        
           case   WM_COMMAND:
        
                  switch (LOWORD (wParam))
        
                  {
        
                  case   IDOK:
        
                                         iCurrentColor         = iColor ;
        
                                       iCurrentFigure        = iFigure ;
        
                                         EndDialog (hDlg, TRUE) ;
        
                                         return TRUE ;
        
             
        
                  case   IDCANCEL:
        
                                         EndDialog (hDlg, FALSE) ;
        
                                         return TRUE ;
        
             
        
                 case   IDC_BLACK:
        
                  case   IDC_RED:
        
                  case   IDC_GREEN:
        
                  case   IDC_YELLOW:
        
                  case   IDC_BLUE:
        
                  case   IDC_MAGENTA:
        
                  case   IDC_CYAN:
        
                  case   IDC_WHITE:
        
                                         iColor = LOWORD (wParam) ;
        
                                         CheckRadioButton (hDlg, IDC_BLACK, IDC_WHITE, LOWORD (wParam)) ;
        
                                         PaintTheBlock (hCtrlBlock, iColor, iFigure) ;
        
                                         return TRUE ;
        
             
        
                  case   IDC_RECT:
        
                  case   IDC_ELLIPSE:
        
                                         iFigure = LOWORD (wParam) ;
        
                                         CheckRadioButton (hDlg, IDC_RECT, IDC_ELLIPSE, LOWORD (wParam)) ;
        
                                         PaintTheBlock (hCtrlBlock, iColor, iFigure) ;
        
                                         return TRUE ;
        
                  }
        
                  break ;
        
        
        
           case   WM_PAINT:
        
                  PaintTheBlock (hCtrlBlock, iColor, iFigure) ;
        
                break ;
        
           }
        
           return FALSE ;
        
}
        
        
//Microsoft Developer Studio generated resource script.
        
#include "resource.h"
        
#include "afxres.h"
        
/////////////////////////////////////////////////////////////////////////////
        
// Dialog
        
ABOUTBOX DIALOG DISCARDABLE  32, 32, 200, 234
        
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
        
FONT 8, "MS Sans Serif"
        
BEGIN
        
    ICON                                                     "ABOUT2",IDC_STATIC,7,7,20,20
        
    CTEXT         "About2",IDC_STATIC,57,12,86,8
        
    CTEXT         "About Box Demo Program",IDC_STATIC,7,40,186,8
        
    LTEXT         "",IDC_PAINT,114,67,74,72
        
    GROUPBOX                                     "&Color",IDC_STATIC,7,60,84,143
        
    RADIOBUTTON                          "&Black",IDC_BLACK,16,76,64,8,WS_GROUP | WS_TABSTOP
        
    RADIOBUTTON           "B&lue",IDC_BLUE,16,92,64,8
        
    RADIOBUTTON           "&Green",IDC_GREEN,16,108,64,8
        
    RADIOBUTTON           "Cya&n",IDC_CYAN,16,124,64,8
        
    RADIOBUTTON           "&Red",IDC_RED,16,140,64,8
        
    RADIOBUTTON           "&Magenta",IDC_MAGENTA,16,156,64,8
        
    RADIOBUTTON           "&Yellow",IDC_YELLOW,16,172,64,8
        
    RADIOBUTTON           "&White",IDC_WHITE,16,188,64,8
        
   GROUPBOX                                "&Figure",IDC_STATIC,109,156,84,46,WS_GROUP
        
    RADIOBUTTON                          "Rec&tangle",IDC_RECT,116,172,65,8,WS_GROUP | WS_TABSTOP
        
    RADIOBUTTON                          "&Ellipse",IDC_ELLIPSE,116,188,64,8
        
    DEFPUSHBUTTON                        "OK",IDOK,35,212,50,14,WS_GROUP
        
    PUSHBUTTON                                   "Cancel",IDCANCEL,113,212,50,14,WS_GROUP
        
END
        
/////////////////////////////////////////////////////////////////////////////
        
// Icon
        
ABOUT2        ICON         DISCARDABLE         "About2.ico"
        
/////////////////////////////////////////////////////////////////////////////
        
// Menu
        
ABOUT2      MENU DISCARDABLE
        
BEGIN
        
   POPUP "&Help"
        
   BEGIN
        
                  MENUITEM "&About",                   IDM_APP_ABOUT
        
   END
        
END
        
        
// Microsoft Developer Studio generated include file.
        
// Used by About2.rc
        
#define IDC_BLACK           1000
        
#define IDC_BLUE            1001
        
#define IDC_GREEN           1002
        
#define IDC_CYAN           1003
        
#define IDC_RED             1004
        
#define IDC_MAGENTA         1005
        
#define IDC_YELLOW          1006
        
#define IDC_WHITE           1007
        
#define IDC_RECT            1008
        
#define IDC_ELLIPSE         1009
        
#define IDC_PAINT           1010
        
#define IDM_APP_ABOUT       40001
        
#define IDC_STATIC          -1
        
| 
					 ABOUT2.ICO  | 
			

ABOUT2中的About框有两组单选按钮。一组用来选择颜色,另一组用来选择是矩形还是椭圆形。所选的矩形或者椭圆显示在对话框内,其内部以目前选择的颜色着色。使用者按下「OK」按钮后,对话框会终止,程序的窗口消息处理程序在它自己的显示区域内绘出所选图形。如果您按下「Cancel」,则主窗口的显示区域会保持原样。对话框如图11-2所示。尽管ABOUT2使用预先定义的标识符IDOK和IDCANCEL作为两个按键,但是每个单选按钮均有自己的标识符,它们以前缀IDC开头(用于控件的ID)。这些标识符在RESOURCE.H中定义。
	
当您在ABOUT2对话框中建立单选按钮时,请按显示顺序建立。这能保证Developer Studio依照顺序定义标识符的值,程序将使用这些值。另外,每个单选按钮都不要选中「Auto」选项。「Auto Radio Button」需要的程序代码较少,但基本上处理起来更深奥些。然后请依照ABOUT2.RC中的定义来设定它们的标识符。
选中「Properties」对话框中下列对象的「Group」选项:「OK」和「Cancel」按钮、「Figure」分组方块、每个分组方块中的第一个单选按钮(「Black」和「Rectangle」)。选中这两个单选按钮的「Tab Stop」复选框。
当您有全部控件在对话框中的近似位置和大小时,就可以从「Layout」菜单选择「Tab Order」选项。按ABOUT2.RC资源描述中显示的顺序单击每一个控件。
