⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wtl for mfc programmers, part iv.mht

📁 大家知道wtl是window UI库
💻 MHT
📖 第 1 页 / 共 5 页
字号:
use.</P><PRE>CMainDlg::CMainDlg() : m_wndOKBtn(<SPAN =
class=3Dcpp-keyword>this</SPAN>, <SPAN class=3Dcpp-literal>1</SPAN>),=20
                       m_wndExitBtn(<SPAN =
class=3Dcpp-keyword>this</SPAN>, <SPAN class=3Dcpp-literal>2</SPAN>)
{
}</PRE>
      <P>The constructor parameters are a <CODE>CMessageMap*</CODE> and =
an=20
      <CODE>ALT_MSG_MAP</CODE> section number. The first parameter will =
usually=20
      be <CODE><SPAN class=3Dcpp-keyword>this</SPAN></CODE>, meaning =
that the=20
      dialog's own message map will be used, and the second parameter =
tells the=20
      object which <CODE>ALT_MSG_MAP</CODE> section it should send its =
messages=20
      to.</P>
      <P>Finally, we associate each <CODE>CContainedWindow</CODE> with a =

      control.</P><PRE>LRESULT CMainDlg::OnInitDialog(...)
{
<SPAN class=3Dcpp-comment>// ...</SPAN>
    <SPAN class=3Dcpp-comment>// Attach CContainedWindows to OK and Exit =
buttons</SPAN>
    m_wndOKBtn.SubclassWindow ( GetDlgItem(IDOK) );
    m_wndExitBtn.SubclassWindow ( GetDlgItem(IDCANCEL) );
=20
    <SPAN class=3Dcpp-keyword>return</SPAN> TRUE;
}</PRE>
      <P>Here are the new <CODE>WM_SETCURSOR</CODE> =
handlers:</P><PRE>LRESULT CMainDlg::OnSetCursor_OK (
    HWND hwndCtrl, UINT uHitTest, UINT uMouseMsg )
{
<SPAN class=3Dcpp-keyword>static</SPAN> HCURSOR hcur =3D LoadCursor ( =
NULL, IDC_HAND );
=20
    <SPAN class=3Dcpp-keyword>if</SPAN> ( NULL !=3D hcur )
        {
        SetCursor ( hcur );
        <SPAN class=3Dcpp-keyword>return</SPAN> TRUE;
        }
    <SPAN class=3Dcpp-keyword>else</SPAN>
        {
        SetMsgHandled(<SPAN class=3Dcpp-keyword>false</SPAN>);
        <SPAN class=3Dcpp-keyword>return</SPAN> FALSE;
        }
}
=20
LRESULT CMainDlg::OnSetCursor_Exit (
    HWND hwndCtrl, UINT uHitTest, UINT uMouseMsg )
{
<SPAN class=3Dcpp-keyword>static</SPAN> HCURSOR hcur =3D LoadCursor ( =
NULL, IDC_NO );
=20
    <SPAN class=3Dcpp-keyword>if</SPAN> ( NULL !=3D hcur )
        {
        SetCursor ( hcur );
        <SPAN class=3Dcpp-keyword>return</SPAN> TRUE;
        }
    <SPAN class=3Dcpp-keyword>else</SPAN>
        {
        SetMsgHandled(<SPAN class=3Dcpp-keyword>false</SPAN>);
        <SPAN class=3Dcpp-keyword>return</SPAN> FALSE;
        }
}</PRE>
      <P>If you wanted to use <CODE>CButton</CODE> features, you could =
declare=20
      the variables as:</P><PRE>    CContainedWindowT&lt;CButton&gt; =
m_wndOKBtn;</PRE>
      <P>and then the <CODE>CButton</CODE> methods would be =
available.</P>
      <P>You can see the <CODE>WM_SETCURSOR</CODE> handlers in action =
when you=20
      move the cursor over the buttons:</P>
      <P><IMG height=3D220 alt=3D" [OK button cursor - 5K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC4/okbtncur.png" =
width=3D333=20
      align=3Dbottom border=3D0> <IMG height=3D220 alt=3D" [Exit button =
