📄 ch10.htm
字号:
<P><A ID="I9" NAME="I9"><B>Creating a New Command ID</B></A></P>
<P>This step is easy, thanks to Visual C++'s symbol browser. To add the command ID, start by choosing <U>V</U>iew, Resource S<U>y</U>mbols. When you do, you see the Resource Symbols dialog box (see Figure 10.12), which displays the currently defined
symbols for your application's resources. Click the <U>N</U>ew button, and the New Symbol dialog box appears. Type the new ID, <B>ID_MYNEWPANE</B>, into the <U>N</U>ame box (see Figure 10.13). Usually, you can just accept the value that MFC suggests for
the ID.</P>
<A HREF="Lfigs12.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch10/Lfigs12.gif"><b>Fig. 10.12</b></A>
<P><I>Use the Resource Symbols dialog box to add new command IDs to your application.</I></P>
<A HREF="Lfigs13.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch10/Lfigs13.gif"><b>Fig. 10.13</b></A>
<P><I>Type the new IDs name and value into the New Symbol dialog box.</I></P>
<P>Click the OK and Close buttons to finalize your selections, and your new command ID is defined.</P>
<P><A ID="I10" NAME="I10"><B>Creating the Default String</B></A></P>
<P>You have now defined a resource ID, but it is not being used. To represent a status bar pane, the ID must have a default string defined for it. To define the string, first go to the ResourceView window (by clicking the ResourceView tab) and
double-click the String Table resource to open it in the string table editor, as shown in Figure 10.14.</P>
<A HREF="Lfigs14.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch10/Lfigs14.gif"><b>Fig. 10.14</b></A>
<P><I>Define the new pane's default string in the string table.</I></P>
<P>Now, choose <U>I</U>nsert, Ne<U>w</U> String to bring up the String Properties dialog box. Type the new pane's command ID into the <U>I</U>D box (or choose it from the drop-down list) and the default string (<B>Default string</B> in this case) into the
<U>C</U>aption box (see Figure 10.15).</P>
<A HREF="Lfigs15.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch10/Lfigs15.gif"><b>Fig. 10.15</b></A>
<P><I>Use the String Properties dialog box to define the new pane's default string.</I></P>
<P><A ID="I11" NAME="I11"><B>Adding the ID to the Indicators Array</B></A></P>
<P>When MFC constructs your status bar, it uses an array of IDs to determine which panes to display and where to display them. This array of IDs is passed as an argument to the status bar's <font color="#008000">SetIndicators()</font> member function,
which is called in the <font color="#008000">CMainFrame</font> class's <font color="#008000">OnCreate()</font> function. You find this array of IDs, shown in Listing 10.3, near the top of the MainFrm.cpp file. One way to reach these lines in the source
code editor is to switch to ClassView, expand <font color="#008000">CMainFrame</font>, double-click <font color="#008000">OnCreate()</font>, and scroll up one page. Alternatively, you could use FileView to open MainFrm.cpp and scroll down to this code.</P>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P><I>Listing 10.3—MainFrm.cpp—The Indicator Array</I></P>
<pre><font color="#008000">static UINT indicators[] =</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> ID_SEPARATOR, // status line indicator</font></pre>
<pre><font color="#008000"> ID_INDICATOR_CAPS,</font></pre>
<pre><font color="#008000"> ID_INDICATOR_NUM,</font></pre>
<pre><font color="#008000"> ID_INDICATOR_SCRL,</font></pre>
<pre><font color="#008000">};</font></pre>
<P>To add your new pane to the array, type the pane's ID into the array at the position in which you want it to appear in the status bar, followed by a comma. (The first pane, <font color="#008000">ID_SEPARATOR</font>, should always remain in the first
position.) Listing 10.4 shows the indicator array with the new pane added.</P>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P><I>Listing 10.4—MainFrm.cpp—The Expanded Indicator Array</I></P>
<pre><font color="#008000">static UINT indicators[] =</font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> ID_SEPARATOR, // status line indicator</font></pre>
<pre><font color="#008000"> ID_MYNEWPANE,</font></pre>
<pre><font color="#008000"> ID_INDICATOR_CAPS,</font></pre>
<pre><font color="#008000"> ID_INDICATOR_NUM,</font></pre>
<pre><font color="#008000"> ID_INDICATOR_SCRL,</font></pre>
<pre><font color="#008000">};</font></pre>
<P><A ID="I12" NAME="I12"><B>Creating the Pane's Command-Update Handler</B></A></P>
<P>MFC does not automatically enable new panes when it creates the status bar. Instead, you must create a command-update handler for the new pane and enable the pane yourself. (You first learned about command-update handlers in <A HREF="index04.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index04.htm"
target="text">Chapter 4</A>, "Messages and Commands.") Also, for most applications, the string displayed in the pane is calculated on-the-fly—the default string you defined in an earlier step is only a placeholder.</P>
<P>Normally you use ClassWizard to arrange for message to be caught, but ClassWizard does not help you catch status bar messages. You must add the handler entries to the message map yourself, and then add the code for the handler. You add entries to the
message map in the header file and the map in the source file, and you add them outside the special <font color="#008000">AFX_MSG_MAP</font> comments used by ClassWizard.</P>
<P>Double-click CMainFrame to open the header file, and scroll to the bottom. Edit the message map so that it resembles Listing 10.5. When you write your own applications, you will use a variety of function names to update status bar panes, but the rest
of the delcaration will always be the same.</P>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P><I>Listing 10.5—MainFrm.h—Message Map</I></P>
<pre><font color="#008000">// Generated message map functions</font></pre>
<pre><font color="#008000">protected:</font></pre>
<pre><font color="#008000"> //{{AFX_MSG(CMainFrame)</font></pre>
<pre><font color="#008000"> afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);</font></pre>
<pre><font color="#008000"> // NOTE - the ClassWizard will add and remove member functions here.</font></pre>
<pre><font color="#008000"> // DO NOT EDIT what you see in these blocks of generated code!</font></pre>
<pre><font color="#008000"> //}}AFX_MSG</font></pre>
<pre><font color="#008000"> afx_msg void OnUpdateMyNewPane(CCmdUI *pCmdUI);</font></pre>
<pre><font color="#008000"> DECLARE_MESSAGE_MAP()</font></pre>
<P>Next, you add the handler to the source message map to actually associate the command ID with the handler. Open any <font color="#008000">CMainFrame</font> function and scroll upwards until you find the message map, then edit it so that it looks like
Listing 10.6.</P>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P><I>Listing 10.6—MainFrm.cpp—Message Map</I></P>
<pre><font color="#008000">BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)</font></pre>
<pre><font color="#008000"> //{{AFX_MSG_MAP(CMainFrame)</font></pre>
<pre><font color="#008000"> // NOTE - the ClassWizard will add and remove mapping macros here.</font></pre>
<pre><font color="#008000"> // DO NOT EDIT what you see in these blocks of generated code !</font></pre>
<pre><font color="#008000"> ON_WM_CREATE()</font></pre>
<pre><font color="#008000"> //}}AFX_MSG_MAP</font></pre>
<pre><font color="#008000"> ON_UPDATE_COMMAND_UI(ID_MYNEWPANE, OnUpdateMyNewPane)</font></pre>
<pre><font color="#008000">END_MESSAGE_MAP()</font></pre>
<P>You have now arranged that whenever the status bar pane <font color="#008000">ID_MYNEWPANE</font> needs to be updated, the <font color="#008000">CMainFrame</font> member function <font color="#008000">OnUpdateMyNewPane()</font> will be called.</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 10.7 shows the command-update handler for the new pane. As you can see, it uses a member variable called <font
color="#008000">m_paneString</font>. Update handlers should be very quick—the job of making sure that <font color="#008000">m_paneString</font> holds the right string should be tackled in a function that is called less often.</P>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P><I>Listing 10.7—</I>CMainFrame::OnUpdateMyNewPane()</P>
<pre><font color="#008000">void CMainFrame::OnUpdateMyNewPane(CCmdUI *pCmdUI) </font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> pCmdUI->Enable(); </font></pre>
<pre><font color="#008000"> pCmdUI->SetText(m_paneString);</font></pre>
<pre><font color="#008000">}</font></pre>
<P><A ID="I13" NAME="I13"><B>Setting the Status Bar's Appearance</B></A></P>
<P>To add the last touch to your status bar demonstration application, you will want a way to set <font color="#008000">m_paneString</font>. To initialize it, add this line to the <font color="#008000">CMainFrame</font> constructor:</P>
<P><B><font color="#008000"> m_paneString = "Default string";</font></B></P>
<P>The value you entered in the string table is only to keep Developer Studio sure that the resource ID you created is in use. Right-click <font color="#008000">CMainFrame</font> in ClassView and choose Add Member Variable to add <font
color="#008000">m_paneString</font> as a private member variable. The type should be <font color="#008000">CString</font>.</P>
<P>To set up the status bar for the first time, add these lines to <font color="#008000">CMainFrame::OnCreate()</font>, just before the <font color="#008000">return</font> statement:</P>
<P><B><font color="#008000"> CClientDC dc(this);</font></B></P>
<P><B><font color="#008000"> SIZE size = dc.GetTextExtent(m_paneString);</font></B></P>
<P><B><font color="#008000"> int index = m_wndStatusBar.CommandToIndex(ID_MYNEWPANE);</font></B></P>
<P><B><font color="#008000"> m_wndStatusBar.SetPaneInfo(index,ID_MYNEWPANE, SBPS_POPOUT, size.cx);</font></B></P>
<P>These lines set the text string and the size of the pane. You set the size of the pane with a call to <font color="#008000">SetPaneInfo()</font>, which needs the index of the pane and the new size. <font color="#008000">CommandToIndex()</font> gets you
the index of the pane, and <font color="#008000">GetTextExtent()</font> gets you the size. As a nice touch, the call to <font color="#008000">SetPaneInfo()</font> uses the <font color="#008000">SBPS_POPOUT</font> style to create a pane that seems to stick
out from the status bar, rather than being indented.</P>
<P>The user will change the string by making a menu selection. Open the <font color="#008000">IDR_STATUSTYPE</font> menu in the resource editor and add a Change S<U>t</U>ring item to the <U>F</U>ile menu. (Working with menus is discussed for the first
time in <A HREF="index09.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index09.htm" target="text">Chapter 9</A>, “Building a Complete Application: <font color="#008000">ShowString</font>.”) Let Developer Studio assign it the resource ID <font color="#008000">ID_FILE_CHANGESTRING</font>.</P>
<P>Bring up ClassWizard and add a handler for this command; it should be caught by <font color="#008000">CMainFrame</font>, because that’s where the <font color="#008000">m_paneString</font> variable is kept. ClassWizard offers to call the handler
<font color="#008000">OnFileChangestring()</font> and you should accept this name. Click OK to close ClassWizard.</P>
<P>Insert a new dialog box into the application and call it <font color="#008000">IDD_PANEDLG</font>. The title should be <font color="#008000">Change Pane String</font>. Add a single edit box, stretched the full width of the dialog box, and leave the ID
as <font color="#008000">IDC_EDIT1</font>. 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, bring up ClassWizard. Create a new class for the dialog box called <font
color="#008000">CPaneDlg</font>, and associate the edit control, <font color="#008000">IDC_EDIT1</font>, with a <font color="#008000">CString</font> member variable of the dialog class called <font color="#008000">m_paneString</font>.</P>
<blockquote><p><img src="tip.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/tip.gif">
<P>Adding dialog boxes to applications and associating them with classes is discussed in more depth in several earlier chapters, including <A HREF="index02.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index02.htm" target="text">Chapter 2</A>, “Dialog Boxes and Controls,” and <A HREF="index10.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index10.htm"
target="text">Chapter 10</A>, “Building a Complete Application: ShowString.”</P>
<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>
<P>Switch to ClassView, expand <font color="#008000">CMainFrame</font>, and double-click <font color="#008000">OnFileChangeString()</font> to edit it. Add the code shown in Listing 10.8.</P>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P><I>Listing 10.8—</I>CMainFrame::OnFileChangestring()</P>
<pre><font color="#008000">void CMainFrame::OnFileChangestring() </font></pre>
<pre><font color="#008000">{</font></pre>
<pre><font color="#008000"> CPaneDlg dialog(this);</font></pre>
<pre><font color="#008000"> dialog.m_paneString = m_paneString;</font></pre>
<pre><font color="#008000"> int result = dialog.DoModal();</font></pre>
<pre><font color="#008000"> if (result == IDOK)</font></pre>
<pre><font color="#008000"> {</font></pre>
<pre><font color="#008000"> m_paneString = dialog.m_paneString;</font></pre>
<pre><font color="#008000"> CClientDC dc(this);</font></pre>
<pre><font color="#008000"> SIZE size = dc.GetTextExtent(m_paneString);</font></pre>
<pre><font color="#008000"> int index = m_wndStatusBar.CommandToIndex(ID_MYNEWPANE);</font></pre>
<pre><font color="#008000"> m_wndStatusBar.SetPaneInfo(index,</font></pre>
<pre><font color="#008000"> ID_MYNEWPANE, SBPS_POPOUT, size.cx);</font></pre>
<pre><font color="#008000"> }</font></pre>
<pre><font color="#008000">}</font></pre>
<P>This code displays the dialog box, and, if the user exits the dialog box by clicking the OK button, changes the text string and resets the size of the pane. The code is very similar to the lines you added to <font color="#008000">OnCreate()</font>.
Scroll up to the top of MainFrm.cpp and add this line:</P>
<P><B><font color="#008000">#include "panedlg.h"</font></B></P>
<P>This tells the compiler what the <font color="#008000">CPaneDlg</font> class is. Build and run the <font color="#008000">Status</font> application, and you should see the window shown in Figure 10.16. As you can see, the status bar contains an extra
panel displaying the text <font color="#008000">Default string</font>. If you choose <U>F</U>ile, Change S<U>t</U>ring, 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 10.17).</P>
<A HREF="Lfigs16.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch10/Lfigs16.gif"><b>Fig. 10.16</b></A>
<P><I>The Status Bar Demo application shows how to add and manage a status bar panel.</I></P>
<A HREF="Lfigs17.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch10/Lfigs17.gif"><b>Fig. 10.17</b></A>
<P><I>The panel resizes itself to fit the new string.</I></P>
<H3><A ID="I14" NAME="I14"><B>From Here</B></A><B>...</B></H3>
<P>Users of Windows applications expect to find certain user-interface elements in place when they run a new application. Two of the most visible of these interface elements are the toolbar and the status bar, which have become standard parts of just
about every Windows application. The toolbar provides the user with shortcut buttons for selecting menu commands, whereas the status bar keeps the user apprised of the application's state, as well as displays messages such as command descriptions. </P>
<P>AppWizard and MFC provide a terrific starting point for implementing these useful interface elements, and with a little effort you can make your application truly user-friendly.</P>
<P>For more information, refer to the following chapters:</P>
<ul>
<li> <A HREF="index02.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index02.htm" target="text">Chapter 2</A>, "Dialog Boxes and Controls," explains how to use dialog boxes in your applications.</P>
<li> <A HREF="index04.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index04.htm" target="text">Chapter 4</A>, "Messages and Commands," describes MFC's message-mapping system, which enables you to respond to menu commands, as well as enable and disable those commands.</P>
<li> <A HREF="index09.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index09.htm" target="text">Chapter 9</A>, "Building a Complete Application: ShowString," provides the information you need to build menus, dialog boxes, and other user interface elements.</P>
</ul>
<p><hr></p>
<center>
<p><font size=-2>
© 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a
Simon and Schuster Company.</font></p>
</center>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -