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

📄 wtl for mfc programmers, part vii.mht

📁 大家知道wtl是window UI库
💻 MHT
📖 第 1 页 / 共 5 页
字号:
        Close button from the header.=20
        <LI><CODE>PANECNT_VERTICAL</CODE>: Set this style to make the =
header=20
        area vertical, along the left side of the container window. =
</LI></UL>
      <P>The default value of the extended styles is 0, meaning a =
horizontal=20
      container with a close button.</P><PRE>HWND SetClient(HWND =
hWndClient)
HWND GetClient()</PRE>
      <P>Call <CODE>SetClient()</CODE> to assign a child window to the =
pane=20
      container. This works similarly to the =
<CODE>SetSplitterPane()</CODE>=20
      method in <CODE>CSplitterWindow</CODE>. <CODE>SetClient()</CODE> =
returns=20
      the <CODE>HWND</CODE> of the old client window. Call=20
      <CODE>GetClient()</CODE> to get the <CODE>HWND</CODE> of the =
current=20
      client window.</P><PRE>BOOL SetTitle(LPCTSTR lpstrTitle)
BOOL GetTitle(LPTSTR lpstrTitle, <SPAN class=3Dcpp-keyword>int</SPAN> =
cchLength)
<SPAN class=3Dcpp-keyword>int</SPAN> GetTitleLength()</PRE>
      <P>Call <CODE>SetTitle()</CODE> to change the text shown in the =
header=20
      area of the container. Call <CODE>GetTitle()</CODE> to retrieve =
the=20
      current header text, and call <CODE>GetTitleLength()</CODE> to get =
the=20
      length in characters of the current header text (not including the =
null=20
      terminator).</P><PRE>BOOL EnableCloseButton(BOOL bEnable)</PRE>
      <P>If the pane container has a Close button, you can use=20
      <CODE>EnableCloseButton()</CODE> to enable and disable it.</P>
      <H3><A name=3Dpcinsplitter></A>Using a pane container in a =
splitter=20
      window</H3>
      <P>To demonstrate how to add a pane container to an existing =
splitter,=20
      we'll add a container to the left pane of the ClipSpy splitter. =
Instead of=20
      assigning the list control to the left pane, we assign the pane =
container.=20
      The list is then assigned to the pane container. Here are the =
lines in=20
      <CODE>CMainFrame::OnCreate()</CODE> to change to set up the pane=20
      container.</P><PRE>LRESULT CMainFrame::OnCreate ( LPCREATESTRUCT =
lpcs )
{
<SPAN class=3Dcpp-comment>//...</SPAN>
    m_wndVertSplit.Create ( *<SPAN class=3Dcpp-keyword>this</SPAN>, =
rcDefault, NULL, dwSplitStyle, dwSplitExStyle );
=20
    <B><SPAN class=3Dcpp-comment>// Create the pane container.</SPAN>
    m_wndPaneContainer.Create ( m_wndVertSplit, IDS_LIST_HEADER );
=20
    <SPAN class=3Dcpp-comment>// Create the left pane (list of clip =
formats)</SPAN>
    m_wndFormatList.Create ( m_wndPaneContainer, rcDefault );
</B><SPAN class=3Dcpp-comment>//...<B></SPAN>
</B>    <B><SPAN class=3Dcpp-comment>// Set up the splitter panes</SPAN>
    m_wndPaneContainer.SetClient ( m_wndFormatList );
    m_wndVertSplit.SetSplitterPanes ( m_wndPaneContainer, =
m_wndDataViewer );</B></PRE>
      <P>Notice that the parent of the list control is=20
      <CODE>m_wndPaneContainer</CODE>. Also, =
<CODE>m_wndPaneContainer</CODE> is=20
      set as the left pane of the splitter.</P>
      <P>Here's what the modified left pane looks like. I've also =
changed the=20
      border styles a bit, since the pane container draws its own 3D =
border=20
      around the header area. This doesn't look perfect, so you =
sometimes may=20
      have to experiment with the border styles until you get the exact =
