📄 csdn_文档中心_wtl for mfc programming实践篇 --- 一个自定义combobox的移植过程(下).htm
字号:
<TR>
<TD align=middle height=5></TD>
<TD align=middle width=500></TD></TR>
<TR>
<TD align=middle bgColor=#003399><FONT color=#ffffff>关键字</FONT></TD>
<TD width=500> WTL ATL MFC 移植 ComboBox 消息反射
DDX</TD></TR>
<TR>
<TD align=middle height=5></TD>
<TD align=middle width=500></TD></TR></TBODY></TABLE><!--文章说明信息结束//-->
<TABLE border=0 width=600>
<TBODY>
<TR>
<TD align=left><BR>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt">《程序员修炼之道》说当你想说这不可能的时候,往往是你在调用的方法上出现了错误。<SPAN
lang=EN-US><?xml:namespace prefix = o ns =
"urn:schemas-microsoft-com:office:office"
/><o:p></o:p></SPAN></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt">我们重新回到起点,来看看那里出了错。仔细地研读代码以后发现,事件是怎么传递到<SPAN
lang=EN-US>MSG_MAP</SPAN>的呢?难道我们通过赋值将一个窗体句柄传进来,我们在这个类中定义的<SPAN
lang=EN-US>MSG_MAP</SPAN>就能自动的连接到这个句柄上吗?这显然是真的不可能。<SPAN
lang=EN-US><o:p></o:p></SPAN></SPAN></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt">那么没有将<SPAN
lang=EN-US>MSG_MAP</SPAN>连接到窗体句柄很可能是控件类无法收到任何事件的原因。那么如何将<SPAN
lang=EN-US>MSG_MAP</SPAN>连接到窗体句柄上呢?原书中提到一个重要的函数,<SPAN
lang=EN-US>CWindowImpl::SubclassWindow()</SPAN>。我们再次更改我们的控件类:<SPAN
lang=EN-US><o:p></o:p></SPAN></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 1">
</SPAN>CComboBoxEx& <SPAN style="COLOR: blue">operator</SPAN>
=(HWND hWnd) {<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 2">
</SPAN>CWindowImpl< CComboBoxEx,
CComboBox>::SubclassWindow(hWnd); <o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 2">
</SPAN><SPAN style="COLOR: blue">return</SPAN> *<SPAN
style="COLOR: blue">this</SPAN>;<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 1">
</SPAN>}<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt"><SPAN
style="mso-tab-count: 1">
</SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt">一测之下,大吃一惊。不仅重画事件被正确触发,连析构函数中的没有<SPAN
lang=EN-US>Attach</SPAN>的<SPAN
lang=EN-US>Detach</SPAN>这个怪用法也可以删除了。为什么会这样呢?探究这个问题之前,让我们先看看原书使用的<SPAN
lang=EN-US>DDX_CONTROL</SPAN>宏<SPAN lang=EN-US> - </SPAN>它只针对<SPAN
lang=EN-US>CWindowImpl</SPAN>的派生类起作用<SPAN lang=EN-US> -
</SPAN>是怎么回事。原码如下:<SPAN lang=EN-US><o:p></o:p></SPAN></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 1"> </SPAN><SPAN
style="COLOR: blue">#define</SPAN> DDX_CONTROL(nID, obj)
\<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 2">
</SPAN><SPAN style="COLOR: blue">if</SPAN>(nCtlID == (UINT)-1 ||
nCtlID == nID) \<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 3">
</SPAN>DDX_Control(nID, obj,
bSaveAndValidate);<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="COLOR: blue; FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><o:p> </o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt"><SPAN
style="mso-tab-count: 1">
</SPAN></SPAN><SPAN lang=EN-US
style="COLOR: green; FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt">//
Full control subclassing (for CWindowImpl derived
controls)<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="COLOR: blue; FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt">template</SPAN><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt">
<<SPAN style="COLOR: blue">class</SPAN>
TControl><o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 1"> </SPAN><SPAN
style="COLOR: blue">void</SPAN> DDX_Control(UINT nID, TControl&
ctrl, BOOL bSave)<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 1">
</SPAN>{<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 2">
</SPAN><SPAN style="COLOR: blue">if</SPAN>(!bSave &&
ctrl.m_hWnd == NULL)<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 2">
</SPAN>{<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 3">
</SPAN>T* pT = <SPAN
style="COLOR: blue">static_cast</SPAN><T*>(<SPAN
style="COLOR: blue">this</SPAN>);<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 3">
</SPAN>ctrl.SubclassWindow(pT->GetDlgItem(nID));<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 2">
</SPAN>}<o:p></o:p></SPAN></P>
<P align=left class=MsoNormal
style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none"><SPAN
lang=EN-US
style="FONT-FAMILY: 新宋体; FONT-SIZE: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><SPAN
style="mso-tab-count: 1">
</SPAN>}<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt"><SPAN
style="mso-tab-count: 1">
</SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt">从原码可以看到,<SPAN
lang=EN-US>DDX_CONTROL</SPAN>宏和<SPAN
lang=EN-US>DDX_CONTROL_HANDLER</SPAN>宏实现的区别只是,前者使用<SPAN
lang=EN-US>SubclassWindow</SPAN>,而后者使用操作符“<SPAN
lang=EN-US>=</SPAN>”。如果把我们上面的代码联系起来,在操作符“<SPAN
lang=EN-US>=</SPAN>”的处理函数中调用<SPAN
lang=EN-US>SubclassWindow</SPAN>,其实就等于是明着使用<SPAN
lang=EN-US>DDX_CONTROL_HANDLER</SPAN>宏,暗地里却把<SPAN
lang=EN-US>DDX_CONTROL</SPAN>宏实现了。原来想出门,结果先绕着后院跑了<SPAN
lang=EN-US>3</SPAN>圈,这真是一个大笑话。<SPAN
lang=EN-US><o:p></o:p></SPAN></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US
style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt"><SPAN
style="mso-tab-count: 1">
</SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt">为什么会这样呢?不使用<SPAN
lang=EN-US>DDX_CONTROL</SPAN>宏是因为<SPAN
lang=EN-US>CComboBox</SPAN>没有<SPAN
lang=EN-US>SubclassWindow</SPAN>函数,而是用<SPAN
lang=EN-US>CComboBox</SPAN>是因为在<SPAN lang=EN-US>MFC</SPAN>中<SPAN
lang=EN-US>CComboBoxEx</SPAN>就是从<SPAN
lang=EN-US>CComboBox</SPAN>派生,移植的时候当然倾向于选择同名的类,而不是<SPAN
lang=EN-US>CWindowImpl<CComboBoxEx,
CComboBox></SPAN>这样怪怪的声明方法。<SPAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -