当前位置: 首页 > news >正文

2409wtl,wtl与ddx

原文

介绍

借助WTL,现在可取得MFC编码的大量易用性,而不会增加体积.本文展示了如何利用WTLDDX/DDV实现,展示添加到WTL实现中的两个自定义扩展扩展其覆盖区间,并使用WTL的属性表实现(CPropertyPageImpl)提供从实际代码中取的真实示例.

WTL头文件atlddx.h提供DDX/DDV处理,它包含创建DDX映射的宏(与ATL消息映射概念相同)和CWinDataExchange模板类.

因此,使用DDX/DDV的第一步是添加

#include <ATLddx.h>

StdAfx.h其他主头文件中放入它.注意,如果你使用的是WTLCString,则必须在AtlDDx.h前包含AtlMisc.h.

因此,我总是在StdAfx.h简单地添加以下内容:

#include <atlmisc.h> //`CString`支持
#include <atlddx.h>

atlwin.h正下方的StdAfx.h中,如下.

...
#include <atlbase.h>
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>
#include <atlmisc.h>
#include <atlddx.h>
#include <atldlgs.h>
...

下一步是确保你使用的对话框类CWinDataExchange继承,以取得对DDX的支持,如下:

class CCameraBase : public CPropertyPageImpl<CCameraBase>,public CWinDataExchange<CCameraBase>

然后,现在可进入它的核心,实际上是把你的变量连接到各自的UI组件.这是DDX消息映射完成的,下面列举了简单示例:

BEGIN_DDX_MAP(<your dialog class>)
DDX_TEXT(<对资标>,<串变量>)
DDX_TEXT_LEN(<对资标2>,<串变量2>,<max text length>)
END_DDX_MAP()

消息映射中,你可指示WTLDDX勾挂变量对话框UI元素.有许多宏可用来处理各种数据类型,但简要地看一下上面的两个项.

第一个DDX_TEXT,简单指出在加载时,<串变量>中的值应该赋值给<对资标>,一般是映射到编辑框串变量.

对话框结束时,反向映射,拉出<对资标>的当前内容并放回至<串变量>中.非常漂亮整洁.

第二个宏如上所示,DDX_TEXT_LEN有与DDX_TEXT类似的函数,因为也有<对资标2>连接<串变量2>,但你可到还有第三个参数,<最大文本长>.

此处指定一个值,如果用户文本输入超过该值,则启动DDV错误处理器.可覆盖默认处理器,也可用默认处理器(它将哔哔),并设置焦点有问题的控件提示用户更正它.

你可覆盖如下函数来实现自己的处理器,这在示例中有演示.

void OnDataValidateError(UINT id, BOOL bSave,_XData& data)

消息映射有许多宏,一般有个来纯连接的宏如,(DDX_TEXT)连接和验证的宏如,(DDX_TEXT_LEN).

这样,最后一步是实际告诉WTL何时实际的数据交换.这是用调用DoDataExchange(BOOLfParam)加载包含数据值的对话,并用对话提取数据来完成的.

由你决定在哪这样干,但OnInitDialog(WM_INITDIALOG的处理器)是DoDataExchange(FALSE)加载调用的好地方.

拉回修改后的数据,可在对话框OnOK中调用DoDataExchange(TRUE)提取,对属性页,可在OnKillActivate()中处理它.

DDX的实际应用

示例应用基于商业应用代码子集,该应用处理多个无线摄像机查看/监听.此应用的相关部分是,它必须允许用户为多达16个相机指定单个设置,并在干净的UI中这样.

我用WTL属性页来实现,这样为每个摄像机提供一个漂亮的选项卡式对话框,然后用DDX/DDV来简化来回转移各个设置.

示例应用只允许你使用四个设置,这样你可在调试器中看到设置是如何转移和验证的.

struct _cameraprops
{CString ssFriendlyName;UINT iHouseCode;UINT iUnitCode;CString ssSaveDir;BOOL fIsInSnapshotCycle;BOOL fAddTimestamp;
};
extern _cameraprops g_cameraProps[4];

