DDX用于控件与变量的数据交换.DDV用于对数据交换后的变量进行校验,倘若校验失败将抛出异常导致Updata后面部分不能正常执行.必要时需要对Updata的返回值进行判断.
    对于数据交换,需要编写一个带有参数CDataExchange指针、一个控件ID和对某变量引用的全局函数,尽管可以不在函数前面添加DDX_前缀,但是为了可以和Class Wizard集成,最好忍住你的这种念头(后面你会看到为什么了).

在交换函数中,可以检查CDataExchange指针,以了解你所须的细节.下面就来看看CDataExchange类的成员.

成员 描述
m_bSaveAndValidate 对应于你提供给UpdateData的参数,当为TRUE时数据从控件传递到变量
m_pDlgWnd 控制窗口或对话框的句柄
PrepareCtrl(int nIDC) 调用该函数,以标识当前控件(如不是编辑框)
PrepareEditCtrl(int nIDC) 调用该函数,以标识当前控件(如是编辑框)
Fail() 产生一个对控件的验证失败(你可以在DDX或者DDV中调用该函数),抛出一个异常,破坏DoDataExchange函数的执行

一般的,编写交换函数,,你首先要检查m_bSaveAndValidate的值以确定数据的传递方向,如果传递失败,你有必要调用PrepareEditCtrl(适于编辑控件)或者PrepareCtrl(适于所有控件),在做此调用之后,任何对Fail的调用将导致把焦点交回给该控件,即使其它过程(比如一起的验证过程)发布同样的失败,也是这样编写一个验证函数,跟编写一个交换函数差不多,差别只是参数的不同.函数以DDV_为前缀,参数可以接受一个CDataExchange指针、合适类型的一个只值、一个或两个参数.

它的工作很简单,如果m_bSaveAndValidate为TRUE时,一定要保证值是合法的(通常认为从程序传递到控件的值是正确的).如果数据正常,则从该函数返回,如果数据不正常,则调用Fail函数.前一个数据交换函数已经标识了当前操作的是哪个控件(这也就是为什么必须要在对应的DDX调用之后立即添加DDV的验证代码的原因了).
    下面的例子演示了如何定制自己的数据验证:

程序清单:使用定制的DDX/DDV
// validView.cpp : implementation of the CValidView class
//
#include "stdafx.h"
#include "valid.h"
typedef float Currency; // used for DDV
#include "validDoc.h"
#include "validView.h"
#include "customdd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CValidView
IMPLEMENT_DYNCREATE(CValidView, CFormView)
// Class Wizard won't put this here because it thinks
// Dialog boxes handle OnOK. They do, but this is a
// form view, not a dialog box
BEGIN_MESSAGE_MAP(CValidView, CFormView)
    //{{AFX_MSG_MAP(CValidView)
    ON_COMMAND(IDOK,OnOK)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

// CValidView construction/destruction
CValidView::CValidView()
: CFormView(CValidView::IDD)
{
    validating=FALSE;
    vid=0;
//{{AFX_DATA_INIT(CValidView)
    m_age = 18;
    m_name = _T("");
    m_wager = 1.0;
    m_btnenable = TRUE;
//}}AFX_DATA_INIT
// TODO: add construction code here
}

CValidView::~CValidView()
void CValidView::DoDataExchange(CDataExchange* pDX)
:CFormView::DoDataExchange(pDX);
{
//{{AFX_DATA_MAP(CValidView)
    DDX_Text(pDX, IDC_AGE, m_age);
    DDV_MinMaxInt(pDX, m_age, 18, 150);
    DDX_Text(pDX, IDC_NAME, m_name);
    DDV_MaxChars(pDX, m_name, 64);
    DDX_Text(pDX, IDC_WAGER, m_wager);
    DDV_MinMaxCurrency(pDX, m_wager, 1.f, 100.f);
    DDX_EnableWindow(pDX, IDOK, m_btnenable);
//}}AFX_DATA_MAP
}

