DDX和DDV方法
DDX和DDV方法 本文主要介绍DDX和DDV的体系结构,本文也帮助您了解DDX或DDV的过程以及如何扩展ClassWizard,使它可以使用用户的过程。下面我们首先来看一下对话框数据交换。请注意,在上面的两个过程中,关键的问题在于虚函数的重载。我们经常会在我们用ClassWizard生成的代码中看到下面的代码: void CMyDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); // call base class //{{AFX_DATA_MAP(CMyDialog) <data_exchange_function_call> //}}AFX_DATA_MAP } 其中AFX是由ClassWizard控制的,只有包括在AFX中间的代码才可以由ClassWizard管理,如果用户不希望让一些东西让ClassWizard管理了,那就把这些东西移出AFX就可以了。但是,通常的情况下还是不这样做的好。上面代码中还有一段没有写出来,那就是<data_exchange_function_call>,它的形式可以是DDX_Custom(pDX, nIDC, field),或是DDV_Custom(pDX, field, ...);,所有的关于DDX和DDV的定义在文件'afxdd_.h'中定义。函数初始化的定义在类的构造函数中的//{{AFX_DATA_INIT和//}}AFX_DATA_INIT之间。 CWnd::UpdateData函数是我们经常使用的,我们经常在它后面的值中取一些true或者false之类的值,那让我们来看看,如果是true,它都做了些什么。它实际上进行的就是数据交换。我们一般不用了解下面的所说的数据交换过程一样可以使用对话框,但是如果我们能够了解一点,那当然要好多了。我们可以把DoDataExchange成员函数看成是Serialize(串行化)成员函数,反正两都都是将数据送入类中,或把数据从类中送出。我们在上面代码中一定看到了一个pDX的东西,它是一个参数,它是用于进行数据交换的参数,我们上面已经知道了在UpdateData中要传送一个参数,表示方向,那我们看看pDX中表示数据传输方向(这个方向就是表示数据究竟是从类中传输出来呢,还是向类传送进去呢): 如果m_bSaveAndValidate为假,将数据传输到相应的控件上去,数据传输出类了。 如果m_bSaveAndValidate为真,将数据传输到类中来,数据传输进类了! 在设置了m_bSaveAndValidate之后,验证(数据有效性的)过程才得以进行。 下面有几个函数可是不能不说:
我们可以通过下面几个方法扩展DDX/DDV。
可以是:void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm); 可以是:void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture); 下面的验证就是验证输入的年纪是不是在0到最大年纪(对人来说可能是500岁)之间: DDV_MinMax(pDX, age, 0, m_maxAge); 上面的这些代码不能由ClassWizard管理,所以要放在//{{AFX_DATA_MAP(CMyClass))之外。 下面是一些有条件的验证,它的意思,我想在我就不多嘴了,看这篇文章的也多少知道几个英文,大家看英文自己也会明白的。 //{{AFX_DATA_MAP(CMyClass) DDX_Check(pDX, IDC_SEX, m_bFemale); DDX_Text(pDX, IDC_EDIT1, m_age); //}}AFX_DATA_MAP if (m_bFemale) DDV_MinMax(pDX, age, 0, m_maxFemaleAge); else DDV_MinMax(pDX, age, 0, m_maxMaleAge); 当然,如果我们能够在ClassWizard中管理DDX/DDV,那不更好吗。ClassWizard支持DDX和DDV的子集,通过让ClassWizard管理DDX和DDV,我们会得到一些方便。特别在重复使用的时候更是如此。如果希望实现这个功能,可以在DDX.CLW中或工程的.CLW中进行编译,加入相应的函数入口。在工程的.CLW中,将用户自定义的函数入口写在[General Info]段中,也可以在DDX.CLW的[ExtraDDX]段中加入相应的代码,但是请注意,一定要把DDX.CLW放在Program FilesDevStudioSharedIDEin目录下。当然,如果DDX.CLW不存在,那只有用户自己创建它了。如果你只希望在你的工程中使用特定的函数入口,将相应的函数入口加入工程的.CLW中就可以了。如果你希望在多个工程中和以后的工作中使用,则可以在DDX.CLW中加入[ExtraDDX]段。 下面我们就看看我们应该写点什么了: ExtraDDXCount=n //N是ExtraDDX?后面的行数 ExtraDDX?=<keys>;<vb-keys>; <prompt>; <type>; <initValue>; <DDX_Proc> [;<DDV_Proc>; <prompt1>; <arg1>; [<prompt2>; <fmt2>]] // 这里的?代表1到N,指定表中定义的是什么类型的DDX;上面定义的各个部分间以;隔开,它们的意义我们在下面说明: <keys> = 它是一个字母,表示对话框控件指示的是什么类型:
如果DDX需要插入在列头上,则要使用1。它一般用于传输控制属性的DDX过程。
例子大家可以参考VC自己带的例子chkbook。 |