cursor - 5K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC4/exitbtncur.png" =
width=3D333=20
      align=3Dbottom border=3D0></P>
      <H3><A name=3Datl3></A>ATL Way 3 - Subclassing</H3>
      <P>Method 3 involves creating a <CODE>CWindowImpl</CODE>-derived =
class and=20
      using it to subclass a control. This is similar to method 2, =
however the=20
      message handlers go in the <CODE>CWindowImpl</CODE> class instead =
of the=20
      dialog class.</P>
      <P>ControlMania1 uses this method to subclass the <I>About</I> =
button in=20
      the main dialog. Here is the <CODE>CButtonImpl</CODE> class, which =
is=20
      derived from <CODE>CWindowImpl</CODE> and handles=20
      <CODE>WM_SETCURSOR</CODE>:</P><PRE><SPAN =
class=3Dcpp-keyword>class</SPAN> CButtonImpl : <SPAN =
class=3Dcpp-keyword>public</SPAN> CWindowImpl&lt;CButtonImpl, =
CButton&gt;
{
    BEGIN_MSG_MAP_EX(CButtonImpl)
        MSG_WM_SETCURSOR(OnSetCursor)
    END_MSG_MAP()
=20
    LRESULT OnSetCursor(HWND hwndCtrl, UINT uHitTest, UINT uMouseMsg)
    {
    <SPAN class=3Dcpp-keyword>static</SPAN> HCURSOR hcur =3D LoadCursor =
( NULL, IDC_SIZEALL );
=20
        <SPAN class=3Dcpp-keyword>if</SPAN> ( NULL !=3D hcur )
            {
            SetCursor ( hcur );
            <SPAN class=3Dcpp-keyword>return</SPAN> TRUE;
            }
        <SPAN class=3Dcpp-keyword>else</SPAN>
            {
            SetMsgHandled(<SPAN class=3Dcpp-keyword>false</SPAN>);
            <SPAN class=3Dcpp-keyword>return</SPAN> FALSE;
            }
    }
};</PRE>
      <P>Then in the main dialog, we declare a <CODE>CButtonImpl</CODE> =
member=20
      variable:</P><PRE><SPAN class=3Dcpp-keyword>class</SPAN> CMainDlg =
: <SPAN class=3Dcpp-keyword>public</SPAN> CDialogImpl&lt;CMainDlg&gt;
{
<SPAN class=3Dcpp-comment>// ...</SPAN>
<SPAN class=3Dcpp-keyword>protected</SPAN>:
    CContainedWindow m_wndOKBtn, m_wndExitBtn;
    <B>CButtonImpl m_wndAboutBtn;</B>
};</PRE>
      <P>And finally, in <CODE>OnInitDialog()</CODE>, we subclass the=20
button.</P><PRE>LRESULT CMainDlg::OnInitDialog(...)
{
<SPAN class=3Dcpp-comment>// ...</SPAN>
    <SPAN class=3Dcpp-comment>// Attach CContainedWindows to OK and Exit =
buttons</SPAN>
    m_wndOKBtn.SubclassWindow ( GetDlgItem(IDOK) );
    m_wndExitBtn.SubclassWindow ( GetDlgItem(IDCANCEL) );
=20
    <B><SPAN class=3Dcpp-comment>// CButtonImpl: subclass the About =
button</SPAN>
    m_wndAboutBtn.SubclassWindow ( GetDlgItem(ID_APP_ABOUT) );</B>
=20
    <SPAN class=3Dcpp-keyword>return</SPAN> TRUE;
}</PRE>
      <H3><A name=3Dwtlway></A>The WTL Way - DDX</H3>
      <P>WTL's DDX (dialog data exchange) support works a lot like =
MFC's, and it=20
      can rather painlessly connect a variable to a control. To begin, =
you need=20
      a <CODE>CWindowImpl</CODE>-derived class as in the previous =
example. We'll=20
      be using a new class this time, <CODE>CEditImpl</CODE>, since this =
example=20
      will subclass the edit control. You also need to #include atlddx.h =
in=20
      stdafx.h to get the DDX code.</P>
      <P>To add DDX support to <CODE>CMainDlg</CODE>, add=20
      <CODE>CWinDataExchange</CODE> to the inheritance =