BOOL CValidView::PreCreateWindow(CREATESTRUCT& cs)
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CFormView::PreCreateWindow(cs);
// CValidView diagnostics
void CValidView::AssertValid() const
CFormView::AssertValid();
void CValidView::Dump(CDumpContext& dc) const
CFormView::Dump(dc);
CValidDoc* CValidView::GetDocument() // non-debug version is inline
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CValidDoc)));
return (CValidDoc*)m_pDocument;
#endif //_DEBUG
// CValidView message handlers
void CValidView::OnOK()
{
    if (UpdateData(TRUE))
    {
        MessageBox("Wager placed");
        m_btnenable=FALSE;
        UpdateData(FALSE);
    }
}

程序清单:定制的DDX/DDV过程
#include <stdafx.h>
// Custom Exchange
void DDX_EnableWindow(CDataExchange *pDX, int id, BOOL &flag)
{
    CWnd *ctl=pDX->m_pDlgWnd->GetDlgItem(id);
    if (pDX->m_bSaveAndValidate)
        flag=ctl->IsWindowEnabled();
    else
        ctl->EnableWindow(flag);
}
// Custom validator
void DDV_MinMaxCurrency(CDataExchange *pDX, float val, float min, float max)
{
    CWnd *editctl=CWnd::FromHandle(pDX->m_hWndLastControl);
    CString s;
    int n;
    // Using math to decide if anything is left over is bad because of rounding
    // errors, so use a string method instead
    editctl->GetWindowText(s);
    n=s.Find('.');
    if (n!=-1 && n+3<s.GetLength())
        {
        AfxMessageBox("Please enter the data to the nearest penny!");
        pDX->Fail();
        }
    DDV_MinMaxFloat(pDX,val,min,max); // let the existing one do the job
}

与Class Wizard集成
   如果你只想把某定制过程应用于一个项目的话,可以把它添加到该项目的CLW文件.你也可以在包含mfcclwz.dll文件的BIN目录(我的是...\Microsoft Visual Studio\Common\MSDev98\Bin)下创建一个DDX.CLW文件,然后你的DDX过程就可以应用到所有项目了.
   下面来看一看怎样写CLW文件:
首先添加一个名为[ExtraDDX]的区段,看起来象INI文件的区段,但是这里的名称是区分大小写的.
[ExtraDDX]
ExtraDDXCount=2
ExtraDDX1=E;;Value;Currency;0.0;Text;Floating Point Currency;MinMaxCurrency;Mi&nimum;f;Ma&ximum;f
ExtraDDX2=bBECcRLIMNn;;Enable State;BOOL;TRUE;EnableWindow;Window Enabled Status
这些代码是什么意思呢?
第二行ExtraDDXCount=x的x表示项目的数目(这里是2),然后接下来的一行以ExtraDDX1=开头,再下来是ExtraDDX2=、ExtraDDX3=等等。等号右边的代码被分成7个、10个或者12个域,具体倚赖于你所想实现的目标,每个域以分号分隔,下面的表格列出了这些域的意思:

 
1 DDX应用的空间类型(比如E=编辑框)
2 未使用
3 属性类型(经常是值,对应着Class Wizard的第一个组合框)
4 变量的数据类型
5 初始值
6 没有DDV_前缀的DDV过程名
7 注释
8  
9 第一个DDV参数的名称(可选)
10 第一个DDV参数的类型(比如,f=float;可选)
11 第二个DDV参数的名称(可选)
12 第二个DDV参数的类型(比如,f=float;可选)

你不必指定任何DDV过程,你可以把一个新的验证过程与标准的交换函数混合在一起(也就象上面ExtraDDX1那一行所做的一样).注意,这些DDX和DDV函数名并没有以DDX_和DDV_开头,但是Class Wizard确实往它产生的代码中添加了这些前缀.这也就是用这些前缀命名函数的原因了

