第11章 对话框_11.2 非模态对话框

11.2.1 模态与非模态对话框的区别

区别

模态

非模态

默认风格

WS_POPUP|DS_MODALFRAME

WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_VISIBLE

创建函数

DialogBox

创建后要等结束对话框后才返回。

CreateDialog

创建后立即返回

可见性

默认是可见的

得指定WS_VISIBLE,否则创建完后得调用ShowWindow

消息处理

有自己的消息循环

消息进入程序的消息队列(处理见下面)

销毁对话框

EndDialog

①DestroyWindow(hDlgModeless);

hDlgModeless =NULL;

②WM_CLOSE消息的处理(对话框窗口过程内部并不处理,得自己处理,如下)

 DestroyWindow(hDlgModeless)

hDlgModeless =NULL;

(2)将消息传递给对话框的窗口过程

 ①保存全局变量hDlgModeless (=CreateDialog…)

 ②消息循环的更改

while (GetMessage(&msg,NULL,0,0))
{
    //IsDialogMessage主要是处理对话框键盘导航(如Tab键转移焦点),注意是键盘消息,而不是鼠标消息
    //鼠标消息时返回False,仍然会进入下列的转换和分派过程中去 

    if (hDlgModeless ==0 || !IsDialogMessage(hDlgModeless,&msg))
    {
        if (!TranslateAccelerator(hwnd,hAccel,&msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}

11.2.2 新的COLORS程序

(1)滚动条ID分别为10、11、12,对应的当前值的静态文本字段ID分别为13、14、15

(2)主窗口样式包含WS_CLIPCHILDREN,表示不擦除对话框的情况下重绘主窗口

(3)设置颜色值:SetDlgItemInt(hDlg,nIDDlgItem,uValue, bSigned);

(4)一次CreateDialog会同时创建对话框上的子窗口控件

(5)IsDialogMessage主要处理对话框中的键盘导航消息

【COLORS2程序】
效果图:

/*------------------------------------------------------------
   COLORS2.C -- Version using Modeless Dialog Box
                (c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK ColorSrcDlg(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("Colors2");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    HWND hDlgModeless;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = NULL;// LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = NULL;// LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = CreateSolidBrush(0L); //黑色背景
    wndclass.lpszMenuName = NULL;
    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("Color Scroll"), // window caption
                        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,        // 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

    hDlgModeless = CreateDialog(hInstance, TEXT("COLORSCRDLG"), hwnd, ColorSrcDlg);

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

    while (GetMessage(&msg, NULL, 0, 0))
    {
        //IsDialogMessage主要是处理对话框键盘导航(如Tab键转移焦点),注意是键盘消息,而不是鼠标消息
        if (!IsDialogMessage(hDlgModeless, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        DeleteObject((HGDIOBJ)SetClassLong(hwnd, GCL_HBRBACKGROUND,
            (LONG)GetStockObject(WHITE_BRUSH)));
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}
BOOL CALLBACK ColorSrcDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    static int iColor[3]; //用来记录各滚动条当前颜色值
    HWND hCtrl, hwndParent;
    int iCtrlID, iIndex;
    switch (message)
    {
    case WM_INITDIALOG:
        for (iCtrlID = 10; iCtrlID < 13; iCtrlID++)
        {
            hCtrl = GetDlgItem(hDlg, iCtrlID);
            SetScrollRange(hCtrl, SB_CTL, 0, 255, FALSE);
            SetScrollPos(hCtrl, SB_CTL, 0, FALSE);
        }
        return TRUE;
    case WM_VSCROLL:
        hCtrl = (HWND)lParam; //滚动条句柄
        hwndParent = GetParent(hDlg);
        iCtrlID = GetWindowLong(hCtrl, GWL_ID);
        iIndex = iCtrlID - 10;
        switch (LOWORD(wParam)) //通知码
        {
        case SB_PAGEDOWN:
            iColor[iIndex] += 16;
            break;
        case SB_LINEDOWN:
            iColor[iIndex] += 1;
            break;
        case SB_PAGEUP:
            iColor[iIndex] -= 16;
            break;
        case SB_LINEUP:
            iColor[iIndex] -= 1;
            break;
        case SB_TOP:
            iColor[iIndex] = 0;
        case SB_BOTTOM:
            iColor[iIndex] = 255;
        case SB_THUMBPOSITION:
        case SB_THUMBTRACK:
            iColor[iIndex] = HIWORD(wParam);
            break;
        default:
            return FALSE;
        }
        iColor[iIndex] = max(0, min(255, iColor[iIndex]));
        SetScrollPos(hCtrl, SB_CTL, iColor[iIndex], TRUE);
        SetDlgItemInt(hDlg, iCtrlID + 3, iColor[iIndex], FALSE);
        DeleteObject((HGDIOBJ)SetClassLong(hwndParent, GCL_HBRBACKGROUND,
            (LONG)CreateSolidBrush(RGB(iColor[0], iColor[1], iColor[2]))));
        InvalidateRect(hwndParent, NULL, TRUE);
        return TRUE;
    case WM_COMMAND:
        break;
    }
    return FALSE;
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 Colors2.rc 使用
//
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1004
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

//Colors2.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
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
COLORSCRDLG DIALOGEX 16, 16, 181, 191
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Color Scroll Scrollbars"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
SCROLLBAR       10, 28, 32, 20, 136, SBS_VERT | WS_TABSTOP
SCROLLBAR       11, 77, 32, 20, 136, SBS_VERT | WS_TABSTOP
SCROLLBAR       12, 126, 32, 20, 136, SBS_VERT | WS_TABSTOP
CTEXT           "&Red", IDC_STATIC, 33, 18, 14, 8, NOT WS_GROUP
CTEXT           "&Green", IDC_STATIC, 78, 18, 20, 8, NOT WS_GROUP
CTEXT           "&Blue", IDC_STATIC, 128, 18, 14, 8, NOT WS_GROUP
CTEXT           "0", 13, 30, 169, 15, 8, NOT WS_GROUP
CTEXT           "0", 14, 78, 169, 19, 8, NOT WS_GROUP
CTEXT           "0", 15, 125, 169, 22, 8, NOT WS_GROUP
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
"COLORSCRDLG", DIALOG
BEGIN
END
END
#endif    // APSTUDIO_INVOKED
#endif    // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED
11.2.3 HEXCALC:窗口还是对话框?

(1)一般对话框程序不能在VC的资源编辑器里设置/修改Class Name,对话框属性的ClassName为不可用状态。但可以通过稍作修改,来达到设置对话框Class Name的目的。

    ①在资源view中,右键单击*.rc,点属性,修改MFC Mode为false;

    ②在看对话框的属性设置中,Class Name属性已经变成可编辑的状态了,设置好Class Name后保存;

(2)该对话框的特殊之处——普通层叠窗口与非模态的混合体!

    ①窗口过程不是Windows内置,而是一个正常的窗口过程。(通过指定对话框的“类名”),该ClassName告诉Windows把消息发送到我们指定的窗口过程。

    ②在创建时调用CreateDialog

(3)注册窗口类时:cbWndExtra必须设DLGWINDOWEXTRA才能注册自己的对话框窗口过程。

(4)按钮的ID被设置成其显示文本对应的ASCII码

(5)焦点问题:每次单击按钮时,焦点总是设为父窗口。否则,焦点会停留在按钮上面,否则,焦点会停留在按钮上面,从而导致键盘消息失效。

【HexCalc程序】
效果图:

 

/*------------------------------------------------------------
HEXCALC.C -- Hexadecimal Calculator
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("HexCalc");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = DLGWINDOWEXTRA; //对自定对话框窗口类必须这样设置!
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateDialog(hInstance, szAppName, 0, NULL); //对话框,却属于自己的窗口过程WndProc(非内置的!)

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

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
void ShowNumber(HWND hwnd, UINT iNumber)
{
    TCHAR szBuffer[20];
    wsprintf(szBuffer, TEXT("%X"), iNumber);
    SetDlgItemText(hwnd, VK_ESCAPE, szBuffer); //显示数字的文本框ID为27(即等于VK_ESCAPE)
}
DWORD CalcIt(UINT iFirstNum, int iOperation, UINT iNum)
{
    switch (iOperation)
    {
    case '=':return iNum;
    case '+':return iFirstNum + iNum;
    case '-':return iFirstNum - iNum;
    case '*':return iFirstNum * iNum;
    case '/':return iNum ? iFirstNum / iNum : MAXDWORD;
    case '&':return iFirstNum & iNum;
    case '|':return iFirstNum | iNum;
    case '^':return iFirstNum ^ iNum;
    case '>':return iFirstNum >> iNum;
    case '<':return iFirstNum << iNum;
    case '%':return iNum ? iFirstNum%iNum : MAXDWORD;
    default:return 0;
    }
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static BOOL bNewNumber = TRUE;
    static int iOperation = '=';
    static UINT iNumber, iFirstNum;
    HWND   hButton;
    switch (message)
    {
    case WM_KEYDOWN:  //左方向键执行删除操作
        if (wParam != VK_LEFT)
            break;
        wParam = VK_BACK; //继续执行下去
    case WM_CHAR:
        //CharUpper的参数如果高位字为0,表示转换单个字符。否则表示一个字符串的指针,将转换字符串。
        wParam = (WPARAM)CharUpper((TCHAR*)wParam); //转为大写字符
        if (wParam == VK_RETURN)
            wParam = '=';

        //获得字符所对应的按钮
        if (hButton = GetDlgItem(hwnd, wParam))
        {
            SendMessage(hButton, BM_SETSTATE, 1, 0); //按下状态,高亮显示
            Sleep(100);
            SendMessage(hButton, BM_SETSTATE, 0, 0); //释放状态
        } else
        {
            MessageBeep(0);
            break;
        }
        //继续执行下去
    case WM_COMMAND:     //LOWORD(wParam)为控件ID,也是字符的ASCII码
        SetFocus(hwnd);  //每次单击按钮时,焦点总是设为父窗口。
        //否则,焦点会停留在按钮上面,从而导致键盘消息失效
        if (LOWORD(wParam) == VK_BACK)         //退格键
            ShowNumber(hwnd, iNumber /= 16);
        else if (LOWORD(wParam) == VK_ESCAPE)  //取消键
            ShowNumber(hwnd, iNumber = 0);
        else if (isxdigit(LOWORD(wParam)))   //十六进制数                              
        {
            if (bNewNumber)                 //新操作数的开始
            {
                iFirstNum = iNumber;
                iNumber = 0;
            }
            bNewNumber = FALSE;
            if (iNumber <= MAXDWORD >> 4)      //iNumber<=0x0FFFFFFF才可再输入一位,即iNumber最大值=0xFFFFFFFF
            {
                iNumber = 16 * iNumber + wParam - (isdigit(wParam) ? '0' : 'A' - 10);  //数字时wParam-'0',
                //字母时(wParam-'A')+10,即wParam-('A'-10);
                ShowNumber(hwnd, iNumber);
            } else
            {
                MessageBeep(0);
            }
        } else                                   //操作符
        {
            if (!bNewNumber)   //防止连续多次按操作符(如多次按加号),出现重复计算现象
            {
                iNumber = CalcIt(iFirstNum, iOperation, iNumber);
                ShowNumber(hwnd, iNumber);
            }
            bNewNumber = TRUE;
            iOperation = LOWORD(wParam);
        }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

//resource.h

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

//HexCalc.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
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
HEXCALC DIALOGEX 0, 0, 127, 184
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU
CAPTION "Hex Calculator"
CLASS "HexCalc"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON      "0", 27, 15, 14, 89, 14
PUSHBUTTON      "D", 68, 8, 41, 18, 18
PUSHBUTTON      "E", 69, 30, 41, 18, 18
PUSHBUTTON      "F", 70, 52, 41, 18, 18
PUSHBUTTON      "A", 65, 8, 64, 18, 18
PUSHBUTTON      "B", 66, 30, 64, 18, 18
PUSHBUTTON      "C", 67, 52, 64, 18, 18
PUSHBUTTON      "0", 48, 8, 156, 18, 18
PUSHBUTTON      "1", 49, 8, 133, 18, 18
PUSHBUTTON      "2", 50, 30, 133, 18, 18
PUSHBUTTON      "3", 51, 52, 133, 18, 18
PUSHBUTTON      "4", 52, 8, 110, 18, 18
PUSHBUTTON      "5", 53, 30, 110, 18, 18
PUSHBUTTON      "6", 54, 52, 110, 18, 18
PUSHBUTTON      "7", 55, 8, 87, 18, 18
PUSHBUTTON      "8", 56, 30, 87, 18, 18
PUSHBUTTON      "9", 57, 52, 87, 18, 18
PUSHBUTTON      "+", 43, 74, 41, 18, 18
PUSHBUTTON      "-", 45, 74, 64, 18, 18
PUSHBUTTON      "*", 42, 74, 87, 18, 18
PUSHBUTTON      "/", 47, 74, 110, 18, 18
PUSHBUTTON      "&&", 38, 96, 41, 18, 18
PUSHBUTTON      "|", 124, 96, 64, 18, 18
PUSHBUTTON      "^", 94, 96, 87, 18, 18
PUSHBUTTON      "<", 60, 96, 110, 18, 18
PUSHBUTTON      "%", 37, 74, 133, 18, 18
PUSHBUTTON      ">", 62, 96, 133, 18, 18
PUSHBUTTON      "Back", 8, 30, 156, 40, 18
PUSHBUTTON      "Equals", 61, 74, 156, 40, 18
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
"HEXCALC", DIALOG
BEGIN
RIGHTMARGIN, 124
BOTTOMMARGIN, 182
END
END
#endif    // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
HEXCALC                 ICON                    "HexCalc.ico"
#endif    // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED
原文地址:https://www.cnblogs.com/5iedu/p/4695085.html