MFC中对话框的数据交换(DDX)和数据校验(DDV) - 小众知识

MFC中对话框的数据交换(DDX)和数据校验(DDV)

2015-10-23 07:37:05 苏内容
  标签: DDX/DDV/MFC
阅读:4813

DDX : dialog data exchange
DDV : dialog data validation
文档描述MFC中的DDX DDV机制,如何使用DDX_和DDV_ 函数和定制自己的DDX_ ,DDV_函数;

Dialog Data Exchange概要:
对话框的数据交换不依赖于任何宏来实现,全部依赖于C++代码实现,唯一特别之处在于每一个对话框如果想处理自己的数据交互必须重载一个虚函数void CMyDialog::DoDataExchage(CDataExchage* pDX)

最常见的形式:
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);    // call base class
    //{{AFX_DATA_MAP(CMyDialog)
        <data_exchange_function_call>        
    //}}AFX_DATA_MAP
}
在包含AFX的2个字段之间的部分,向导用来定位和编辑代码;
如果想实现自定义的DDX DDV应该定位在这2个字段外

可以在头文件afxdd_.h中找到MFC定义的一些关于DDV DDX的函数的声明;

注意:
DDX /DDV技术虽然被称为对话框数据交换和校验,但是适用于任何需要与控件进行数据交换和校验的CWnd派生类

这些用于交换的成员数据变量一般在对话框的构造函数中的
//{{AFX_DATA_INIT 和 
//}}AFX_DATA_INIT之间的字段中进行初始化的

CWnd::UpdateData()函数用来封装对数据交换(初始化或获取数据)和校验的处理(范围出错)

在程序的任意部分都可以通过调用UpdateData来进行数据交换或数据校验;
默认情况下
在对话框的OnInitDialog()函数中会调用UpdateData(FALSE);
在对话框的OnOK()函数中会调用UpdateData(TRUE);


DDX/DDV技术实现
DDX/DDV技术实现用于帮助实现定制的DDX和DDV函数

DoDateExchange成员函数类似于序列化中Serialize函数,不同之处在于DoDateExchange是从对话框的控件上读取或写入数据,而在这个过程中的CDataExchage对象类似序列化中于CArchive对象;CDataExchange对象也有数据方向标识:
• if !m_bSaveAndValidate,   设定控件上的数据
• if m_bSaveAndValidate,    读取控件上的数据 
只有当m_bSaveAndValidate的值设定时才进行校验,这个值是通过传给UpdateData的参数来设定的;

CDateExchage中还有几个有意义的成员:
m_pDlgWnd : 含有控件的窗体 (通常是对话框),这样可以避免每次调用DDX\DDV函数时需要将this指针传人;
PrepareCtrl or PrepareEditCtrl: 将要数据交互的控件, 当某一个控件的数据交互失败时,则将设定焦点在这个控件上(PrepareCtrl是非Edit控件, 而PrepareEditCtrl是Edit控件);
Fail: 显示一个对话框来告知输入错误;这个函数在DDX DDV函数中被调用,该函数会保持最后一个那个PrepareCtrl的数据的焦点,并抛出异常

用户可实现扩展(User Extensions)
有几种方法可以用于实现扩展DDX DDV机制:
• 增加一种新数据类型.
• CTime
• 增加新的数据交换函数 (DDX_???).
• void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm);
• 增加新的数据校验函数(DDV_???).
• void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture);
• //make sure time is in the future or past
• 特定的数据校验.
• DDV_MinMax(pDX, age, 0, m_maxAge);
注意只有最后一种方法是不能为类向导支持的,所以不能置于类向导标识字段中


类向导的支持(ClasWizard Support)
类向导通过支持一个个性化子集来允许用户将自己编写的DDX_ DDV_函数集成到类向导中;这样做可以在可以使定制的DDX DDV函数在一直有效(在任意工程中都可以使用)或只在一个工程中有效;

实现这些功能需要在DDX.CLW或工程的.CLW中添加一些特殊的字段
在DDX.CLW(位于\Program Files\Microsoft Visual Studio\Visual C++\bin 也可能不存在需要用户创建)[ExtraDDX]字段添加的信息则可以在任意工程中使用;而在用户工程的CLW中[GENERAL INFO]字段添加的信息则只可以在该工程的向导中使用

相关字段的格式及意义:
ExtraDDXCount = n
//n 表示ExtraDDx的数目 如下:
ExtraDDX?=<keys>;<vb-keys>; <prompt>; <type>; <initValue>; <DDX_Proc> [;<DDV_Proc>; <prompt1>; <arg1>; [<prompt2>; <fmt2>]]
//?表示列表中的第几个DDX 被定义;每一个字段由‘;‘ 字符分开每个参数的意义如下: 
<keys>
//指示符表示适用的对话框中控件类型 如下
E = edit
C = two-state check box
c = tri-state check box
R = first radio button in a group
L = non-sorted list box
l = sorted list box
M = combo box (with edit item)
N = non-sorted drop list
n = sorted drop list
1 = if the DDX insert should be added to head of list (default is add to tail) This is generally used for DDX routines that transfer the 'Control' property.
<vb-keys>
这个字段仅在16位程序中用于VBX控件(32位程序已不使用)
<prompt> =
置于属性组合框类向导中设定数据交换的对话框propery combo box)中的字符串提示信息<type> =
需要载头文件中包含的引用的用于数据交换的数据类型 如上CTime
<vb-keys> =
当前版本中必须为空(VC6.0)
<initValue> =
初始化值0或空,如果为空则在初始化字段中(//{{AFX_DATA_INIT}})不会有任何初始化字段 通常一个C++对象这个字段为空表示调用默认的构造函数来保证正确的初始化
<DDX_Proc> =
DDX调用(routine)的标识;这个C++函数必须以DDX_开头但是在这个字段只需写入DDX_以后的字段如添上Time则类向导会在{{AFX_DATA_MAP字段中加上DDX_字段结果在{{AFX_DATA_MAP中就是这样:DDX_Time
<comment> =
在对话框中当前DDX显示描述变量的内容,同上promopt在使用向导时可视;一般描述DDX\DDV对的完成的操作
<DDV_Proc>
DDV部分在这里是可选的;并非全部的DDX都需要对应的数据校验函数。
= DDV调用(routine)的标识如<DDV_Proc>字段的格式;
其后为1 或 2 DDV 参数:
<promptX> =
类向导中在edit item位置之前的字符串提示信息(向导中) 
<fmtX> =
格式化字符表示参数类型
d = int
u = unsigned
D = long int (that is, long)
U = long unsigned (that is, DWORD)
f = float
F = double
s = string

 

DDX_Control 与 DDX_Text 区别

 

DDX_TEXT()的作用可以理解为把字符串变量和控件的文本(WindowText)关联起来, 
DDX_Control()的作用可以理解为把变量和控件本身关联起来, 
DoDataExchange(pDX)就是处理所有变量与其关联控件交换数据的函数。

void CView::DoDataExchange(CDataExchange* pDX)

CFormView::DoDataExchange(pDX);
DDX_Text(pDX, IDC_ID_VALUE, m_strID);
DDX_Control(pDX, IDC_ID_VALUE, m_editID);

在程序中
通过update(TRUE)取得控件上的值到m_strID,处理修改后通过update(FALSE)传回控件,界面显示
通过m_editID.GetWindText(str),取得值,处理后,通过m_editID.SetWindText(str)传回控件界面显示

扩展阅读
相关阅读
© CopyRight 2010-2021, PREDREAM.ORG, Inc.All Rights Reserved. 京ICP备13045924号-1