VC中DDX/DDV自定义相关推荐

  1. VC++的DDX/DDV机制

    C++的MFC类库中为用户提供了在对话框控件和数据变量间交换数据的         DDX/DDV(数据交换/数据验证)机制,而在此之前,用户只能通过调用         GetDlgItemInt或 ...

  2. MFC 中DDX DDV 解疑

    DDX/DDV 通过使用ClassWizard向对话类添加成员变量,你可以利用ClassWizard所提供的高效特征,为对话数据交换和对话数据验证自动生成源代码,也就是人们所熟知的DDX/DDV. 数 ...

  3. MFC vc++ 中CTreeContrl如何自定义实现鼠标单击或双击响应事件 ,即重写类似于控件的响应事件或消息

    代码部分摘录自"天上的猩猩的专栏":https://blog.csdn.net/qq_23992597/article/details/51006920#commentsedit ...

  4. VC++中的DDX和DDV

    DDX/DDV        通过使用ClassWizard向对话类添加成员变量,你可以利用ClassWizard所提供的高效特征,为对话数据交换和对话数据验证自动生成源代码,也就是人们所熟知的DDX ...

  5. VC/MFC DDX和DDV机制介绍

    VC/MFC DDX和DDV机制介绍 C++的MFC类库中为用户提供了在对话框控件和数据变量间交换数据的         DDX/DDV(数据交换/数据验证)机制,而在此之前,用户只能通过调用     ...

  6. VC中自定义IE浏览器

    VC中自定义IE浏览器 http://www.5xsoft.com/Article.aspx?id=155 本教程提供了自定义浏览器控件的行为和外观的一些方法.你将看到高级的宿主接口, IDocHos ...

  7. VC中自定义打印调试信息函数,打印调试信息到DebugView上

    该文档参考了以下网友的文章,在此表示感谢. 1. (更新)OutputDebugString函数简单封装,实现格式化打印输出(VC++) 链接:http://blog.csdn.net/sunflov ...

  8. VC中的宏 (#define) 与预处理 (#if/#ifdef/#pragma) 的使用方法总结。

    C/C++ 预定义宏 例子:C/C++ 预定义宏的取值 C/C++ 预定义宏用途:诊断与调试输出 CRT 的诊断与调试输出:assert, _ASSERT/_ASSERTE, _RPTn/_RPTFn ...

  9. [转]ToolTip在VC中的使用

    按照下面的步骤去做:  1.先为static设置一个ID,如ID_TIP;  2.在CDialogBar的头文件中的AFX_MSG内加入一行申明  afx_msg BOOL OnToolTip(UIN ...

最新文章

  1. jQuery获取或设置元素的宽度和高度
  2. Android学习起步 - 新建工程及相关
  3. 方法入门_方法的调用
  4. mysql binlog2sql_mysql闪回工具binlog2sql安装配置教程详解
  5. 利用均差的牛顿插值法(Newton)
  6. 微课|Python程序设计开发宝典(5.1.2节):可调用对象
  7. 用jQuery的ajax的功能实现输入自动提示的功能
  8. 如何在sh的字符串中包含换行符?
  9. 强悍的 Linux —— 系统文件及其作用
  10. Senparc.Weixin.MP SDK 微信公众平台开发教程(九):自定义菜单接口说明
  11. redis应用场景:实现简单计数器-防止刷单
  12. esp8266对接天猫精灵 微信控制
  13. 华为模拟器eNSP下载与安装教程(面向小白)
  14. android9 apk自动安装功能,Android自动安装APK
  15. 微信小程序例子——点击发送信息清空输入框
  16. 不小心将项目的 iml文件删除了怎么办
  17. 两球体相交,球缺的计算
  18. MaxListenersExceededWarning: Possible EventEmitter memory leak detected.警告的处理
  19. 顺丰理赔要讲究方法,注意这几个方面能获得满意结果
  20. android imageview stretchblt,想知道Bmp图像的缩小放大用Tcanvas.StretchDraw还是用StretchBlt函数?(50分)...

热门文章

  1. 云计算介绍 、TCP/IP协议及配置
  2. 现代软件工程讲义 5 团队合作的阶段
  3. 解析Makefile文件的构建规则
  4. Gulp:插件编写入门
  5. 菜鸟解读qt源码----qsqlfield.h
  6. 函数组:BUSG(SAP 商业图形库)
  7. BCH链上交易量剧增,超越莱特币
  8. 【重要预警】“永恒之蓝”漏洞又现新木马 组成僵尸网络挖矿虚拟货币
  9. java关键字--static--应用场景、特点和注意事项
  10. Android设置多个定时器时只有最后一个定时器有效的问题