1. 使用GetDlgItem函数来访问对话框中的控件:
1) 函数原型:CWnd* CWnd::GetDlgItem(int nID) const;
2) 只要参数指定为要访问的控件的ID,即可返回该控件的指针,但要注意的是返回的是CWnd*类型的指针,是所有窗口类型的父类;
2. 安全地利用GetDlgItem返回的指针来访问控件:
1) 如果想访问的是CWnd就有的功能则可以不做任何处理直接访问,例如:
CWnd* pWnd = GetDlgItem(IDC_CHECK); pWnd->EnableWindow(TRUE);!由于使控件(或窗口)有效的函数EnableWindow直接继承自CWnd,因此可以不做任何处理放心地使用;
2) 拙劣而危险的用法——强类型转换:
i. 如果想访问控件特有的功能,则可以尝试将GetDlgItem的返回值强制转换为控件所对应的类型,例如:
CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST); pListBox->AddString(_T("One"));ii. 上面的代码之所以可以运行那是因为MFC对CListBox这种控件有特殊的支持,换做其它的,例如CComboBox就会失效!!
iii. 绝对不推荐用这种方法来访问控件的特有功能,因为MFC对这样的用法不太支持,有些情况下会产生严重错误,而有些情况下则不起任何作用;
3) 局部范围内临时访问对话框中的控件——利用控件类型的Attach函数来绑定对话框中的控件:
i. 设想:在对话框中类中定义空的控件类型的对象作为数据成员,然后利用这些对象的Attach函数将空的对象和对话框中的控件资源绑定起来,这样就可以利用这些对象正常访问控件的功能了;
ii. 例如:
CListBox m_wndListBox; m_wndListBox.Attach(GetDlgItem(IDC_LIST)->m_hWnd); m_wndListBox.AddString(_T("One")); m_wndListBox.Detach();!!注意:如果这样的对象是在局部函数中定义的,则一定要在使用完后解除绑定,否则控件资源会随着对象一并释放掉,这就会导致对话框中的控件莫名地突然消失!!
!!Attach和Detach均是从CWnd继承而来,注意Attach的参数是HWND类型的,所以要用控件的m_hWnd作为参数传入;
!!!该方法仍然不是最优先推荐使用的,因为该方法使用的最多的情况是在局部函数中临时要访问控件,因此一旦Attach就必定跟着一个Detach,如果将绑定的对象主体作为窗口的数据成员的话,则Attach需要放在对话框的构造函数中使用,而Detach则要放对话框的析构函数中使用,这就会产生一个问题,如果这开发的仅仅是一个库供别人使用,而别人在不知情的情形下又在某个局部函数中再次Attach,即重复绑定,这会造成运行时错误(不能重复绑定和解除绑定),因此这种方法只推荐在局部函数中访问控件时使用的一种临时访问法;
!!因此上面的设想并不好!!!!
4) 将控件编程对话框的数据成员的完美解决方案——DDX_Control:
i. 要实现上面的设想MFC提供了完美的解决方案,上面设想中定义的空的空间类成员m_wndXXX,可以在DoDataExchange中用DDX_Control和相应的对话框控件资源完美而安全地联系起来,然后就利用该数据成员肆无忌惮地访问控件的功能,并不用在对话框的构造寒素和析构函数中使用Attach和Detach进行绑定和解绑!!
ii. 函数原型:void AFXAPI DDX_Control(CDataExchange* pDX, int nID, CWnd& rControl);
iii. 使用示例:
// 在对话框派生类中定义相应的控件类对象 class CMyDialog: public CDialog { ... CListBox m_wndListBox; ... }; // 然后在DoDataExchange函数中用DDX_Control将该对象和控件资源联系起来 void CMyDialog::DoDataExchange(CDataExchange* pDX) { ... DDX_Control(pDX, IDC_LISTBOX, m_wndListBox); ... } // 最后就可以随意访问对话框控件的功能 m_wndListBox.AddString(_T("One"));5) DDX_Control的附加功能:
i. 有时你希望在对话框中使用自定义的控件,比如利用CListBox派生出一个你自定义的具有特异功能的列表框,并且你想在对话框中添加它,那么现在有一个重要的问题需要解决,那就是这种自定义的控件无法在资源脚本.rc文件中定义,.rc中只能定义MFC预定义的控件;
ii. 现在DDX_Control又能完美解决这个问题,在.rc中还是照样定义普通类型的基本控件,然后在对话框中照样定义自定义的控件类型的对象(比如CMyListBox m_wndMyListBox),最后还是用DDX_Control将.rc中定义的普通控件和对象联系起来即可,比如DDX_Control(pDX, IDC_LISTBOX, m_wndMyListBox);
iii. 这就是DDX_Control的附加功能,即可以对资源脚本中定义的普通控件作向下扩展,将其扩展为自定义类型的派生类对象,这种不仅仅是类型上的向下扩展,也是功能上彻彻底底地向下扩展;