look you=20
      want. (Then of course, you need to re-test on XP where themes make =
it even=20
      more "interesting" to get the right look.)</P>
      <P><IMG height=3D280 alt=3D" [Pane container - 5K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC7/panecont.png" =
width=3D356=20
      align=3Dbottom border=3D0></P>
      <H3><A name=3Dpcclosebtn></A>The Close button and message =
handling</H3>
      <P>When the user clicks the Close button, the pane container sends =
a=20
      <CODE>WM_COMMAND</CODE> message to its parent, with a command ID =
of=20
      <CODE>ID_PANE_CLOSE</CODE>. When you use the pane container in a =
splitter,=20
      the usual course of action is to call =
<CODE>SetSinglePaneMode()</CODE> to=20
      hide the splitter pane that has the pane container. (But remember =
to=20
      provide a way for the user to show the pane again!)</P>
      <P>The <CODE>CPaneContainer</CODE> message map also has the=20
      <CODE>FORWARD_NOTIFICATIONS()</CODE> macro, just like=20
      <CODE>CSplitterWindow</CODE>, so the container passes notification =

      messages from its client window to its parent. In the case of =
ClipSpy,=20
      there are two windows between the list control and the main frame =
(the=20
      pane container and the splitter), but the=20
      <CODE>FORWARD_NOTIFICATIONS()</CODE> macros ensure that all =
notifications=20
      from the list arrive at the main frame.</P>
      <H2><A name=3Dadvancedsplitter></A>Advanced Splitter Features</H2>
      <P>In this section, I'll describe how to do some common advanced =
UI tricks=20
      with WTL splitters.</P>
      <H3><A name=3Dnested></A>Nested splitters</H3>
      <P>If you plan on writing an email client, you'll probably end up =
using=20
      nested splitters, one horizontal and one vertical. This is easy to =
do with=20
      WTL splitters - you create one splitter as the child of the =
other.</P>
      <P>To show this in action, we'll add a horizontal splitter to =
ClipSpy.=20
      After adding a <CODE>CHorSplitterWindow</CODE> member called=20
      <CODE>m_wndHorzSplitter</CODE>, we first create that splitter the =
same way=20
      as we create <CODE>m_wndVertSplitter</CODE>. To make=20
      <CODE>m_wndHorzSplitter</CODE> the topmost splitter.=20
      <CODE>m_wndVertSplitter</CODE> is now created as a child of=20
      <CODE>m_wndHorzSplitter</CODE>. Finally, <CODE>m_hWndClient</CODE> =
is set=20
      to <CODE>m_wndHorzSplitter</CODE>, since that's the window that =
now=20
      occupies the main frame's client area.</P><PRE>LRESULT =
CMainFrame::OnCreate()
{
<SPAN class=3Dcpp-comment>//...</SPAN>
    <SPAN class=3Dcpp-comment>// Create the splitter windows.</SPAN>
    <B>m_wndHorzSplit.Create ( *<SPAN class=3Dcpp-keyword>this</SPAN>, =
rcDefault, NULL,=20
                           dwSplitStyle, dwSplitExStyle );
=20
    m_wndVertSplit.Create ( m_wndHorzSplit, rcDefault, NULL,=20
                           dwSplitStyle, dwSplitExStyle );</B>
<SPAN class=3Dcpp-comment>//...</SPAN>
<B>    <SPAN class=3Dcpp-comment>// Set the horizontal splitter as the =
client area window.</SPAN>
    m_hWndClient =3D m_wndHorzSplit;

    <SPAN class=3Dcpp-comment>// Set up the splitter panes</SPAN>
    m_wndPaneContainer.SetClient ( m_wndFormatList );
    m_wndHorzSplit.SetSplitterPane ( SPLIT_PANE_TOP, m_wndVertSplit );
    m_wndVertSplit.SetSplitterPanes ( m_wndPaneContainer, =
m_wndDataViewer );
</B><SPAN class=3Dcpp-comment>//...</SPAN>
}</PRE>
      <P>And here's what the result looks like:</P>
      <P><IMG height=3D323 alt=3D" [Horz splitter w/empty pane - 5K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC7/emptyhsplit.png" =
width=3D388=20
      align=3Dbottom border=3D0></P>
      <H3><A name=3Daxinpane></A>Using ActiveX controls in a pane</H3>
      <P>Hosting an ActiveX control in a splitter pane is similar to =
hosting a=20
      control in a dialog. You create the control at runtime using=20
      <CODE>CAxWindow</CODE> methods, then assign the =
<CODE>CAxWindow</CODE> to=20
      a pane in the splitter. Here's how you would add a browser control =
to the=20
      bottom pane of the horizontal splitter:</P><PRE>    <B><SPAN =
class=3Dcpp-comment>// Create the bottom pane (browser)</SPAN>
CAxWindow wndIE;
<SPAN class=3Dcpp-keyword>const</SPAN> DWORD dwIEStyle =3D WS_CHILD | =
WS_VISIBLE | WS_CLIPCHILDREN |
                        WS_HSCROLL | WS_VSCROLL;

    wndIE.Create ( m_wndHorzSplit, rcDefault,=20
                  _T(<SPAN =
class=3Dcpp-string>"http://www.codeproject.com"</SPAN>), dwIEStyle );
</B>
    <SPAN class=3Dcpp-comment>// Set the horizontal splitter as the =
client area window.</SPAN>
    m_hWndClient =3D m_wndHorzSplit;

    <SPAN class=3Dcpp-comment>// Set up the splitter panes</SPAN>
    m_wndPaneContainer.SetClient ( m_wndFormatList );
    <B>m_wndHorzSplit.SetSplitterPanes ( m_wndVertSplit, wndIE );
</B>    m_wndVertSplit.SetSplitterPanes ( m_wndPaneContainer, =
m_wndDataViewer );</PRE>
      <H3><A name=3Dspecialdraw></A>Special drawing</H3>
      <P>If you want to provide a different appearance for the splitter =
bar, for=20
      example to draw a texture on it, you can derive a class from=20
      <CODE>CSplitterWindowImpl</CODE> and override=20
      <CODE>DrawSplitterBar()</CODE>. If you just want to tweak the =
appearance,=20
      you can copy the existing function in =
<CODE>CSplitterWindowImpl</CODE> and=20
      make any little changes you want. Here's an example that paints a =
diagonal=20
      hatch pattern in the bar.</P><PRE><SPAN =
class=3Dcpp-keyword>template</SPAN> &lt;<SPAN =
class=3Dcpp-keyword>bool</SPAN> t_bVertical =3D <SPAN =
class=3Dcpp-keyword>true</SPAN>&gt;
<SPAN class=3Dcpp-keyword>class</SPAN> CMySplitterWindowT :=20
    <SPAN class=3Dcpp-keyword>public</SPAN> =
CSplitterWindowImpl&lt;CMySplitterWindowT&lt;t_bVertical&gt;, =
t_bVertical&gt;
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
    DECLARE_WND_CLASS_EX(_T(<SPAN =
class=3Dcpp-string>"My_SplitterWindow"</SPAN>),=20
                         CS_DBLCLKS, COLOR_WINDOW)
=20
    <SPAN class=3Dcpp-comment>// Overrideables</SPAN>
    <SPAN class=3Dcpp-keyword>void</SPAN> DrawSplitterBar(CDCHandle dc)
    {
    RECT rect;
=20
        <SPAN class=3Dcpp-keyword>if</SPAN> ( m_br.IsNull() )
            m_br.CreateHatchBrush ( HS_DIAGCROSS,=20
                                    t_bVertical ? RGB(<SPAN =
class=3Dcpp-literal>255</SPAN>,<SPAN class=3Dcpp-literal>0</SPAN>,<SPAN =
class=3Dcpp-literal>0</SPAN>)=20
                                                : RGB(<SPAN =
class=3Dcpp-literal>0</SPAN>,<SPAN class=3Dcpp-literal>0</SPAN>,<SPAN =
class=3Dcpp-literal>255</SPAN>) );
=20
        <SPAN class=3Dcpp-keyword>if</SPAN> ( GetSplitterBarRect ( =
&amp;rect ) )
        {
            dc.FillRect ( &amp;rect, m_br );
=20
            <SPAN class=3Dcpp-comment>// draw 3D edge if needed</SPAN>
            <SPAN class=3Dcpp-keyword>if</SPAN> ( (GetExStyle() &amp; =
WS_EX_CLIENTEDGE) !=3D <SPAN class=3Dcpp-literal>0</SPAN>)
                dc.DrawEdge(&amp;rect, EDGE_RAISED,=20
                            t_bVertical ? (BF_LEFT | BF_RIGHT)=20
                                        : (BF_TOP | BF_BOTTOM));
        }
    }
=20
<SPAN class=3Dcpp-keyword>protected</SPAN>:
    CBrush m_br;
};
=20
<SPAN class=3Dcpp-keyword>typedef</SPAN> CMySplitterWindowT&lt;<SPAN =
class=3Dcpp-keyword>true</SPAN>&gt;    CMySplitterWindow;
<SPAN class=3Dcpp-keyword>typedef</SPAN> CMySplitterWindowT&lt;<SPAN =
class=3Dcpp-keyword>false</SPAN>&gt;   CMyHorSplitterWindow;</PRE>
      <P>Here's the result (with the bars made wider so the effect is =
easier to=20
      see):</P>
      <P><IMG height=3D349 alt=3D" [custom drawn bars - 14K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC7/custombars.png" =
width=3D413=20
      align=3Dbottom border=3D0></P>
      <H2><A name=3Dpcoverrides></A>Special Drawing in Pane =
Containers</H2>
      <P><CODE>CPaneContainer</CODE> has a few methods that you can =
override to=20
      change the appearance of a pane container. You can derive a new =
class from=20
      <CODE>CPaneContainerImpl</CODE> and override the methods you want, =
for=20
      example:</P><PRE><SPAN class=3Dcpp-keyword>class</SPAN> =
CMyPaneContainer :
    <SPAN class=3Dcpp-keyword>public</SPAN> =
CPaneContainerImpl&lt;CMyPaneContainer&gt;
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
    DECLARE_WND_CLASS_EX(_T(<SPAN =
class=3Dcpp-string>"My_PaneContainer"</SPAN>), <SPAN =
class=3Dcpp-literal>0</SPAN>, -<SPAN class=3Dcpp-literal>1</SPAN>)
<SPAN class=3Dcpp-comment>//... overrides here ...</SPAN>
};</PRE>
      <P>Some of the more interesting methods are:</P><PRE><SPAN =
class=3Dcpp-keyword>void</SPAN> CalcSize()</PRE>
      <P>The purpose of <CODE>CalcSize()</CODE> is simply to set=20
      <CODE>m_cxyHeader</CODE>, which controls the width or height of =
the=20
      container's header area. There is a bug in=20
      <CODE>SetPaneContainerExtendedStyle()</CODE>, however, that =
results in a=20
      derived class's <CODE>CalcSize()</CODE> not being called when the =
pane is=20
      switched between horizontal and vertical modes. You can change the =

      <CODE>CalcSize()</CODE> call to <CODE>pT-&gt;CalcSize()</CODE> to =
fix=20
      this.</P><PRE>HFONT GetTitleFont()</PRE>
      <P>This method returns an <CODE>HFONT</CODE>, which will be used =
to draw=20
      the header text. The default is the value returned by=20
      <CODE>GetStockObject(DEFAULT_GUI_FONT)</CODE>, which is MS Sans =
Serif. If=20
      you want to use the more modern-looking Tahoma, you can override=20
      <CODE>GetTitleFont()</CODE> and return a handle to a Tahoma font =
that you=20
      create.</P><PRE>BOOL GetToolTipText(LPNMHDR lpnmh)</PRE>
      <P>Override this method to provide tooltip text when the cursor =
hovers=20
      over the Close button. This method is actually a handler for=20
      <CODE>TTN_GETDISPINFO</CODE>, so you cast <CODE>lpnmh</CODE> to a=20
      <CODE>NMTTDISPINFO*</CODE> and set the members of that struct =
accordingly.=20
      Keep 

⌨️ 快捷键说明

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