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

📄 wtl for mfc programmers, part iv.mht

📁 大家知道wtl是window UI库
💻 MHT
📖 第 1 页 / 共 5 页
字号:
      you can use the MFC documentation whilst using the WTL wrappers. =
Failing=20
      that, the F12 key comes in handy when you need to jump to the =
definition=20
      of one of the classes.</P>
      <P>Here are the wrapper classes for built-in controls:</P>
      <UL>
        <LI>User controls: <CODE>CStatic</CODE>, <CODE>CButton</CODE>,=20
        <CODE>CListBox</CODE>, <CODE>CComboBox</CODE>, =
<CODE>CEdit</CODE>,=20
        <CODE>CScrollBar</CODE>, <CODE>CDragListBox</CODE>=20
        <LI>Common controls: <CODE>CImageList</CODE>, =
<CODE>CListViewCtrl</CODE>=20
        (<CODE>CListCtrl</CODE> in MFC), <CODE>CTreeViewCtrl</CODE>=20
        (<CODE>CTreeCtrl</CODE> in MFC), <CODE>CHeaderCtrl</CODE>,=20
        <CODE>CToolBarCtrl</CODE>, <CODE>CStatusBarCtrl</CODE>,=20
        <CODE>CTabCtrl</CODE>, <CODE>CToolTipCtrl</CODE>,=20
        <CODE>CTrackBarCtrl</CODE> (<CODE>CSliderCtrl</CODE> in MFC),=20
        <CODE>CUpDownCtrl</CODE> (<CODE>CSpinButtonCtrl</CODE> in MFC),=20
        <CODE>CProgressBarCtrl</CODE>, <CODE>CHotKeyCtrl</CODE>,=20
        <CODE>CAnimateCtrl</CODE>, <CODE>CRichEditCtrl</CODE>,=20
        <CODE>CReBarCtrl</CODE>, <CODE>CComboBoxEx</CODE>,=20
        <CODE>CDateTimePickerCtrl</CODE>, =
<CODE>CMonthCalendarCtrl</CODE>,=20
        <CODE>CIPAddressCtrl</CODE>=20
        <LI>Common control wrappers not in MFC: <CODE>CPagerCtrl</CODE>, =

        <CODE>CFlatScrollBar</CODE>, <CODE>CLinkCtrl</CODE> (clickable=20
        hyperlink, available on XP only) </LI></UL>
      <P>There are also a few WTL-specific classes: =
<CODE>CBitmapButton</CODE>,=20
      <CODE>CCheckListViewCtrl</CODE> (list view control with check =
boxes),=20
      <CODE>CTreeViewCtrlEx</CODE> and <CODE>CTreeItem</CODE> (used =
together,=20
      <CODE>CTreeItem</CODE> wraps an <CODE>HTREEITEM</CODE>),=20
      <CODE>CHyperLink</CODE> (clickable hyperlink, available on all =
OSes)</P>
      <P>One thing to note is that most of the wrapper classes are =
window=20
      interface classes, like <CODE>CWindow</CODE>. They wrap an=20
      <CODE>HWND</CODE> and provide wrappers around messages (for =
instance,=20
      <CODE>CListBox::GetCurSel()</CODE> wraps =
<CODE>LB_GETCURSEL</CODE>). So=20
      like <CODE>CWindow</CODE>, it is cheap to create a temporary =
control=20
      wrapper and attach it to an existing control. Also like=20
      <CODE>CWindow</CODE>, the control is not destroyed when the =
control=20
      wrapper is destructed. The exceptions are =
<CODE>CBitmapButton</CODE>,=20
      <CODE>CCheckListViewCtrl</CODE>, and <CODE>CHyperLink</CODE>.</P>
      <P>Since these articles are aimed at experienced MFC programmers, =
I won't=20
      be spending much time on the details of the wrapper classes that =
are=20
      similar to their MFC counterparts. I will, however, be covering =
the new=20
      classes in WTL; <CODE>CBitmapButton</CODE> is quite different from =
the MFC=20
      class of the same name, and <CODE>CHyperLink</CODE> is completely =
new.</P>
      <H2><A name=3Dappwizard></A>Creating a Dialog-Based App with the=20
      AppWizard</H2>
      <P>Fire up VC and start the WTL AppWizard. I'm sure you're as =
tired as I=20
      am with clock apps, so let's call our next app =
<I>ControlMania1</I>. On=20
      the first page of the AppWizard, click <I>Dialog Based</I>. We =
also have a=20
      choice between making a modal or modeless dialog. The difference =
is=20
      important and I will cover it in Part V, but for now let's go with =
the=20
      simpler one, modal. Check <I>Modal Dialog</I> and <I>Generate .CPP =

      Files</I> as shown here:</P>
      <P><IMG height=3D387 alt=3D" [AppWizard page 1 - 21K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC4/appwiz1.png" =
width=3D477=20
      align=3Dbottom border=3D0></P>
      <P>All the options on the second page are only meaningful when the =
main=20
      window is a frame window, so they are all disabled. Click =
<I>Finish</I>=20
      and then <I>OK</I> to complete the wizard.</P>
      <P>As you might expect, the AppWizard-generated code is much =
simpler for a=20
      dialog-based app. ControlMania1.cpp has the =
<CODE>_tWinMain()</CODE>=20
      function, here are the important parts:</P><PRE><SPAN =
class=3Dcpp-keyword>int</SPAN> WINAPI _tWinMain (=20
    HINSTANCE hInstance, HINSTANCE <SPAN =
class=3Dcpp-comment>/*hPrevInstance*/</SPAN>,=20
    LPTSTR lpstrCmdLine, <SPAN class=3Dcpp-keyword>int</SPAN> nCmdShow )
{
    HRESULT hRes =3D ::CoInitialize(NULL);
=20
    AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);
=20
    hRes =3D _Module.Init(NULL, hInstance);
=20
    <SPAN class=3Dcpp-keyword>int</SPAN> nRet =3D <SPAN =
class=3Dcpp-literal>0</SPAN>;
    <SPAN class=3Dcpp-comment>// BLOCK: Run application</SPAN>
    {
        CMainDlg dlgMain;
        nRet =3D dlgMain.DoModal();
    }
=20
    _Module.Term();
    ::CoUninitialize();
    <SPAN class=3Dcpp-keyword>return</SPAN> nRet;
}</PRE>
      <P>The code first initializes COM and creates a single-threaded =
apartment.=20
      This is necessary for dialogs that host ActiveX controls. Next, =
the code=20
      calls the WTL utility function =
<CODE>AtlInitCommonControls()</CODE>, which=20
      is a wrapper for <CODE>InitCommonControlsEx()</CODE>. The global=20
      <CODE>_Module</CODE> is initialized, and the main dialog is =
