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

📄 ch09.htm

📁 Learning language of Visual C++6
💻 HTM
📖 第 1 页 / 共 3 页
字号:
</PRE>
<P>Next, you add the handler to the source message map to associate the command ID
with the handler. Open any CMainFrame function and scroll upwards until you find
the message map; then edit it so that it looks like Listing 9.6.</P>
<P>
<H4>Listing 9.6&#160;&#160;MainFrm.cpp--Message Map</H4>
<PRE>BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
        // NOTE - the ClassWizard will add and remove mapping macros here.
        //    DO NOT EDIT what you see in these blocks of generated code !
    ON_WM_CREATE()
    //}}AFX_MSG_MAP
    ON_UPDATE_COMMAND_UI(ID_MYNEWPANE, OnUpdateMyNewPane)
</PRE>
<PRE>END_MESSAGE_MAP()
</PRE>
<P>You have now arranged for the CMainFrame member function OnUpdateMyNewPane() to
be called whenever the status bar pane ID_MYNEWPANE needs to be updated.</P>
<P>Now you're ready to write the new command-update handler. In the handler, you
will enable the new pane and set its contents. Listing 9.7 shows the command-update
handler for the new pane; add this code to mainfrm.cpp. As you can see, it uses a
member variable called m_paneString. Update handlers should be very quick--the job
of making sure that m_paneString holds the right string should be tackled in a function
that is called less often.</P>


<BLOCKQUOTE>
	<P>
<HR>
<strong>TIP:</strong> Command update handlers are discussed in Chapter 3, &quot;Messages
	and Commands,&quot; in the &quot;Understanding Command Updates&quot; section. They
	have to be quick because the system calls them whenever it refreshes the display.
	
<HR>


</BLOCKQUOTE>

<H4>Listing 9.7&#160;&#160;CMainFrame::OnUpdateMyNewPane()</H4>
<PRE>void CMainFrame::OnUpdateMyNewPane(CCmdUI *pCmdUI) 
{
    pCmdUI-&gt;Enable(); 
    pCmdUI-&gt;SetText(m_paneString); 
</PRE>
<PRE>}
</PRE>
<H3><A NAME="Heading10"></A>Setting the Status Bar's Appearance</H3>
<P>To add the last touch to your status bar demonstration application, you will want
a way to set m_paneString. To initialize it, double-click on the CMainFrame constructor
to edit it, and add this line:</P>
<P>
<PRE><B>    m_paneString = &quot;Default string&quot;;</B>
</PRE>
<P>The value you entered in the string table is only to assure Visual Studio that
the resource ID you created is in use. Right-click CMainFrame in ClassView and choose
Add Member Variable to add m_paneString as a private member variable. The type should
be CString.</P>
<P>To set up the status bar for the first time, add these lines to CMainFrame::OnCreate(),
just before the return statement:</P>
<P>
<PRE><B>     CClientDC dc(this);</B>
<B>     SIZE size = dc.GetTextExtent(m_paneString);</B>
<B>     int index = m_wndStatusBar.CommandToIndex(ID_MYNEWPANE);</B>
<B>     m_wndStatusBar.SetPaneInfo(index,ID_MYNEWPANE, SBPS_POPOUT, size.cx);</B>
</PRE>
<P>These lines set the text string and the size of the pane. You set the size of
the pane with a call to SetPaneInfo(), which needs the index of the pane and the
new size. CommandToIndex() obtains the index of the pane, and GetTextExtent() obtains
the size. As a nice touch, the call to SetPaneInfo() uses the SBPS_POPOUT style to
create a pane that seems to stick out from the status bar, rather than be indented.</P>
<P>The user will change the string by making a menu selection. Open the IDR_STATUSTYPE
menu in the resource editor and add a Change String item to the File menu. (Working
with menus is discussed for the first time in Chapter 8.) Let Developer Studio assign
it the resource ID ID_FILE_CHANGESTRING.</P>
<P>Open ClassWizard and add a handler for this command; it should be caught by CMainFrame
because that's where the m_paneString variable is kept. ClassWizard offers to call
the handler OnFileChangestring(), and you should accept this name. Click OK twice
to close ClassWizard.</P>
<P>Insert a new dialog box into the application and call it <B>IDD_PANEDLG</B>. The
title should be <B>Change Pane String</B>. Add a single edit box, stretched the full
width of the dialog box, and leave the ID as IDC_EDIT1. Add a static text item just
above the edit box with the caption <B>New String:</B>. With the dialog box open
in the resource editor, open ClassWizard. Create a new class for the dialog box called
CPaneDlg, and associate the edit control, IDC_EDIT1, with a CString member variable
of the dialog class called m_paneString.</P>


<BLOCKQUOTE>
	<P>
<HR>
<strong>TIP:</strong> Adding dialog boxes to applications and associating them with classes
	are discussed in more depth in several earlier chapters, including Chapters 2 and
	8. 
<HR>


</BLOCKQUOTE>

<P>Switch to ClassView, expand CMainFrame, and double-click OnFileChangeString()
to edit it. Add the code shown in Listing 9.8.</P>
<P>
<H4>Listing 9.8&#160;&#160;CMainFrame::OnFileChangestring()</H4>
<PRE>void CMainFrame::OnFileChangestring() 
{
    CPaneDlg dialog(this);
    dialog.m_paneString = m_paneString;
    int result = dialog.DoModal();
    if (result == IDOK)
    {
        m_paneString = dialog.m_paneString;
        CClientDC dc(this);
        SIZE size = dc.GetTextExtent(m_paneString);
        int index = m_wndStatusBar.CommandToIndex(ID_MYNEWPANE);
        m_wndStatusBar.SetPaneInfo(index,
            ID_MYNEWPANE, SBPS_POPOUT, size.cx);
    }
</PRE>
<PRE>}
</PRE>
<P>This code displays the dialog box, and, if the user exits the dialog box by clicking
OK, changes the text string and resets the size of the pane. The code is very similar
to the lines you added to OnCreate(). Scroll up to the top of MainFrm.cpp and add
this line:</P>
<P>
<PRE>#include &quot;panedlg.h&quot;
</PRE>
<P>This tells the compiler what the CPaneDlg class is. Build and run the Status application,
and you should see the window shown in Figure 9.16. As you can see, the status bar
contains an extra panel displaying the text Default string. If you choose File, Change
String, a dialog box appears into which you can type a new string for the panel.
When you exit the dialog box via the OK button, the text appears in the new panel,
and the panel resizes itself to accommodate the new string (see Figure 9.17).</P>
<P><A HREF="javascript:popUp('09uvc16.gif')"><B>FIG. 9.16</B></A><B> </B><I>The Status
Bar Demo application shows how to add and manage a status bar panel.</I></P>
<P>
<H2><A NAME="Heading11"></A>Working with Rebars</H2>
<P>Rebars are toolbars that contain controls other than toolbar buttons. It was possible
to add other controls to normal toolbars in the past, but difficult. With rebars,
it's simple.</P>
<P>Start by using AppWizard to make a project call ReBar. Accept all the defaults
on each step, or click Finish on step 1 to speed the process a little. When the project
is generated, double-click CMainFrame in ClassView to edit the header file. This
frame holds the open documents and is where a classic toolbar goes. The rebar for
this sample will go here, too. Add the rebar as a public member variable:</P>
<P>
<PRE>CReBar m_rebar;
</PRE>
<P><A HREF="javascript:popUp('09uvc17.gif')"><B>FIG. 9.17</B></A><B> </B><I>The panel
resizes itself to fit the new string.</I></P>
<P>In this sample application, you will add a check box to the bar--you can add any
kind of control at all. A check box, a radio button, and a command button (like the
OK or Cancel button on a dialog) are all represented by the CButton class, with slightly
different styles. Add the check box to the header file right after the rebar, like
this:</P>
<P>
<PRE>CButton m_check;
</PRE>
<P>You saw in the previous section that an application's toolbar is created and initialized
in the OnCreate() function of the mainframe class. The same is true for rebars. Expand
CMainFrame in ClassView, and double-click OnCreate() to edit it. Add these lines
just before the final return statement:</P>
<P>
<PRE>   if (!m_rebar.Create(this) )
   {
      TRACE0(&quot;Failed to create rebar\n&quot;);
      return -1;      // fail to create
   }
</PRE>
<P>The check box control will need a resource ID. When you create a control with
the dialog editor, the name you give the control is automatically associated with
a number. This control will be created in code, so you will have to specify the resource
ID yourself, as you did for the new pane in the status bar earlier in this chapter.
Choose View, Resource Symbols and click the New button. Type the name <B>IDC_CHECK</B>
and accept the number suggested. This adds a line to resource.h, defining IDC_CHECK,
and assures you that other controls will not reuse this resource ID.</P>
<P>Back in CMainFrame::OnCreate(), add these lines to create the check box (note
the styles carefully):</P>
<P>
<PRE>   if (!m_check.Create(&quot;Check Here&quot;, 
         WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
         CRect(0,0,20,20), this, IDC_CHECK)  )
   {
      TRACE0(&quot;Failed to create checkbox\n&quot;);
      return -1;      // fail to create
   }
</PRE>
<P>Finally, add this line to add a band containing the check box control to the rebar:</P>
<P>
<PRE>   m_rebar.AddBar(&amp;m_check, &quot;On The Bar&quot;, NULL, 
                   RBBS_BREAK | RBBS_GRIPPERALWAYS);
</PRE>
<P>AddBar() takes four parameters: a pointer to the control that will be added, some
text to put next to it, a pointer to a bitmap to use for the background image on
the rebar, and a rebar style, made by combining any of these style flags:</P>

<UL>
	<LI>RBBS_BREAK puts the band on a new line, even if there's room for it at the end
	of an existing line.
	<P>
	<LI>RBBS_CHILDEDGE puts the band against a child window of the frame.
	<P>
	<LI>RBBS_FIXEDBMP prevents moving the bitmap if the band is resized by the user.
	<P>
	<LI>RBBS_FIXEDSIZE prevents the user from resizing the band.
	<P>
	<LI>RBBS_GRIPPERALWAYS guarantees sizing wrinkles are present.
	<P>
	<LI>RBBS_HIDDEN hides the band.
	<P>
	<LI>RBBS_NOGRIPPER suppresses sizing wrinkles.
	<P>
	<LI>RBBS_NOVERT hides the band when the rebar is vertical.
	<P>
	<LI>RBBS_VARIABLEHEIGHT enables the band to be resized by the rebar.
</UL>

<P>At this point, you can build the project and run it. You should see your rebar,
as in Figure 9.18. The check box works in that you can select and deselect it, but
nothing happens when you do.</P>
<P><A HREF="javascript:popUp('09uvc18.gif')"><B>FIG. 9.18</B></A><B> </B><I>The rebar
contains a check box.</I></P>
<P>To react when the user clicks the button, you need to catch the message and do
something based on the message. The simplest thing to do is change what is drawn
in the view's OnDraw(), so the view should catch the message. Double click CRebarView
in ClassView to edit the header file, and scroll to the message map. Between the
closing AFX_MSG and the DECLARE_MESSAGE_MAP, add this line:</P>
<P>
<PRE>afx_msg void OnClick();
</PRE>
<P>Expand CRebarView in ClassView and double-click OnDraw(), which you will edit
in a moment. After it, add this function:</P>
<P>
<PRE>void CRebarView::OnClick()
{
   Invalidate();
}
</PRE>
<P>This causes the view to redraw whenever the user selects or deselects the check
box. Scroll up in the file until you find the message map, and add (after the three
entries related to printing) this line:</P>
<P>
<PRE>   ON_BN_CLICKED(IDC_CHECK, OnClick)
</PRE>
<P>At the top of the file, after the other include statements, add this one:</P>
<P>
<PRE>#include &quot;mainFrm.h&quot;
</PRE>
<P>Now add these lines to OnDraw() in place of the TODO comment:</P>
<P>
<PRE>   CString message;
   if ( ((CMainFrame*)(AfxGetApp()-&gt;m_pMainWnd))-&gt;m_check.GetCheck())
      message = &quot;The box is checked&quot;;
   else
      message = &quot;The box is not checked&quot;;
   pDC-&gt;TextOut(20,20,message);
</PRE>
<P>The if statement obtains a pointer to the main window, casts it to a CMainFrame*,
and asks the check box whether it is selected. Then the message is set appropriately.</P>
<P>Build the project and run it. As you select and deselect the check box, you should
see the message change, as in Figure 9.19.</P>
<P><A HREF="javascript:popUp('09uvc19.gif')"><B>FIG. 9.19</B></A><B> </B><I>Clicking
the check box changes the view.</I></P>
<H1><I></I></H1>
<CENTER>
<P>
<HR>
<A HREF="../ch08/ch08.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch10/ch10.htm"><IMG
SRC="../button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"
BORDER="0"></A><A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> <BR>
</P>

<P>&#169; <A HREF="../copy.htm">Copyright</A>, Macmillan Computer Publishing. All
rights reserved.
</CENTER>


</BODY>

</HTML>

⌨️ 快捷键说明

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