2409wtl,wtl与ddx

news/2024/9/17 7:10:03/ 标签: wtl

原文

介绍

借助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


http://www.ppmy.cn/news/1521909.html

相关文章

【HTML】script标签asyncdefer

<script> 标签中的 defer 和 async 属性是用来控制外部脚本加载和执行时机的重要机制&#xff0c;它们可以帮助优化网页加载速度和用户体验。 async 属性 async 表示异步加载脚本。当 <script> 标签包含 async 属性时&#xff1a; 脚本下载和其他资源&#xff0…

Qt 控件学习指南

Qt基础 项目控件组(Item Widgets) 包括&#xff1a; - List Widget: 清单控件 - Tree Widget: 树形控件 - Table Widget: 表控件 创建具有复选框的树形控件的步骤&#xff1a; 1. 新建Qt Widgets Application项目&#xff0c;基类选择"QWidget"。 2. 在界面设计…

C# WPF 读取西门子S7系列PLC

在C# WPF应用程序中&#xff0c;与西门子S7系列PLC进行通信是一个常见的需求&#xff0c;尤其是在工业自动化领域。以下是三种实现WPF上位机与西门子S7系列PLC通信同步的方式&#xff0c;每种方式都提供了代码实例、优缺点和使用场景。 1. 使用S7.Net库 代码示例&#xff1a; c…

【C-LeetCode】977 有序数组的平方

一、暴力解法 测试代码 #include <stdio.h> #include <stdlib.h>int* sortedSquares(int* nums, int numsSize, int* returnSize); void print(int *nums, int len);int main() {int nums[] { -19, -10, -7, -4, -3, 0, 1, 3, 6, 7, 9, 10 };int len sizeof(nums…

LAN变压器的DCR

在变压器技术中&#xff0c;DCR代表直流电阻&#xff08;DC Resistance&#xff09;。它是变压器线圈在直流条件下测得的电阻值&#xff0c;通常用来评估变压器的质量和效率。直流电阻是线圈材料和尺寸的一个函数&#xff0c;它与变压器线圈的发热量和功率损耗直接相关。在变压…

Web3与AI的融合:开启去中心化应用的新纪元

在数字科技不断发展的今天&#xff0c;Web3与人工智能&#xff08;AI&#xff09;的融合正引领去中心化应用&#xff08;DApps&#xff09;的新纪元。这种结合不仅扩展了去中心化技术的应用场景&#xff0c;还为智能应用提供了更加高效和创新的解决方案。本文将深入探讨Web3与A…

Pyspark中catalog的作用与常用方法

文章目录 Pyspark catalog用法catalog 介绍cache 缓存表uncache 清除缓存表cleanCache 清理所有缓存表createExternalTable 创建外部表currentDatabase 返回当前默认库tableExists 检查数据表是否存在&#xff0c;包含临时视图databaseExists 检查数据库是否存在dropGlobalTemp…

React-CSS

1. React中的样式 React并没有像Vue那样提供特定的区域给我们编写CSS代码 所以你会发现在React代码中, CSS样式的写法千奇百怪 2. 内联样式 内联样式的优点: 内联样式, 样式之间不会有冲突 可以动态获取当前state中的状态 内联样式的缺点&#xff1a; 写法上都需要使用驼峰标…

前端框架有哪些

前端框架有哪些 前端框架是用来帮助开发者构建用户界面和交互的库或工具。以下是一些流行的前端框架&#xff1a; React: 由 Facebook 维护的一个声明式、高效且灵活的 JavaScript 库&#xff0c;用于构建用户界面。 Vue.js: 一个渐进式 JavaScript 框架&#xff0c;用于构建…

python数值误差

最近在用fenics框架跑有限元代码&#xff0c;其中有一个部分是把在矩阵里定义的初始值&#xff0c;赋值到有限元空间里&#xff0c;这就涉及到了初始矩阵和有限元空间坐标的转化&#xff0c;部分代码如下 for i in range(len(dof_coordinates)):# x, y dof_coordinates[i…

梨花声音教育退费普通话学习听力练习