displayed.=20
      (Note that ATL dialogs created with <CODE>DoModal()</CODE> =
actually are=20
      modal, unlike MFC where all dialogs are modeless and MFC simulates =

      modality by manually disabling the dialog's parent.) Finally,=20
      <CODE>_Module</CODE> and COM are uninitialized, and the value =
returned by=20
      <CODE>DoModal()</CODE> is used as the app's exit code.</P>
      <BLOCKQUOTE>
        <P>The block around the <CODE>CMainDlg</CODE> variable is =
important=20
        because <CODE>CMainDlg</CODE> may have members that use ATL and =
WTL=20
        features. Those members may also use ATL/WTL features in their=20
        destructors. If the block were not present, the =
<CODE>CMainDlg</CODE>=20
        destructor (and the destructors of the members) would run after =
the call=20
        to <CODE>_Module.Term()</CODE> (which uninitializes ATL/WTL) and =
try to=20
        use ATL/WTL features, which could cause a hard-to-diagnose =
crash. (As a=20
        historical note, the WTL 3 AppWizard-generated code did not have =
a block=20
        there, and some of my apps did crash.)</P></BLOCKQUOTE>
      <P>You can build and run the app right away, although the dialog =
is pretty=20
      bare:</P>
      <P><IMG height=3D187 alt=3D" [Bare dialog - 4K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC4/bareapp.png" =
width=3D287=20
      align=3Dbottom border=3D0></P>
      <P>The code in <CODE>CMainDlg</CODE> handles =
<CODE>WM_INITDIALOG</CODE>,=20
      <CODE>WM_CLOSE</CODE>, and all three buttons. Take a quick glance =
through=20
      the code now if you like; you should be able to follow the=20
      <CODE>CMainDlg</CODE> declaration, its message map, and its =
message=20
      handlers.</P>
      <P>This sample project will demonstrate how to hook up variables =
to the=20
      controls. Here's the app with a couple more controls; you can =
refer back=20
      to this diagram for the following discussions.</P>
      <P><IMG height=3D227 alt=3D" [Add'l controls - 6K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC4/cm1ctrls.png" =
width=3D507=20
      align=3Dbottom border=3D0></P>
      <P>Since the app uses a list view control, the call to=20
      <CODE>AtlInitCommonControls()</CODE> will need to be changed. =
Change it=20
      to:</P><PRE>    AtlInitCommonControls ( ICC_WIN95_CLASSES );</PRE>
      <P>That registers more classes than necessary, but it saves us =
having to=20
      remember to add <CODE>ICC_*</CODE> constants when we add different =
types=20
      of controls to the dialog.</P>
      <H2><A name=3Dusingwrap></A>Using the Control Wrapper Classes</H2>
      <P>There are several ways to associate a member variable with a =
control.=20
      Some use plain <CODE>CWindow</CODE>s (or another window interface =
class,=20
      like <CODE>CListViewCtrl</CODE>), while others use a=20
      <CODE>CWindowImpl</CODE>-derived class. Using a =
<CODE>CWindow</CODE> is=20
      fine if you just need a temporary variable, while a=20
      <CODE>CWindowImpl</CODE> is required if you need to subclass a =
control and=20
      handle messages sent to it.</P>
      <H3><A name=3Datl1></A>ATL Way 1 - Attaching a CWindow</H3>
      <P>The simplest method is to declare a <CODE>CWindow</CODE> or =
other=20
      window interface class, and call its <CODE>Attach()</CODE> method. =
You can=20
      also use the <CODE>CWindow</CODE> constructor or assignment =
operator to=20
      associate the variable with a control's <CODE>HWND</CODE>.</P>
      <P>This code demonstrates all three methods of associating =
variables with=20
      the list control:</P><PRE>HWND hwndList =3D GetDlgItem(IDC_LIST);
CListViewCtrl wndList1 (hwndList);  <SPAN class=3Dcpp-comment>// use =
constructor</SPAN>
CListViewCtrl wndList2, wndList3;
=20
  wndList2.Attach ( hwndList );     <SPAN class=3Dcpp-comment>// use =
Attach method</SPAN>
  wndList3 =3D hwndList;              <SPAN class=3Dcpp-comment>// use =
assignment operator</SPAN></PRE>
      <P>Remember that the <CODE>CWindow</CODE> destructor does not =
destroy the=20
      window, so there is no need to detach the variables before they go =
out of=20
      scope. You can also use this technique with member variables if =
you wish -=20
      you can attach the variables in the <CODE>OnInitDialog()</CODE>=20
      handler.</P>
      <H3><A name=3Datl2></A>ATL Way 2 - CContainedWindow</H3>
      <P><CODE>CContainedWindow</CODE> is sort of halfway between using =
a=20
      <CODE>CWindow</CODE> and a <CODE>CWindowImpl</CODE>. It lets you =
subclass=20
      a control, then handle that control's messages <I>in the control's =
parent=20
      window</I>. This lets you put all the message handlers in the =
dialog=20
      class, and you don't have to write separate =
<CODE>CWindowImpl</CODE>=20
      classes for each control. Note that you don't use=20
      <CODE>CContainedWindow</CODE> to handle <CODE>WM_COMMAND</CODE>,=20
      <CODE>WM_NOTIFY</CODE>, or other notification messages, because =
those are=20
      always sent to the control's parent.</P>
      <P>The actual class, <CODE>CContainedWindowT</CODE>, is a template =
class=20
      that takes a window interface class name as its template =
parameter. There=20
      is a specialization <CODE>CContainedWindowT&lt;CWindow&gt;</CODE> =
that=20
      works like a plain <CODE>CWindow</CODE>; this is typedef'ed to the =
shorter=20
      name <CODE>CContainedWindow</CODE>. To use a different window =
interface=20
      class, specify its name as the template parameter, for example=20
      <CODE>CContainedWindowT&lt;CListViewCtrl&gt;</CODE>.</P>
      <P>To hook up a <CODE>CContainedWindow</CODE>, you do four =
things:</P>
      <OL>
        <LI>Create a <CODE>CContainedWindowT</CODE> member variable in =
the=20
        dialog.=20
        <LI>Put handlers in an <CODE>ALT_MSG_MAP</CODE> section of the =
dialog's=20
        message map=20
        <LI>In the dialog's constructor, call the =
<CODE>CContainedWindowT</CODE>=20
        constructor and tell it which <CODE>ALT_MSG_MAP</CODE> section =
it should=20
        route messages to.=20
        <LI>In <CODE>OnInitDialog()</CODE>, call the=20
        <CODE>CContainedWindowT::SubclassWindow()</CODE> method to =
associate a=20
        variable with a control. </LI></OL>
      <P>In ControlMania1, we'll use a <CODE>CContainedWindow</CODE> for =
each of=20
      the three buttons. The dialog will handle =
<CODE>WM_SETCURSOR</CODE>=20
      messages sent to each button, and change the cursor.</P>
      <P>Let's go through the steps. First, we add =
<CODE>CContainedWindow</CODE>=20
      members in <CODE>CMainDlg.</CODE></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;
};</PRE>
      <P>Second, we add <CODE>ALT_MSG_MAP</CODE> sections. The <I>OK</I> =