和主CPP文件中赋值的存储(propsheetddx.cpp):

#include "maindlg.h"
CAppModule _Module;
_cameraprops g_cameraProps[4];

设置中央存储结构后,下一步是创建处理属性表的头文件,并为属性页处理器创建基类.

class CCameraBase : public CPropertyPageImpl<CameraBas>,public CWinDataExchange<CameraBas>

然后,我在VC中创建了一个对话框,如下:
接着,我添加了DDX消息映射,以指定UIg_cameraprops全局结构间的连接:

BEGIN_DDX_MAP(CCameraBase)
DDX_TEXT_LEN(IDC_edit_CameraTitle, g_cameraProps[m_iIdentity].ssFriendlyName, 35)
DDX_COMBO_INDEX(IDC_cmbo_HouseCode, g_cameraProps[m_iIdentity].iHouseCode)
DDX_COMBO_INDEX(IDC_cmbo_UnitCode, g_cameraProps[m_iIdentity].iUnitCode)
DDX_TEXT(IDC_edit_FileDirectory, g_cameraProps[m_iIdentity].ssSaveDir)
DDX_BOOL_RADIO(IDC_radio_AddTimeStamp, g_cameraProps[m_iIdentity].fAddTimestamp, IDC_radio_NoTimeStamp)
END_DDX_MAP()
enum { IDD = IDD_PROP_PAGE1 };

当然,必须调用DoDataExchange加载.

LRESULT OnInitDialog(...)
{
...
InitComboBoxes(hwndComboHouse, hwndComboUnit, m_iIdentity);
CenterWindow();
DoDataExchange(FALSE);//..
...
}

验证和取修改后的数据:

BOOL OnKillActive()
{DoDataExchange(TRUE);//..return true;
}

因为必须扩展到16个摄像头(尽管示例中有4个),因此我修改了CcameraBase类的构造器,用一个整数来识别它正在处理的摄像头:

CCameraBase(int _index)
{m_iIdentity = _index;...
}

现在,为了在的UI中实际实现该4x,转向继承的CpropertySheetImplCcameraProperties.没有太多内容,如下:

class CCameraProperties : public CPropertySheetImpl<CameraPropertie>
{
public:CCameraBase m_page1;CCameraBase m_page2;CCameraBase m_page3;CCameraBase m_page4;CCameraProperties():m_page1(1),m_page2(2),m_page3(3),m_page4(4){m_psh.dwFlags |= PSH_NOAPPLYNOW;AddPage(m_page1);AddPage(m_page2);AddPage(m_page3);AddPage(m_page4);SetActivePage(0);SetTitle(_T("Camera and Video Input Properties"));
}

注意,上面粗体显示成员初化列表显示了实际使用各自相机来标识每个类实例的位置.后,在选项卡式布局中调用AddPage勾挂类,并SetActivePage指定你的第一个页.
上面省略了一个小消息映射,但除此外,你现在拥有完整属性表的处理器.

WTL中扩展DDX

当然,还遇见了两个直接的问题,需要向<ATLDDX.H>添加新的扩展DDX帧干一些额外的处理.

因为索引表示到数组或枚举中的组合框而不是试表示文本值是很常见的,因此我添加了叫DDX_COMBO_INDEX新宏和宏处理器.

它处理传递和提取索引值,而不是文本翻译.该示例包含修改后的代码,但最终如下:

#define DDX_COMBO_INDEX(nID, var) \if(nCtlID == (UINT)-1 || nCtlID == nID) \{ \if(!DDX_Combo_Index(nID, var, TRUE, bSaveAndValidate)) \return FALSE; \}

其次:

template <class Type>
BOOL DDX_Combo_Index(UINT nID, Type& nVal, BOOL bSigned, BOOL bSave, BOOL bValidate = FALSE, Type nMin = 0, Type nMax = 0)
{T* pT = static_cast<>(this);BOOL bSuccess = TRUE;if(bSave){nVal = ::SendMessage((HWND) (Type)pT->GetDlgItem(nID), CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); bSuccess = (nVal == CB_ERR ? false : true);}else{ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax);int iRet = |::SendMessage((HWND) (Type)pT->GetDlgItem(nID), CB_SETCURSEL, (WPARAM) nVal, (LPARAM) 0);bSuccess = (iRet == CB_ERR ? false : true);}
|if(!bSuccess){pT->OnDataExchangeError(nID, bSave);}else if(bSave && bValidate)|//验证{ATLASSERT(nMin != nMax);if(nVal < nMin || nVal > nMax){_XData data;data.nDataType = ddxDataInt;data.intData.nVal = (long)nVal;data.intData.nMin = (long)nMin;data.intData.nMax = (long)nMax;pT->OnDataValidateError(nID, bSave, data);bSuccess = FALSE;}}return bSuccess;
}

这样,就可成功处理组合框UI中的索引.另一个问题是我想用的UI是有两个单选按钮,代表用户的true/false选择.
因此,我添加了另一个扩展DDX_BOOL_RADIO,它带两个资源ID,如下:

DDX_BOOL_RADIO(<primary radio buttonID>,<BOOL variable>,<Secondary radio buttonID>)

作用是确保在加载中,根据变量的状态,仅选择两个按钮中的一个.如果为,则选中主ID单选按钮,单选按未选中初化按钮,如果初始加载值,则相反.

默认数据处理器

以下是默认DDX/DDV处理器的列表:

DDX_TEXT(nID, var)
DDX_TEXT_LEN(nID, var, len)
DDX_INT(nID, var)
DDX_INT_RANGE(nID, var, min, max)
DDX_UINT(nID, var)
DDX_UINT_RANGE(nID, var, min, max)
DDX_FLOAT(nID, var)
DDX_FLOAT_RANGE(nID, var, min, max)
//注意:你必须定义`_ATL_USE_DDX_FLOAT`才能交换`浮点`值.
DDX_CONTROL(nID, obj)
DDX_CHECK(nID, var)
DDX_RADIO(nID, var)

见,wtlddx

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • vscode从本地安装插件
  • 数据集 Ubody人体smplx三维建模mesh-姿态估计 >> DataBall
  • Win10磁盘出现小锁和感叹号的解决办法
  • Nexus配置npm私服
  • 深度学习(九)-图像形态操作
  • UDP通信实现
  • 有希带你深入理解指针(4)
  • 软考-高级架构师Keywords(上半部分)
  • sping boot 基于 RESTful 风格,模拟增删改查操作
  • 伽罗华域GF的简单计算
  • 『功能项目』战士的A键连击【33】
  • 《深入探究 <侠盗猎车手 5>(GTA5)的 C++ 代码世界》
  • 脏页标记技术的优缺点详解
  • 【重学 MySQL】十五、过滤数据
  • React入门教程:创建你的第一个React应用
  • 【刷算法】求1+2+3+...+n
  • 【知识碎片】第三方登录弹窗效果
  • echarts的各种常用效果展示
  • Git 使用集
  • Java,console输出实时的转向GUI textbox
  • k8s 面向应用开发者的基础命令
  • python大佬养成计划----difflib模块
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 机器学习中为什么要做归一化normalization
  • 你真的知道 == 和 equals 的区别吗?
  • 驱动程序原理
  • 如何使用 JavaScript 解析 URL
  • 微信小程序开发问题汇总
  • 小程序button引导用户授权
  • 译有关态射的一切
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • C# - 为值类型重定义相等性
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #1014 : Trie树
  • #Linux(make工具和makefile文件以及makefile语法)
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (十二)Flink Table API
  • (十六)视图变换 正交投影 透视投影
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (转)Google的Objective-C编码规范
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • (转)树状数组
  • ... 是什么 ?... 有什么用处?
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .Net 6.0--通用帮助类--FileHelper
  • .NET Core中的去虚
  • .net mvc部分视图
  • .NET MVC第五章、模型绑定获取表单数据
  • .net分布式压力测试工具(Beetle.DT)
  • .NET企业级应用架构设计系列之开场白
  • @Controller和@RestController的区别?