第11章 对话框_11.1 模态对话框

对话框管理器——Windows内置的对话框代码

      ①负责创建对话框窗口及其上面的子窗口控件;在创建对话框函数的内部,Windows使用用户自定义的对话框模板,并且使用Windows内部定义的窗口类(一般类名是“#32770”)来创建对话框。

      ②提供内置的窗口过程来处理对话框消息(包括所有鼠标和键盘输入)

      ③内置的窗口过程会将消息传递给我们自定义的“对话框过程”(也叫“对话过程”)。

      ④对话框中,Windows负责处理在多个控件中转移输入焦点的相关逻辑。

11.1 模态对话框

11.1.1 对话框及其模板

(1)对话框的坐标单位——基于对话框所用的字体的大小(本例为“"MS Shell Dlg"”)

    X轴:以字符的平均宽度的1/4为单位。如x=32表示8个字符宽度处

    Y轴:以字符的平均高度的1/8为单位。如y=32表示4个字符高度处。

       ★一般字体的字符高度是宽度的两倍,所以X轴与Y轴的尺寸基本相同
       ★可通过MapDialogRect函数将字符为单位的坐标转换为对话框客户区的像素坐标。

(2)对话框模板

 ①STYLE语句与CreateWindow中的样式相似,模态对话框用WS_POPUP|DS_MODALFRAME

样式

功能

备注

WM_POPUP

弹出式窗口

模态对话框用WS_POPUP|DS_MODALFRAME

DS_MODALFRAME

去边框

WM_CAPTION

标题栏,允许移动对话框

CAPTION “DialogBox Caption”

SetWindowText(hDlg,TEXT(“对话框”));

WS_SYSMENU

添加系统菜单

允许Move或Close对话框

WS_THICKFRAME

允许改变对话框大小

等价于对话框Border属性中选择Resizing

②MNEU 菜单名  ——允许为对话框添加菜单

③FONT 字号,字体名称 ——发布程序要一起打包

④CLASS “类名”

   A、没指定窗口类名时——Windows会自动提供一个特殊的窗口类,该窗口类的内置过程会调用我们定义的对话框过程(由DialogBox最后一个参数提供)

   B、指定窗口类名时——可以使用自己的窗口类及窗口过程来处理对话框消息,窗口类的cbWndExtra必须设定为DLGWINDOWEXTRA。

⑤定义子窗口控件格式

  控件类型  “文本”,ID,xPos,yPos,xWidth,yHeight,iStyle

  CONTROL “文本”,ID,“类”,iStyle,xPos,yPos,xWidth,yHeight //通用格式

   A、控件类型

 控件类型

窗口类

窗口样式

PUSHBUTTON

button

BS_PUSHBUTTON|WS_TABSTOP

DEFPUSHBUTTON

button

BS_DEFPUSHBUTTON|WS_TABSTOP

CHECKBOX

button

BS_CHECKBOX|WS_TABSTOP

RADIOBUTTON

button

BS_RADIOBUTTON|WS_TABSTOP

GROUPBOX

button

BS_GROUPBOX

LTEXT

static

SS_LEFT|WS_GROUP

CTEXT

static

SS_CENTER|WS_GROUP

RTEXT

static

SS_RIGHT|WS_GROUP

ICON

static

SS_ICON

EDITTEXT

edit

ES_LEFT|WS_BORDER|WS_TABSTOP

SCROLLBAR

scrollbar

SBS_HORZ

LISTBOX

listbox

LBS_NOTIFY|WS_BORDER

COMBOBOX

combobox

CBS_SIMPLE|WS_TABSTOP

    ★子控件除以上样式外,还有WS_CHILD|WS_VISIBLE样式

     ★除EDITTEXT、SCROLLBAR、LISTBOX、COMBOBOX没“文本”,其他都有。

         控件类型  ID,xPos,yPos,xWidth,yHeight,iStyle//注意,没“文本”这项。

  B、文本字段中的符号加“&”会添加一个键盘接口,如“&Red”,按R时,焦点会转过来。

  C、应用举例

功能需求

相应的模板语句

复选框,文本左侧

CHECKBOX “TEXT”,ID,xPos,yPos,xWidth,yHeight,BS_LEFTTEXT

没边框的编辑框

EDITTEXT,ID,xPos,yPos,xWidth,yHeight,NOT WS_BORDER

按钮及等价代码

PUSHBUTTON “OK”,IDOK,10,20,32,14

CONTROL “OK”,IDOK,“button”,WS_CHILD|WS_VISIBLE|

          BS_PUSHBUTTON|WS_TABSTOP,10,20,32,14

D、模板语句及等价调用(以上面创建按钮的模板语句为例)

   hCtrl =CreateWindow(TEXT(“button”,TEXT(“OK”),

                    WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|WS_TABSTOP|BS_PUSHBUTTON,10*cxChar/4 ,20*cyChar /8,32*cxChar/4, 14*cyChar/8,

                    hDlg,IDOK,hInstance,NULL);

⑥WS_TABSTOP——可以通过TAB键获得输入焦点,按TAB键,焦点只会在有WS_TABSTOP的控件间转移。

⑦WS_GROUP——定义一组控件

 A、从第一个含有WS_GROUP样式开始,到下一个含有该样式的控件之间的为一组

 B、组内控件可以通过方向键循环转移焦点。

 C、同组中随着光标移动键,不但会转移焦点,还会赋于新的焦点控件WS_TABSTOP样式,这样下次再按Tab时会定位到该控件上。

⑧不向父窗口发送消息的子控件(如文本和图标),ID设为IDC_STATIC(-1)。

⑨IDOK、IDCANCEL在WINUSER.H中分别被定义为1、2

11.1.2 对话框过程

(1)子窗口向父窗口发送WM_COMMAND过程:子窗口→父窗口(对话框)内置的窗口过程→自定义的对话框过程

(2)对话框过程

 BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT msg,WPARAM wParam,lPARAMlParam)

{

     switch(message)

     {

     case WM_INITDIALOG:

          return TRUE;  //表示消息处理过了,不让对话框内置的窗口过程处理了。

     case WM_COMMAND:

         switch(LOWORD(wParam)) //子控件ID

         {

         case IDOK:

         case IDCANCEL:

              EndDialog(hDlg,0); //结束模态对话框,0会返回给创建模态对话框的那个函数,如作为DialobBox函数的返回值。

              return TRUE; //该消息处理好了,不让内置的窗口过程处理了。

         }

     }

     return FALSE; //False表示其余消息不处理,留给内置对话框窗口过程去处理

}

 

对话框过程

一般窗口过程

返回值

BOOL

LRESULT

默认处理

当返回值为

①TRUE时表示该消息在对话框过程巳处理,不再传递给内置的对话框处理。

②FALSE 表示该消息未处理好,得再交给内置的对话框过程。

DefWindowProc

接收的第1条消息

①WM_INIDIALOG消息(对话框独有的)进行初始化工作,并把焦点设置为第1个含有WS_TABSTOP的子窗口控件。自定义的对话框过程不会收到WM_CREATE。

②在该消息中可手动设置焦点(SetFocus),但返回值有点特殊,应设为FALSE。如果为TRUE,Windows会自动将输入焦点设置到第一个有WS_TABSTOP的子控件上。

WM_CREATE

创建

DialogBox或DialogBoxIndirectParam——模态

CreateDialog——非模态

CreateWindow

销毁

用EndDialog通知Windows销毁(内部会调用WM_DESTROY)

WM_DESTROY

WM_COMMAND

LOWORD(wParam):子控件、菜单、加速键ID

HIWORD(wParam):通知码,加速键时为1,菜单为0,其它为子控件的通知码

LParam:子控件句柄

【About1程序】
 
/*------------------------------------------
ABOUT1.C -- About Box Demo Program No. 1
(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 WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("About1");
    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;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HINSTANCE hInstance;

    switch (message)
    {
    case WM_CREATE:
        hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
        return 0;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDM_APP_ABOUT:
            DialogBox(hInstance, TEXT("AboutBox"), hwnd, AboutDlgProc);
            break;
        }
        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)
{
    switch (message)
    {
    case WM_INITDIALOG:
        return TRUE;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
        case IDCANCEL:
            EndDialog(hDlg, 0);
            return TRUE;
        }
        break;
    }
    return FALSE;
}

//resource.h

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by About1.rc
//
#define IDM_APP_ABOUT                   40001
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        104
#define _APS_NEXT_COMMAND_VALUE         40004
#define _APS_NEXT_CONTROL_VALUE         1003
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

//About1.rc

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""
"
""
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"
"
""
END
#endif    // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
ABOUTBOX DIALOG DISCARDABLE  32, 32, 180, 102
STYLE DS_MODALFRAME | WS_POPUP
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON   "OK", IDOK, 66, 81, 50, 14
ICON            "ABOUT1", IDC_STATIC, 7, 7, 21, 20
CTEXT           "About1", IDC_STATIC, 40, 12, 100, 8
CTEXT           "About Box Demo Program", IDC_STATIC, 7, 40, 166, 8
CTEXT           "(c) Charles Petzold, 1998", IDC_STATIC, 7, 52, 166, 8
END
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
ABOUT1 MENU DISCARDABLE
BEGIN
POPUP "&Help"
BEGIN
MENUITEM "&About About1...", IDM_APP_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
ABOUT1                  ICON    DISCARDABLE     "About1.ico"
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
"ABOUTBOX", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 173
TOPMARGIN, 7
BOTTOMMARGIN, 95
END
END
#endif    // APSTUDIO_INVOKED
#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

 11.1.3 更复杂的对话框

【About2程序】
效果图:

/*------------------------------------------------------------
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);
TCHAR szAppName[] = TEXT("About2");
int iCurrentColor = IDC_BLACK,
iCurrentFigure = IDC_RECT;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                  // window class name
                        TEXT("About Box Demo Program"), // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    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),        //Black
        RGB(0, 0, 255),      //Blue
        RGB(0, 255, 0),      //Green
        RGB(0, 255, 255),    //Cyan
        RGB(255, 0, 0),      //Red
        RGB(255, 0, 255),    //Meganta
        RGB(255, 255, 0),    //Yellow
        RGB(255, 255, 255)   //White
    };
    HDC hdc;
    HBRUSH hBrush;
    RECT rect;

    hBrush = CreateSolidBrush(crColor[iColor - IDC_BLACK]);
    hdc = GetDC(hwnd);
    GetClientRect(hwnd, &rect);
    hBrush = SelectObject(hdc, hBrush);
    if (iFigure == IDC_RECT)  //矩形按钮ID
        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); //这句意思是,在绘制新图像前,先把hCtrl上旧的内容清除掉。
    
//UpdateWindow的意思是,上述的操作要立即生效。然后再去执行PaintWindow,画出新的内容。
//这个顺序很好理解,因为要绘制新内容前,得先清除旧的内容。
//UpdateWindow很重要,要立即生效,原因如下: /* 1、如果不UpdateWindow的话,经过InvalidateRect,系统会向hCtrl窗口内置的窗口过程发送WM_PAINT消息
但这条消息不会被马上执行。换句话讲,程序执行完InvalidateRect后,会直接执行PaintWindow,此时此
刻新的内容确实在hCtrl上画出来了。
2、但问题来了,当本函数执行完后,因消息队列中,还有一条WM_PAINT消息。所以程序会转去执行这条消息。这
意味着,对于hCtrl来说,那个“清除”操作延迟到现在才执行,所以就会把新的内容给“清除”掉。结果表现出来,
好象这个函数就只擦除以前的以容,然后什么事都没做。
*/ UpdateWindow(hCtrl); PaintWindow(hCtrl, iColor, iFigure); } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; static HINSTANCE hInst; switch (message) { case WM_CREATE: hInst = ((LPCREATESTRUCT)lParam)->hInstance; return 0; case WM_COMMAND: switch (LOWORD(wParam)) //子控件ID { case IDM_APP_ABOUT: if (DialogBox(hInst, szAppName, hwnd, AboutDlgProc)) InvalidateRect(hwnd, NULL, TRUE); return 0; } break; case WM_PAINT: hdc = 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 int iColor, iFigure; static HWND hCtrlBlock; 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); //将TRUE作为DialogBox的返回值,用来决定是否重绘主窗口 return TRUE; case IDCANCEL: EndDialog(hDlg, FALSE); //将FALSE作为DialogBox的返回值 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, iColor); PaintTheBlock(hCtrlBlock, iColor, iFigure); return TRUE; case IDC_RECT: case IDC_ELLIPSE: iFigure = LOWORD(wParam); CheckRadioButton(hDlg, IDC_RECT, IDC_ELLIPSE, iFigure); PaintTheBlock(hCtrlBlock, iColor, iFigure); return TRUE; } break; case WM_PAINT: PaintTheBlock(hCtrlBlock, iColor, iFigure); break; //不能直接return TRUE; 要交默认处理,因为无效区要通过BeginPaint有效化。 } return FALSE; }

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 About2.rc 使用
//
#define IDC_BLACK                       1001
#define IDC_BLUE                        1002
#define IDC_GREEN                       1003
#define IDC_CYAN                        1004
#define IDC_RED                         1005
#define IDC_MAGENTA                     1006
#define IDC_YELLOW                      1007
#define IDC_WHITE                       1008
#define IDC_RECT                        1009
#define IDC_ELLIPSE                     1010
#define IDC_PAINT                       1011
#define IDM_APP_ABOUT                   40001
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        104
#define _APS_NEXT_COMMAND_VALUE         40004
#define _APS_NEXT_CONTROL_VALUE         1012
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

//About2.rc

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""
"
""
END
3 TEXTINCLUDE
BEGIN
"
"
""
END
#endif    // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
ABOUT2                  ICON                    "About2.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
ABOUT2 DIALOGEX 32, 32, 200, 234
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON   "&Ok", IDOK, 36, 205, 50, 14
PUSHBUTTON      "Cancel", IDCANCEL, 99, 204, 50, 14
ICON            "ABOUT2", IDC_STATIC, 7, 7, 21, 20
LTEXT           "About2", IDC_STATIC, 95, 14, 24, 8
LTEXT           "About Box Demo Program", IDC_STATIC, 69, 31, 83, 8
LTEXT           "", IDC_PAINT, 102, 55, 77, 79
GROUPBOX        "&Color", IDC_STATIC, 17, 49, 73, 141
CONTROL         "&Black", IDC_BLACK, "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 25, 61, 32, 10
CONTROL         "B&lue", IDC_BLUE, "Button", BS_AUTORADIOBUTTON, 25, 77, 29, 10
CONTROL         "&Green", IDC_GREEN, "Button", BS_AUTORADIOBUTTON, 25, 93, 35, 10
CONTROL         "Cya&n", IDC_CYAN, "Button", BS_AUTORADIOBUTTON, 25, 109, 33, 10
CONTROL         "&Red", IDC_RED, "Button", BS_AUTORADIOBUTTON, 25, 125, 29, 10
CONTROL         "&Megenta", IDC_MAGENTA, "Button", BS_AUTORADIOBUTTON, 25, 141, 44, 10
CONTROL         "&Yellow", IDC_YELLOW, "Button", BS_AUTORADIOBUTTON, 25, 157, 36, 10
CONTROL         "&White", IDC_WHITE, "Button", BS_AUTORADIOBUTTON, 26, 173, 35, 10
GROUPBOX        "&Figure", IDC_STATIC, 100, 146, 82, 43
CONTROL         "Rec&tangle", IDC_RECT, "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 112, 158, 48, 10
CONTROL         "&Ellipse", IDC_ELLIPSE, "Button", BS_AUTORADIOBUTTON, 112, 175, 35, 10
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
"ABOUT2", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 192
TOPMARGIN, 7
BOTTOMMARGIN, 228
END
END
#endif    // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
ABOUT2 MENU
BEGIN
POPUP "&Help"
BEGIN
MENUITEM "&About", IDM_APP_ABOUT
END
END
#endif    // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED
(1)对话框控件的应用

  ① 对比三种设置控件状态函数

将一组单选按钮的第3个设为Checked状态

第1种

for (i=idFirst,i<=idLast,i++)

{

SendMessage(GetDlgItem(hDlg,i),BM_SETCHECK,i==3,0);

}

第2种

for (i=idFirst,i<=idLast,i++)

{

SendDlgItemMessage(hDlg,i,BM_SETCHECK,i==3,0);

}

第3种

CheckRadioButton(hDlg,idFirst,idLast,3);

②设置和获到复选框的状态

CheckDlgButton(hDlg,idCheckBox,iCheck);

iCheck = IsDlgButtonChecked(hDlg,idCheckBox);

(2)避免全局变量——iCurrentColor和iCurrentFigure是全局变量,应尽量避免!

   ①先定义结构体

    typedef struct

{

    int iColor,iFigure;

}ABOUTBOX_DATA;

  ②WndProc的改动

    A、声明部分:Static ABOUTBOX_DATA ad = {IDC_BLACK,IDC_RECT};

    B、创建对话框: DialogBoxParam(hInst,TEXT(“AboutBox”),hwnd,AboutDlgProc,&ad);

  ③对话框过程的变动

    A、声明部分:static ABOUTBOX_DATA ad, *pad;

    B、WM_INITDIALOG: pad = (ABOUT_DATA*)lParam;//从lParam取出传进来的ad

                       ad =*pad;

 (3)禁用或启用子控件:EnableWindow(hwndCtrl,bEnable);

11.1.4 定义自己的控件

(1)定义自己的子控件,并运用于对话框,并用自己定义的子窗口过程来处理子窗口消息。

(2)自定义子控件:在CONTROL语句中,指定自己的窗口类。

/*------------------------------------------------------------
About3.C -- About Box Demo Program No.3
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK EllipsePushWndProc(HWND, UINT, WPARAM, LPARAM);
BOOL    CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("About3");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = EllipsePushWndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = NULL;
    wndclass.hIconSm = NULL;
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = TEXT("EllipsePush");
    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;
    RegisterClassEx(&wndclass);
    hwnd = CreateWindow(szAppName,                  // window class name
                        TEXT("About Box Demo Program"), // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;
    PAINTSTRUCT ps;
    static HINSTANCE hInst;

    switch (message)
    {
    case WM_CREATE:
        hInst = ((LPCREATESTRUCT)lParam)->hInstance;
        return 0;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDM_APP_ABOUT:
            DialogBox(hInst, TEXT("About3"), hwnd, AboutDlgProc);
            return 0;
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        EndPaint(hwnd, &ps);
        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)
{
    switch (message)
    {
    case WM_INITDIALOG:
        return TRUE;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
            EndDialog(hDlg, 0);
            return TRUE;
        }
        break;
    }
    return  FALSE;
}
//子窗口(按钮)过程
LRESULT CALLBACK EllipsePushWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    TCHAR  szText[40];
    HBRUSH hBrush;
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rc;
    switch (message)
    {
    case WM_PAINT:
        GetClientRect(hwnd, &rc);
        GetWindowText(hwnd, szText, sizeof(szText));
        hdc = BeginPaint(hwnd, &ps);
        hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
        hBrush = SelectObject(hdc, (HGDIOBJ)hBrush);
        SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
        SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
        Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);
        DrawText(hdc, szText, -1, &rc,
                 DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        DeleteObject(hBrush);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_KEYUP:
        if (wParam != VK_SPACE)
            break;
        //继续执行下去,处理空格键
    case WM_LBUTTONUP:
        SendMessage(GetParent(hwnd), WM_COMMAND, GetWindowLong(hwnd, GWL_ID), (LPARAM)hwnd);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 About3.rc 使用
//
#define IDM_APP_ABOUT                   40002
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        104
#define _APS_NEXT_COMMAND_VALUE         40003
#define _APS_NEXT_CONTROL_VALUE         1002
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

//About3.rc

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""
"
""
END
3 TEXTINCLUDE
BEGIN
"
"
""
END
#endif    // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
ABOUT3 MENU
BEGIN
POPUP "&Help"
BEGIN
MENUITEM "About About3...", IDM_APP_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
ABOUT3 DIALOGEX 0, 0, 167, 150
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
ICON            "ABOUT3", IDC_STATIC, 7, 7, 20, 20
LTEXT           "About3", IDC_STATIC, 68, 33, 24, 8
LTEXT           "About Box Demo Program", IDC_STATIC, 44, 55, 83, 8
LTEXT           "(c) Charles PetZold,1998", IDC_STATIC, 44, 77, 80, 8
CONTROL         "OK", IDOK, "EllipsePush", WS_TABSTOP, 54, 113, 50, 14 //这里EllipsePush为自定义的 窗口类,很重要!
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
ABOUT3                  ICON                    "ICON1.ICO"
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
"ABOUT3", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 157
TOPMARGIN, 7
BOTTOMMARGIN, 142
END
END
#endif    // APSTUDIO_INVOKED
#endif    // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED
原文地址:https://www.cnblogs.com/5iedu/p/4695071.html