分享

对话框简介

 牛人的尾巴 2017-01-08

对话框简介

发表于2013/12/26 16:29:07  311人阅读

分类: MFC

一、模态对话框和非模态对话框区别

1、创建方法不同。模态对话框一般通过声明对话框类对象,然后,直接调用DoModal即可创建成功;而非模态对话框一般通过Create函数创建。

2、销毁方法不同。当模态对话框创建函数DoModal返回时,对话框自动销毁;而销毁非态对话框时则要人工干预,一般调用函数DestroyWindow。

3、对“确定”、“取消”按钮的响应不同。对于模态对话框,则直接重载基类的版本即可,并且要求在重载的版本中调用基类的实现;而对于非模态对话框,则不可以调用基类的实现,因为基类的版本将调用EndDialog,而此函数只适用于模态对话框。

4、消息的处理途径不同。模态对话框有自己的消息循环,而非模态对话框的消息要经过应用的消息队列。如果想把这些消息传送给对话框窗口过程,则必须更改消息队列。

5、对于默认的对话框模板,其Visible 属性默认为空,这不会对创建模态对话框产生任何影响,因为在消息循环中将会对此作出处理,从而创建完毕后即是可见的;而对于非模态对话框,就有所不同,如果没有选中Visible 的话,则创建对话框后,必须调用ShowWindow 以便确保对话框可见。

二、对话框数据交换和验证

1、CDataExchange类简介

CDataExchange类提供了用于进行DDX和DDV所必需的上下文信息。当m_bSaveAndValidate为FALSE时,DDX将使用对话框数据成员值填充对话框控件的初始值;而当其为TRUE时,DDX将会把控件的当前值置入成员变量,并用DDV验证此值是否符合所设定的标准。如果DDV失败,那么DDV过程将会弹出一个用于解释输入错误的对话框。接着,DDV过程将会调用Fail,把焦点设置为产生错误的控件,并抛出异常以终止验证过程。

CDataExchange类共有2个成员变量以及3个成员函数

1)m_bSaveAndValidate:用于DDX和DDV方向的标志。

2)m_pDlgWnd:发生数据交换的对话框或者窗口(任何从CWnd 类派生的均可以进行数据交换)。

3)PrepareCtrl以及PrepareEditCtrl:准备用于数据交换的对话框控件。它存储控件的句柄以便当验证失败时设置控件的输入焦点。

前者用于非编辑控件,后者用于编辑控件。

4)Fail:验证失败时调用。恢复前一个控件的输入焦点并且抛出异常。

2、数据交换和验证

如果使用DDX机制,通常在OnInitDialog函数或者对话框构造函数中,设置对话框对象的成员变量值。在对话框将要显示的前一刻,

框架的DDX机制立即将成员变量值传输到对话框的控件中,而当用DoModal或者Create创建对话框并显示时,即可看到那些控件值。

对话框成员函数OnInitDialog缺省实现是:调用CWnd 的成员函数UpdateData 以初始化对话框的控件。

当用户单击了“确定”按钮时,或者在任何时候以参数TRUE调用UpdateData时,DDX机制就会把数据从控件传输到成员变量中。

此时,DDV机制按照事先指定的验证规则对传输的数据进行验证。

A.数据更新——UpdateData

当按下“确定”按钮时,用户的输入变量将会传输到控件所对应的变量中,而且DoModal返回IDOK。在DoModal中调用函数CreateDlgIndirect创建对话时,产生了WM_INITDIALOG消息,从而引起对函数CDialog::OnInitDialog的调用,在初始化对话框资源后,立即就调用了函数UpdateData,此函数正是开始数据交换的起点。它是CWnd类的成员函数,其定义如下:

//对话框数据支持
BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
{
    ASSERT(::IsWindow(m_hWnd));
    //提供用于数据交换所必需的上下文
    CDataExchange dx(this, bSaveAndValidate);
    …
    DoDataExchange(&dx);
    …
    return bOK;
}

它首先以传进来的bSaveAndValidate值为参数构造CDataExchange对象,然后调用CWnd的虚拟成员函数DoDataExchange,此函数为空,而且它什么也不做,而对话框类CModalDlg已经重载了此函数,接下来对它进行介绍。

B.数据交换——DoDataExchange

下面是DoDataExchange函数的具体实现:

void CModalDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CModalDlg)
    DDX_Text(pDX, IDC_TITTLE, m_strTittle);
     DDV_MaxChars(pDX, m_strTittle, 15);
    …
    //}}AFX_DATA_MAP
}
它首先调用基类的版本,而基类版本的实现为空,所以不需要理它。然后调用了DDX_Text,此函数用于管理对话框、表单视以及控件视中的编辑控件与int、UINT、long、DWORD、CString、float 或者double数据类型之间的传输,或者管理对话框、表单视以及控件视中的CString数据成员之间的数据传输等。它的具体定义如下:
void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value)
{
    //准备用于数据交换的对话框控件
    HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
    //如果是从控件向成员变量传输
    if (pDX->m_bSaveAndValidate)
    {
        int nLen = ::GetWindowTextLength(hWndCtrl);
        //获取文本
        ::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
        value.ReleaseBuffer();
    }
    else
    {
        //从成员变量向控件传输
        AfxSetWindowText(hWndCtrl, value);
    }
}

此函数有三个参数,其含义分别如下。

1)参数pDX:该参数表示CDataExchange对象的指针。

2)参数nIDC:该参数表示编辑控件的ID值。

3)参数value:对话框数据成员的引用,其类型取决于用户使用的DDX_Text版本,这里为CString类型。

DDX_Text 主要根据m_bSaveAndValidate的值决定控件和成员变量交换数据的方向。

当m_bSaveAndValidate为FALSE中,则将从对话框成员变量向对话框控件传输数据,即调用函数AfxSetWindowText,其定义如下:

void AFXAPI AfxSetWindowText(HWND hWndCtrl, LPCTSTR lpszNew)
{
    int nNewLen = lstrlen(lpszNew);
    TCHAR szOld[256];
    //快速检测以便确认文本是否真的发生变化
    if (nNewLen > _countof(szOld) || ::GetWindowText(hWndCtrl, szOld, _countof(szOld)) != nNewLen || lstrcmp(szOld, lpszNew) != 0)
    {
        // 改变
        //最终在控件上显示出来
        ::SetWindowText(hWndCtrl, lpszNew);
    }
}

C.数据验证

在为控件IDC_TITTLE添加成员变量时,指定了允许输入的最大字符数,因此,当m_bSaveAndValidate为TRUE时,DoDataExchange还将调用函数DDV_MaxChars,它的定义如下:

//最大字符的DDV
void AFXAPI DDV_MaxChars(CDataExchange* pDX, CString const& value, int nChars)
{
    // 确保非空
    ASSERT(nChars >= 1);
    //如果m_bSaveAndValidate 为TRUE 并且输入的字符数大于最大值时
    if (pDX->m_bSaveAndValidate && value.GetLength() > nChars)
    {
        TCHAR szT[32];
        wsprintf(szT, _T("%d"), nChars);
        CString prompt;
        AfxFormatString1(prompt, AFX_IDP_PARSE_STRING_SIZE, szT);
        AfxMessageBox(prompt, MB_ICONEXCLAMATION, AFX_IDP_PARSE_STRING_SIZE);
        //异常准备
        prompt.Empty();
        //抛出异常
        pDX->Fail();
    }
    …
}

此函数的3 个参数含义如下。

1)参数pDX:该参数表示CDataExchange对象的指针。

2)参数value:对话框等数据成员的引用,也是此函数进行验证的对象。

3)参数nChars:该参数表示编辑控件所能接受的最大字符数目。

此函数主要根据参数nChars对参数value进行验证。

三、通用对话框

除了CDialog类之外,MFC还提供了几个派生于CDialog的类,它们主要用来封装一些通用的对话框,如:“颜色选择”、“字体选择”以及“打开文件”等。它们是Windows通用对话框库(库为COMMDLG.DLL,头文件为COMMDLG.H)的一部分。

1)CColorDialog:允许用户选择或者创建颜色。

2)CFileDialog:允许用户打开或者保存一个文件。

3)CFindReplaceDialog:允许用户将一个字符串替换为另一个字符串。

4)CFontDialog:允许用户选择字体。

5)CPrintDialog:允许用户设置打印信息。

6)CPageSetupDialog:允许用户设置页面参数。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多