MFC控件数据交换:DDX
来源:互联网 发布:淘宝试用官网 编辑:程序博客网 时间:2024/05/21 19:27
原博链接:http://blog.csdn.net/eldn__/article/details/38357643
MFC中操纵控件
操作控件的两种方式:
对话框的初始化函数:OnInitDialog()
方式2: 对话框的数据交换技术(DDX)
将控件和一个成员变量绑定,可以通过操作成员变量达到操作控件的目的。
1 定义与控件绑定的成员变量
2 在对话框中添加DoDataExchange()函数,在函数中完成控件
与变量的绑定。
DDX_Control()//控件类型的绑定
DDX_Text()//值类型的绑定
3 通过成员变量完成对控件的操作
4 值类型的绑定,还需要调用UpdateData(BOOL)函数
UpdateData(TRUE)- 控件中的值传赋值变量(接收)
UpdateData(FALSE)-将变量的值显示到控件上
新建一个Win32 Application,选择A Simple Win32 Application,修改stdafx.h 中的windwos.h为afxwin.h,工程属性设置使用MFC静态库。
编写如下测试代码:
- // DDX.cpp : Defines the entry point for the application.
- //
- #include "stdafx.h"
- #include "resource.h"
- class CMyDlg : public CDialog
- {
- public:
- CMyDlg ():CDialog(IDD_DIALOG1){}
- virtual void DoDataExchange (CDataExchange* pDX);
- virtual BOOL OnInitDialog ();
- virtual void OnOK();
- protected:
- CButton m_wndOK;
- CString m_strEdit;
- };
- void CMyDlg::DoDataExchange (CDataExchange* pDX)
- {
- //完成控件与变量的绑定
- DDX_Control (pDX, IDOK, m_wndOK);
- DDX_Text (pDX, IDC_EDIT1, m_strEdit);
- }
- BOOL CMyDlg::OnInitDialog ()
- {
- if (!CDialog::OnInitDialog())
- return FALSE;
- // 初始化控件
- // 方式一:通过GetDlgItem操作控件
- CWnd *pWnd = GetDlgItem (IDCANCEL);
- pWnd->EnableWindow (FALSE);
- m_wndOK.MoveWindow (0, 0, 100, 100);
- m_wndOK.SetWindowText ("DDXOK");
- // 方式二:通过DDX操作控件
- m_strEdit = "Hello you";
- UpdateData (FALSE);
- return TRUE;
- }
- void CMyDlg::OnOK ()
- {
- // 接收控件的值到关联的变量
- UpdateData (TRUE);
- AfxMessageBox (m_strEdit);
- CDialog::OnOK();
- }
- class CMyWinApp : public CWinApp
- {
- public:
- virtual BOOL InitInstance ();
- };
- CMyWinApp theApp;
- BOOL CMyWinApp::InitInstance ()
- {
- CMyDlg dlg;
- m_pMainWnd = &dlg;
- dlg.DoModal ();
- return TRUE;
- }
DDX的实现原理
1 控件类型的绑定
- DDX_Control (pDX, IDOK, m_wndOK);
- void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl)
- {// nIDC: IDCOK , rControl: m_wndOK
- ...................................
- // 通过控件ID得到控件句柄
- HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
- if (!rControl.SubclassWindow(hWndCtrl))
- {
- ..........................................
- }
- }
- DDX_Control-->SubclassWindow
跟进:
- BOOL CWnd::SubclassWindow(HWND hWnd)
- {// this == m_wndOK, hWnd == 控件句柄
- // 将m_wndOK控件变量与OK按钮句柄绑定
- if (!Attach(hWnd))
- return FALSE;
- ...............................................
- }
- DDX_Control-->SubclassWindow-->Attach
- BOOL CWnd::Attach(HWND hWndNew)
- {//this == m_wndOK, hWndNew == 控件句柄
- ......................................
- CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist
- ASSERT(pMap != NULL);
- // 建立映射关系
- pMap->SetPermanent(m_hWnd = hWndNew, this);
- ........................................
- }
- DDX_Control-->SubclassWindow-->Attach-->SetPermanent
跟进:
- void CHandleMap::SetPermanent(HANDLE h, CObject* permOb)
- {
- .......................................
- // 以控件句柄为键,以变量句柄为值建立映射关系
- m_permanentMap[(LPVOID)h] = permOb;
- .........................................
- }
Ok到这里就清晰了
总结流程如下:
- DDX_Control(pDX,IDOK,m_wndOK);
- {
- //通过控件ID得到控件句柄
- HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
- //将控件句柄与变量绑定
- rControl.SubclassWindow(hWndCtrl);
- {
- Attach(hWnd);
- {
- pMap->SetPermanent(m_hWnd = hWndNew, this);
- {
- //以句柄为健,以变量地址为值建立映射关系
- m_permanentMap[(LPVOID)h] = permOb;
- }
- }
- }
- }
2 值类型的绑定
- UpdateData (FALSE);
- BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
- {// this == &dlg, bSaveAndValidate == FALSE
- .............................................
- CDataExchange dx(this, bSaveAndValidate);
- ..........................................
- // 虚函数,会调用我们重写的函数
- DoDataExchange(&dx);
- ........................................
- }
- UpdateData-->DoDataExchange-->CMyDlg::DoDataExchange-->DDX_Text
跟进:
- void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value)
- {// pDX中保存了&dlg和FALSE, nIDC == IDOK, value == m_strEdit
- // 通过控件ID拿到编辑框控件句柄
- HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
- if (pDX->m_bSaveAndValidate)
- {// UpdateData (TRUE)
- int nLen = ::GetWindowTextLength(hWndCtrl);
- // 获取控件文本
- ::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
- value.ReleaseBuffer();
- }
- else
- {// UpdateData (FALSE)
- // 设置控件文本
- AfxSetWindowText(hWndCtrl, value);
- }
- }
总结上面的流程如下:
- UpdateData(FALSE);
- {
- CDataExchange dx(this, bSaveAndValidate);
- DoDataExchange(&dx);
- {
- DDX_Text(pDX,IDC_EDIT1,m_strEdit);
- {
- //通过控件ID得到控件句柄
- HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
- if (pDX->m_bSaveAndValidate)
- {
- ::GetWindowText(hWndCtrl,...);
- value.ReleaseBuffer();
- }
- else
- {
- //将变量的值设置到控件的窗口上
- AfxSetWindowText(hWndCtrl, value);
- }
- }
- }
- }
0 0
- MFC控件数据交换:DDX
- MFC控件数据交换:DDX
- MFC控件数据交换:DDX
- MFC—— 控件数据交换:DDX
- MFC中对话框的数据交换(DDX)和数据…
- WTL中的数据交换(DDX)
- MFC中对话框的数据交换(DDX)和数据校验(DDV)
- MFC中对话框的数据交换(DDX)和数据校验(DDV)
- MFC中对话框的数据交换(DDX)和数据校验(DDV)
- MFC中对话框的数据交换(DDX)和数据校验(DDV)。。。
- MFC中对话框的数据交换(DDX)和数据校验(DDV)
- MFC 控件变量数据交换
- MFC操作--控件显示及数据交换
- 动态数据交换(DDX)的另类用法
- VS2005 对话框数据交换 DDX 与 校验 DDV
- javascript与MFC ActiveX控件接口方法数据交换
- 1.2学习MFC之控件数据交换UpdateData
- VC中数据的动态交换技术DDV\DDX的实现方法
- 【数据结构】BST:二叉排序树算法
- verilog 变量命名注意事项
- 经典错误:插入for循环后程序无法运行
- 二进制运算
- linux信号处理函数
- MFC控件数据交换:DDX
- ssh tunnel 代理
- 动态代理可以使代理模式更加灵活
- 工厂方法PK抽象工厂
- ListView 中 getSelectedView() 和 getSelectedItem() 区别
- 如何自定义FragmentTabHost中某一个Tab的点击效果
- opencv学习篇(8)轮廓的查找、表达、绘制、特性及匹配
- 技术向:一文读懂卷积神经网络
- ——黑马程序员——OC中的多态