MFC控件数据交换:DDX

来源:互联网 发布:淘宝试用官网 编辑:程序博客网 时间:2024/05/21 19:27

原博链接:http://blog.csdn.net/eldn__/article/details/38357643


   MFC中操纵控件

   操作控件的两种方式:


   方式1:通过调用CWnd::GetDlgItem()函数,根据控件ID获取控件对象指针,操作控件即可。
                对话框的初始化函数: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静态库。

编写如下测试代码:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. // DDX.cpp : Defines the entry point for the application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "resource.h"  
  6. class CMyDlg : public CDialog  
  7. {  
  8. public:  
  9.     CMyDlg ():CDialog(IDD_DIALOG1){}  
  10.     virtual void DoDataExchange (CDataExchange* pDX);  
  11.     virtual BOOL OnInitDialog ();  
  12.     virtual void OnOK();  
  13. protected:  
  14.     CButton m_wndOK;  
  15.     CString m_strEdit;  
  16. };  
  17. void CMyDlg::DoDataExchange (CDataExchange* pDX)  
  18. {  
  19.     //完成控件与变量的绑定  
  20.     DDX_Control (pDX, IDOK, m_wndOK);  
  21.     DDX_Text (pDX, IDC_EDIT1, m_strEdit);  
  22. }  
  23. BOOL CMyDlg::OnInitDialog ()  
  24. {  
  25.     if (!CDialog::OnInitDialog())  
  26.         return FALSE;  
  27.     // 初始化控件  
  28.     // 方式一:通过GetDlgItem操作控件  
  29.     CWnd *pWnd = GetDlgItem (IDCANCEL);  
  30.     pWnd->EnableWindow (FALSE);  
  31.     m_wndOK.MoveWindow (0, 0, 100, 100);  
  32.     m_wndOK.SetWindowText ("DDXOK");  
  33.   
  34.     // 方式二:通过DDX操作控件  
  35.     m_strEdit = "Hello you";  
  36.     UpdateData (FALSE);  
  37.     return TRUE;  
  38. }  
  39. void CMyDlg::OnOK ()  
  40. {  
  41.     // 接收控件的值到关联的变量  
  42.     UpdateData (TRUE);  
  43.     AfxMessageBox (m_strEdit);  
  44.     CDialog::OnOK();  
  45. }  
  46. class CMyWinApp : public CWinApp  
  47. {  
  48. public:  
  49.     virtual BOOL InitInstance ();  
  50. };  
  51. CMyWinApp theApp;  
  52. BOOL CMyWinApp::InitInstance ()  
  53. {  
  54.     CMyDlg dlg;  
  55.     m_pMainWnd = &dlg;  
  56.     dlg.DoModal ();  
  57.     return TRUE;  
  58. }  

DDX的实现原理  

1 控件类型的绑定

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. DDX_Control (pDX, IDOK, m_wndOK);  
跟进:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl)  
  2. {// nIDC: IDCOK   , rControl: m_wndOK  
  3.     ...................................  
  4.     // 通过控件ID得到控件句柄  
  5.     HWND hWndCtrl = pDX->PrepareCtrl(nIDC);  
  6.   
  7.     if (!rControl.SubclassWindow(hWndCtrl))  
  8.     {  
  9.         ..........................................  
  10.     }  
  11. }  
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. DDX_Control-->SubclassWindow  

跟进:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. BOOL CWnd::SubclassWindow(HWND hWnd)  
  2. {// this == m_wndOK, hWnd == 控件句柄  
  3.     // 将m_wndOK控件变量与OK按钮句柄绑定  
  4.     if (!Attach(hWnd))  
  5.         return FALSE;  
  6.     ...............................................  
  7. }  
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. DDX_Control-->SubclassWindow-->Attach  
跟进:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. BOOL CWnd::Attach(HWND hWndNew)  
  2. {//this == m_wndOK, hWndNew == 控件句柄  
  3.     ......................................  
  4.     CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist  
  5.     ASSERT(pMap != NULL);  
  6.     // 建立映射关系  
  7.     pMap->SetPermanent(m_hWnd = hWndNew, this);  
  8.     ........................................  
  9. }  
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. DDX_Control-->SubclassWindow-->Attach-->SetPermanent  

跟进:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. void CHandleMap::SetPermanent(HANDLE h, CObject* permOb)  
  2. {  
  3.     .......................................  
  4.     // 以控件句柄为键,以变量句柄为值建立映射关系  
  5.     m_permanentMap[(LPVOID)h] = permOb;  
  6.     .........................................  
  7. }  

Ok到这里就清晰了

  总结流程如下:

   

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. DDX_Control(pDX,IDOK,m_wndOK);  
  2. {  
  3.   //通过控件ID得到控件句柄  
  4.   HWND hWndCtrl = pDX->PrepareCtrl(nIDC);  
  5.   //将控件句柄与变量绑定  
  6.   rControl.SubclassWindow(hWndCtrl);  
  7.   {  
  8.      Attach(hWnd);  
  9.      {  
  10.         pMap->SetPermanent(m_hWnd = hWndNew, this);  
  11.         {  
  12.           //以句柄为健,以变量地址为值建立映射关系  
  13.           m_permanentMap[(LPVOID)h] = permOb;  
  14.         }  
  15.      }  
  16.   }  
  17. }   

2 值类型的绑定

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. UpdateData (FALSE);  
跟进:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. BOOL CWnd::UpdateData(BOOL bSaveAndValidate)  
  2. {// this == &dlg,  bSaveAndValidate == FALSE  
  3.     .............................................  
  4.   
  5.     CDataExchange dx(this, bSaveAndValidate);  
  6.   
  7.      ..........................................  
  8.      // 虚函数,会调用我们重写的函数  
  9.      DoDataExchange(&dx);  
  10.      ........................................  
  11. }  
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. UpdateData-->DoDataExchange-->CMyDlg::DoDataExchange-->DDX_Text  

跟进:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value)  
  2. {// pDX中保存了&dlg和FALSE, nIDC == IDOK, value == m_strEdit  
  3.     // 通过控件ID拿到编辑框控件句柄  
  4.     HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);  
  5.     if (pDX->m_bSaveAndValidate)  
  6.     {// UpdateData (TRUE)  
  7.         int nLen = ::GetWindowTextLength(hWndCtrl);  
  8.         // 获取控件文本  
  9.         ::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);  
  10.         value.ReleaseBuffer();  
  11.     }  
  12.     else  
  13.     {// UpdateData (FALSE)  
  14.         // 设置控件文本  
  15.         AfxSetWindowText(hWndCtrl, value);  
  16.     }  
  17. }  

总结上面的流程如下:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1.  UpdateData(FALSE);  
  2.  {  
  3.     CDataExchange dx(this, bSaveAndValidate);  
  4.     DoDataExchange(&dx);  
  5.     {  
  6.        DDX_Text(pDX,IDC_EDIT1,m_strEdit);  
  7.        {  
  8.          //通过控件ID得到控件句柄  
  9.          HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);  
  10.          if (pDX->m_bSaveAndValidate)  
  11.   {  
  12.   
  13. ::GetWindowText(hWndCtrl,...);   
  14. value.ReleaseBuffer();  
  15.   }  
  16.   else  
  17.   {  
  18.               //将变量的值设置到控件的窗口上  
  19. AfxSetWindowText(hWndCtrl, value);  
  20.   }  
  21.            
  22.        }  
  23.     }  
  24.  }  
0 0
原创粉丝点击