在学习普通话的过程中&#xff0c;提高听力能力是至关重要的一环。听力不仅是语言理解的基础&#xff0c;也是口语表达的重要前提。通过系统的听力训练和有效的方法&#xff0c;我们可以逐步提升普通话的听力水平&#xff0c;进而实现流利的沟通交流。以下是一些提高普通话听力…

HTML:charset讲解

charset 1. 什么是字符编码?2. 常见的字符编码类型ASCII&#xff08;American Standard Code for Information Interchange&#xff09;ISO-8859-1&#xff08;Latin-1&#xff09;UTF-8&#xff08;8-bit Unicode Transformation Format&#xff09;GB2312/GBK 3. HTML中的ch…

scrapy 爬取微博(一)【最新超详细解析】:创建微博爬取工程

本项目属于个人学习记录&#xff0c;爬取的数据会于12小时内销毁&#xff0c;且不可用于商用。 1 初始化环境 首先我们需要有python环境&#xff0c;先安装一下python&#xff0c;然后配置环境变量&#xff0c;这边给出windows的配置&#xff1a; 我这边的安装目录是D:\pyt…

ClickHouse 二进制特征值怎么转化为字符串

要将二进制特征值转化为字符串&#xff0c;可以使用以下方法&#xff1a; 1. 使用 base64 编码 base64 是一种将二进制数据编码为 ASCII 字符串的方法。在 ClickHouse 中&#xff0c;可以使用函数 base64Encode() 来将二进制特征值转化为 base64 编码的字符串。例如&#xff…

idea问题解决:java: -source 7 中不支持 方法引用 (请使用 -source 8 或更高版本以启用 方法引用)

以下是AI生成 &#xff1a;鱼聪明AI - 做您强大的AI助手 这个错误信息表明你尝试使用了Java 8中引入的方法引用特性&#xff0c;但是你的编译器设置使用的源代码版本是Java 7。方法引用是Java 8中引入的一个新特性&#xff0c;允许你以更简洁的方式调用方法。 要解决这个问题…

基于opencv实现双目立体匹配点云距离

双目相机或两个单目相机。 一、相机标定 MATLAB软件&#xff0c;打开双目标定app。 点击add images&#xff0c;弹出加载图像的窗口&#xff0c;分别导入左图和右图&#xff0c;设置黑白格长度&#xff08;标定板的长度一般为20&#xff09;。 点击确定&#xff0c;弹出加载…

pdf转word怎么转换?2024快速进行文件格式转换的几款软件

pdf转word怎么转换&#xff1f;2024快速进行文件格式转换的几款软件 将PDF文件转换为Word文档是日常工作中常见的需求&#xff0c;尤其是当你需要编辑或重新利用PDF中的内容时。市面上有许多软件可以帮助你轻松完成PDF转Word的任务&#xff0c;以下是五款值得推荐的软件&#…

ArcGIS Pro SDK (十二)布局 11 报告

ArcGIS Pro SDK (十二)布局 11 报告 文章目录 ArcGIS Pro SDK (十二)布局 11 报告1 报告项目项1.1 获取当前项目中的所有报告1.2 获取特定报告1.3 在新视图中打开报告项目项1.4 激活已打开的报告视图1.5 引用活动报告视图1.5 刷新报告视图1.7 缩放到整个页面1.8 缩放到报告…

计算机网络10——数据库语法1

目录 1、sql语句执行顺序 2、多表查询 3、写sql的步骤 4、去重 5、视图 6、自定义函数:function 7、调用函数 1、sql语句执行顺序 一般情况下:1、from 2、where 3、select 如果有分组和having:from 分组 having最后执行 2、多表查询 内联:select * from 表1 inne…

EI会议推荐-第二届大数据与数据挖掘国际会议(BDDM 2024)

第二届大数据与数据挖掘国际会议&#xff08;BDDM 2024&#xff09; 1、基本信息 大会官网&#xff1a;http://www.icbddm.org/ 官方邮箱&#xff1a;icbddm163.com 主办方&#xff1a;武汉纺织大学 会议时间&#xff1a;2024年12月13日-12月15日 会议地点&#xff1a;湖…