button=20
      will use section 1, while the <I>Exit</I> button will use section =
2. This=20
      means that all messages sent to the <I>OK</I> button will be =
routed to the=20
      <CODE>ALT_MSG_MAP(<SPAN class=3Dcpp-literal>1</SPAN>)</CODE> =
section, and=20
      all messages sent to the <I>Exit</I> button will be routed to the=20
      <CODE>ALT_MSG_MAP(<SPAN class=3Dcpp-literal>2</SPAN>)</CODE> =
section.</P><PRE><SPAN class=3Dcpp-keyword>class</SPAN> CMainDlg : <SPAN =
class=3Dcpp-keyword>public</SPAN> CDialogImpl&lt;CMainDlg&gt;
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
    BEGIN_MSG_MAP_EX(CMainDlg)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
        COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
        COMMAND_ID_HANDLER(IDOK, OnOK)
        COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
    <B>ALT_MSG_MAP(<SPAN class=3Dcpp-literal>1</SPAN>)
        MSG_WM_SETCURSOR(OnSetCursor_OK)
    ALT_MSG_MAP(<SPAN class=3Dcpp-literal>2</SPAN>)
        MSG_WM_SETCURSOR(OnSetCursor_Exit)</B>
    END_MSG_MAP()
=20
    <B>LRESULT OnSetCursor_OK(HWND hwndCtrl, UINT uHitTest, UINT =
uMouseMsg);
    LRESULT OnSetCursor_Exit(HWND hwndCtrl, UINT uHitTest, UINT =
uMouseMsg);</B>
};</PRE>
      <P>Third, we call the <CODE>CContainedWindow</CODE> constructor =
for each=20
      member and tell it which <CODE>ALT_MSG_MAP</CODE> section to =

⌨️ 快捷键说明

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