list:</P><PRE><SPAN class=3Dcpp-keyword>class</SPAN> CMainDlg : <SPAN =
class=3Dcpp-keyword>public</SPAN> CDialogImpl&lt;CMainDlg&gt;,=20
                 <B><SPAN class=3Dcpp-keyword>public</SPAN> =
CWinDataExchange&lt;CMainDlg&gt;</B>
{
<SPAN class=3Dcpp-comment>//...</SPAN>
};</PRE>
      <P>Next you create a DDX map in the class, which is similar to the =

      <CODE>DoDataExchange()</CODE> function that the ClassWizard =
generates in=20
      MFC apps. There are several <CODE>DDX_*</CODE> macros for varying =
types of=20
      data; the one we'll use here is <CODE>DDX_CONTROL</CODE> to =
connect a=20
      variable with a control. This time, we'll use =
<CODE>CEditImpl</CODE> that=20
      handles <CODE>WM_CONTEXTMENU</CODE> to do something when you =
right-click=20
      in the control.</P><PRE><SPAN class=3Dcpp-keyword>class</SPAN> =
CEditImpl : <SPAN class=3Dcpp-keyword>public</SPAN> =
CWindowImpl&lt;CEditImpl, CEdit&gt;
{
    BEGIN_MSG_MAP_EX(CEditImpl)
        MSG_WM_CONTEXTMENU(OnContextMenu)
    END_MSG_MAP()
=20
    <SPAN class=3Dcpp-keyword>void</SPAN> OnContextMenu ( HWND hwndCtrl, =
CPoint ptClick )
    {
        MessageBox(<SPAN class=3Dcpp-string>"Edit control handled =
WM_CONTEXTMENU"</SPAN>);
    }
};
=20
<SPAN class=3Dcpp-keyword>class</SPAN> CMainDlg : <SPAN =
class=3Dcpp-keyword>public</SPAN> CDialogImpl&lt;CMainDlg&gt;,=20
                 <SPAN class=3Dcpp-keyword>public</SPAN> =
CWinDataExchange&lt;CMainDlg&gt;
{
<SPAN class=3Dcpp-comment>//...</SPAN>
=20
    <B>BEGIN_DDX_MAP(CMainDlg)
        DDX_CONTROL(IDC_EDIT, m_wndEdit)
    END_DDX_MAP()</B>
=20
<SPAN class=3Dcpp-keyword>protected</SPAN>:
    CContainedWindow m_wndOKBtn, m_wndExitBtn;
    CButtonImpl m_wndAboutBtn;<B>
</B>    <B>CEditImpl   m_wndEdit;</B>
};</PRE>
      <P>Finally, in <CODE>OnInitDialog()</CODE>, we call the=20
      <CODE>DoDataExchange()</CODE> function that is inherited from=20
      <CODE>CWinDataExchange</CODE>. The first time=20
      <CODE>DoDataExchange()</CODE> is called, it subclasses controls as =

      necessary. So in this example, <CODE>DoDataExchange()</CODE> will =
subclass=20
      the control with ID IDC_EDIT, and connect it to the variable=20
      <CODE>m_wndEdit</CODE>.</P><PRE>LRESULT =
CMainDlg::OnInitDialog(...)
{
<SPAN class=3Dcpp-comment>// ...</SPAN>
    <SPAN class=3Dcpp-comment>// Attach CContainedWindows to OK and Exit =
buttons</SPAN>
    m_wndOKBtn.SubclassWindow ( GetDlgItem(IDOK) );
    m_wndExitBtn.SubclassWindow ( GetDlgItem(IDCANCEL) );
=20
    <SPAN class=3Dcpp-comment>// CButtonImpl: subclass the About =
button</SPAN>
    m_wndAboutBtn.SubclassWindow ( GetDlgItem(ID_APP_ABOUT) );
=20
    <B><SPAN class=3Dcpp-comment>// First DDX call, hooks up variables =
to controls.</B></SPAN>
    <B>DoDataExchange(<SPAN class=3Dcpp-keyword>false</SPAN>);</B>
=20
    <SPAN class=3Dcpp-keyword>return</SPAN> TRUE;
}</PRE>
      <P>The parameter to <CODE>DoDataExchange()</CODE> has the same =
meaning as=20
      the parameter to MFC's <CODE>UpdateData()</CODE> function. We'll =
cover=20
      that in more detail in the next section.</P>
      <P>If you run the ControlMania1 project, you can see all this =
subclassing=20
      in action. Right-clicking in the edit box will pop up the message =
box, and=20
      the cursor will change shape over the buttons as shown =
earlier.</P>
      <H2><A name=3Dmoreddx></A>More on DDX</H2>
      <P>DDX can, of course, actually do data exchange too. WTL supports =

      exchanging string data between an edit box and a string variable. =
It can=20
      also parse a string as a number, and transfer that data between an =
integer=20
      or floating-point variable. And it also supports transferring the =
state of=20
      a check box or group of radio buttons to/from an <CODE><SPAN=20
      class=3Dcpp-keyword>int</SPAN></CODE>.</P>
      <H3><A name=3Dddxmacros></A>DDX macros</H3>
      <P>There are six macros used in DDX. Each one expands to a=20
      <CODE>CWinDataExchange</CODE> method call that does the work. The =
macros=20
      all have the general form: <CODE>DDX_FOO(controlID, =
variable)</CODE>. Each=20
      macro takes a different type of variable, and some like=20
      <CODE>DDX_TEXT</CODE> are overloaded to accept many types.</P>
      <DL>
        <DT><CODE>DDX_TEXT</CODE>=20
        <DD>Transfers text data to/from an edit box. The variable can be =
a=20
        <CODE>CString</CODE>, <CODE>BSTR</CODE>, <CODE>CComBSTR</CODE>, =
or=20
        statically-allocated character array. Using an array allocated =
with=20
        <CODE><SPAN class=3Dcpp-keyword>new</SPAN></CODE> will not work. =

        <DT><CODE>DDX_INT</CODE>=20
        <DD>Transfers numerical data between an edit box and an =
<CODE><SPAN=20
        class=3Dcpp-keyword>int</SPAN></CODE>.=20
        <DT><CODE>DDX_UINT</CODE>=20
        <DD>Transfers numerical data between an edit box and an =
<CODE><SPAN=20
        class=3Dcpp-keyword>unsigned</SPAN> <SPAN=20
        class=3Dcpp-keyword>int</SPAN></CODE>.=20
        <DT><CODE>DDX_FLOAT</CODE>=20
        <DD>Transfers numerical data between an edit box and a =
<CODE><SPAN=20
        class=3Dcpp-keyword>float</SPAN></CODE> or <CODE><SPAN=20
        class=3Dcpp-keyword>double</SPAN></CODE>.=20
        <DT><CODE>DDX_CHECK</CODE>=20
        <DD>Transfers the state of a check box to/from an <CODE><SPAN=20
        class=3Dcpp-keyword>int</SPAN></CODE>.=20
        <DT><CODE>DDX_RADIO</CODE>=20
        <DD>Transfers the state of a group of radio buttons to/from an=20
        <CODE><SPAN class=3Dcpp-keyword>int</SPAN></CODE>. </DD></DL>
      <P>A note about using <CODE>DDX_FLOAT</CODE>: When you use this in =
your=20
      app, you need to add a #define to stdafx.h, before any WTL headers =
are=20
      included:</P><PRE><SPAN class=3Dcpp-preprocessor>#define =
_ATL_USE_DDX_FLOAT</SPAN></PRE>
      <P>This is necessary because by default, floating-point support is =

      disabled as a size optimization.</P>
      <H3><A name=3Dmoreddx></A>More about DoDataExchange()</H3>
      <P>You call the <CODE>DoDataExchange()</CODE> method just as you =
call=20
      <CODE>UpdateData()</CODE> in MFC. The prototype for=20
      <CODE>DoDataExchange()</CODE> is:</P><PRE>BOOL DoDataExchange ( =
BOOL bSaveAndValidate =3D FALSE,=20
                      UINT nCtlID =3D (UINT)-<SPAN =
class=3Dcpp-literal>1</SPAN> );</PRE>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -