DDX/DDV工作内幕 DDX(动态数据交换)和DDV(动态数据验证)看起来好象是在对话框中某控件和 某成员变量之间建立连接,自动实现控件和变量之间的数据转移.但这只是一个幻 觉.它的实际工作方式是这样的:当你用ClassWizard把某变量和控件连接起来时 (通过Member Variables选项卡),它在数据映射中创建一个入口.实际上也就是 在对话框的DoDataExchange函数中添加一个入口函数(DoDataExchange函数是 Class Wizard产生和维护的函数).当你调用UpdateData(FALSE)时,MFC调用 DoDataExchange 函数,Class Wizard放于DoDataExchange中的实现代码将把 来自变量的数据拷贝到对应的控件.如果调用UpdateData(TRUE),MFC反过来把 数据拷贝回变量(并且可能同时进行数据验证) 应该注意到,CDialog经常在OnInitDialog函数中调用UpdateData(FALSE), 这样当对话框显示时你的成员变量就会神秘的出现在对话框中.同样OnOK函数也 调用UpdateData,但参数是TRUE.这样模态对话框看起来自己处理自己了.你可以 编写类似下面的代码: CNameDlg dlg; dlg.m_name="New Name"; if ( dlg.DoModal() == IDOK ) MessageBox(dlg.m_name,"Greetings"); 来实现模态对话框的自动处理. 下面考虑一下使用非模态对话框的情况吧.对话框仍处理OnInitDialog消息, 因此数据初始传输正常.但是非模态对话框一般不等到按OK按钮来处理它们的数 据,这就意味这我们必须自己处理数据传输,具体请看『快速DDX』. 好了,现在来看看DDV动态数据验证.你在使用DDX动态数据交换的同时,也可 以使用数据验证.典型的,验证可以保证一个字符串的字符数小于给定的数目,或 者数字在一定范围之内. 不过数据验证通常并不能满足我们的期望,这是因为验证只在控件到变量的 数据传输时才发生.这通常意味着用户在输入了所有数据,单击OK,然后就收到 一个错误消息. 不过我们可以改进一下,使用『现场数据验证』. 改进DDX/DDV 快速DDX 有几种情况我们需要使用快速DDX,比如你编写一个电子邮件程序,用户在对 话框中输入名称和地址,你需要一个按钮使应用程序可以在用户输入完之后得到 邮件的名称和地址.或者考虑一下模态对话框的"应用"按钮的实现吧. 当然要实现上面的任务,我们可以直接调用GetDlgItemText获取编辑框数据, 但为什么不使用DDX呢?这样至少可以使对话框看起来有点自动化.可以调用 UpdateData(TRUE)把数据传送到变量,反过来填充地址时可以调用UpdateData(FALSE). 要想得到每个控件的状态以确定何时需要进行数据交换,可以重载CDialog类 的OnCommand函数,因为一般的传统控件都用WM_COMMAND消息来提示状态的改变, 当然对于使用WM_NOTIFY消息的新型控件可以一样的处理OnNotify函数.下面是 使用该技术的一个简单例子,当你在对话框中输入数据的同时主窗口中数据也进 行相应的改变. 程序清单:快速DDX // LiveDialog.cpp : implementation file // #include "stdafx.h" #include "Custom.h" #include "LiveDialog.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif / // CLiveDialog dialog CLiveDialog::CLiveDialog(CWnd* pParent /*=NULL*/) : CDialog(CLiveDialog::IDD, pParent) { //{ {AFX_DATA_INIT(CLiveDialog) m_email = _T(""); m_name = _T(""); //}}AFX_DATA_INIT m_pView=NULL; // 应用程序窗口视的指针 } void CLiveDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{ {AFX_DATA_MAP(CLiveDialog) DDX_Text(pDX, IDC_EMAIL, m_email); DDX_Text(pDX, IDC_NAME, m_name); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CLiveDialog, CDialog) //{ {AFX_MSG_MAP(CLiveDialog) //}}AFX_MSG_MAP END_MESSAGE_MAP() / // CLiveDialog message handlers BOOL CL