一、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资源描述中显示的顺序单击每一个控件。