WTL for MFC Programming实践篇
--- 一个自定义ComboBox的移植过程
现在有一个MFC写的自定义ComboBox打算移植到WTL上,于是根据WTL的书写方法修改了程序,就得到下面的代码:
Class CComboBoxEx : public CComboBox
{
protected:
void OnDrawItem(UINT wParam, LPDRAWITEMSTRUCT lpDrawItemStruct);
public:
BEGIN_MSG_MAP_EX(CComboBoxEx)
MSG_OCM_DRAWITEM(OnDrawItem)
END_MSG_MAP()
}
Class CMainDlg : public CDialogImpl< CMainDlg >
{
Protected:
CComboBoxEx m_cmbEx;
Public:
BEGIN_DDX_MAP(CPageConfigFont)
DDX_CONTROL_HANDLE(IDC_COMBOBOXEX, m_cmbEx);
END_DDX_MAP()
BEGIN_MSG_MAP_EX(CPageConfigFont)
MSG_WM_INITDIALOG(OnInitDialog)
REFLECT_NOTIFICATIONS()
END_MSG_MAP()
}
如何生成以上代码及代码的含义,原书都有介绍,由于不是本文的重点,不再一一解释。
要说的是,在WTL 7.1中添加了DDX_CONTROL_HANDLE宏,可以用来设置控件,与DDX_CONTROL不同的是,它不要求控件类由CWindowImpl派生,即不需要包含SubclassWindow()函数,这样我们才可以使用DDX来设置我们从CComboBox派生的类(听上去很有道理,其实却是在MFC编程习惯带动下错误思维)。
当然,要实现还有一个小小的问题,DDX_CONTROL_HANDLE宏需要我们的类包含一个操作符“=”,怎么写这个函数呢?参看了一下基类的实现方法:
CComboBoxExT< TBase >& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
参看WTL文件<atlctrls.h>
原来只是将m_hWnd赋值,于是我们在我们的类中添加如下的代码:
CComboBoxEx& operator=(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
于是编译通过了。(殊不知潜在的错误就这样被深深的埋起来了)
可是为什么DDX_CONTROL_HANDLE宏需要我们的类包含操作符“=”呢?我们来看看DDX_CONTROL_HANDLE宏是怎么实现的:
整个DDX_MAP其实是定义了一个DoDataExchange函数,BEGIN_DDX_MAP宏定义了函数头,而END_DDX_MAP定义了函数尾,中间一项项的DDX定义函数的具体内容,而当你在代码中定义DDX_MAP的时候就等于重载了CWinDataExchange::DoDataExchange()函数,具体代码如下:
#define BEGIN_DDX_MAP(thisClass) \
BOOL DoDataExchange(BOOL bSaveAndValidate = FALSE, UINT nCtlID = (UINT)-1) \
{ \
bSaveAndValidate; \
nCtlID;
#define END_DDX_MAP() \
return TRUE; \
}
参看WTL文件<atlddx.h>
对于DDX_CONTROL_HANDLE宏,它其实是调用了CWinDataExchange:: DDX_Control_Handle函数,具体代码如下:
// Simple control attaching (for HWND wrapper controls)
template <class TControl>
void DDX_Control_Handle(UINT nID, TControl& ctrl, BOOL bSave)
{
if(!bSave && ctrl.m_hWnd == NULL
(编辑:aniston)
|