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

📄 ch12.htm

📁 Using Visual C++ 6.0 一本关于Visual C++ 6.0基本编程应用的书籍。
💻 HTM
📖 第 1 页 / 共 3 页
字号:
    CPropSheet propSheet("Property Sheet", this, 0);
    propSheet.m_page1.m_edit = m_edit;
    propSheet.m_page2.m_checkbox = m_check;
    int result = propSheet.DoModal();
    if (result == IDOK)
    {
        m_edit = propSheet.m_page1.m_edit;
        m_check = propSheet.m_page2.m_checkbox;
        Invalidate();
    }
     
</PRE>
<PRE>}
</PRE>

<DL>
	<DT></DT>
	<DD>The code segment in Listing 12.2, discussed in more detail later in this chapter,
	creates an instance of the CPropSheet class and sets the member variables of each
	of its pages. It displays the sheet by using the familiar DoModal function first
	discussed in Chapter 2, &quot;Dialogs and Controls.&quot; If users click OK, it updates
	the view member variables to reflect the changes made on each page and forces a redraw
	with a call to Invalidate().
	<P>
</DL>

<H2><A NAME="Heading8"></A>Running the Property Sheet Demo Application</H2>
<P>You've finished the complete application. Click the Build button on the Build
minibar (or choose Build, Build) to compile and link the application. Run it by choosing
Build, Execute or by clicking the Execute button on the Build minibar. When you do,
you see the window shown in Figure 12.15.</P>
<P>As you can see, the window displays two values--the default values for the controls
in the application's property sheet. You can change these values by using the property
sheet. Choose File, Property Sheet; the property sheet appears (see Figure 12.16).
The property sheet contains two pages, each of which holds a single control. When
you change the settings of these controls and click the property sheet's OK button,
the application's window displays the new values. Try it!</P>
<P><A HREF="javascript:popUp('12uvc15.gif')"><B>FIG. 12.15</B></A><B> </B><I>When
it first starts, the Property Sheet Demo application displays default values for
the property sheet's controls.</I></P>
<P><A HREF="javascript:popUp('12uvc16.gif')"><B>FIG. 12.16</B></A><B> </B><I>The
application's property sheet contains two pages.</I></P>
<H2><A NAME="Heading9"></A>Adding Property Sheets to Your Applications</H2>
<P>To add a property sheet to one of your own applications, you follow steps very
similar to those you followed in the previous section to create the demo application:</P>

<DL>
	<DT></DT>
	<DD><B>1. </B>Create a dialog box resource for each page in the property sheet. These
	resources should have the Child and Thin styles and should have no system menu.
	<P>
	<DT></DT>
	<DD><B>2. </B>Associate each property page resource with an object of the CPropertyPage
	class. You can do this easily with ClassWizard. Connect controls on the property
	page to members of the class you create.
	<P>
	<DT></DT>
	<DD><B>3. </B>Create a class for the property sheet, deriving the class from MFC's
	CPropertySheet class. You can generate this class by using ClassWizard.
	<P>
	<DT></DT>
	<DD><B>4. </B>In the property sheet class, add member variables for each page you'll
	be adding to the property sheet. These member variables must be instances of the
	property page classes that you created in step 2.
	<P>
	<DT></DT>
	<DD><B>5. </B>In the property sheet's constructor, call AddPage() for each page in
	the property sheet.
	<P>
	<DT></DT>
	<DD><B>6. </B>To display the property sheet, call the property sheet's constructor
	and then call the property sheet's DoModal() member function, just as you would with
	a dialog box.
	<P>
</DL>

<P>After you write your application and define the resources and classes that represent
the property sheet (or sheets--you can have more than one), you need a way to enable
users to display the property sheet when it's needed. In Property Sheet Demo, this
is done by associating a menu item with a message-response function. However you
handle the command to display the property sheet, the process of creating the property
sheet is the same. First, you must call the property sheet class's constructor, which
Property Sheet Demo does like this:</P>
<P>
<PRE>CPropSheet propSheet(&quot;Property Sheet&quot;, this, 0);
</PRE>
<P>Here, the program creates an instance of the CPropSheet class. This instance (or
object) is called propSheet. The three arguments are the property sheet's title string,
a pointer to the parent window (which, in this case, is the view window), and the
zero-based index of the first page to display. Because the property pages are created
in the property sheet's constructor, creating the property sheet also creates the
property pages.</P>
<P>After you create the property sheet object, you can initialize the data members
that hold the values of the property page's controls, which Property Sheet Demo does
like this:</P>
<P>
<PRE>propSheet.m_page1.m_edit = m_edit;
propSheet.m_page2.m_checkbox = m_check;
</PRE>
<P>Now it's time to display the property sheet, which you do just as though it were
a dialog box, by calling the property sheet's DoModal() member function:</P>
<P>
<PRE>int result = propSheet.DoModal();
</PRE>
<P>DoModal() doesn't take any arguments, but it does return a value indicating which
button users clicked to exit the property sheet. In a property sheet or dialog box,
you'll usually want to process the information entered into the controls only if
users clicked OK, which is indicated by a return value of IDOK. If users exit the
property sheet by clicking the Cancel button, the changes are ignored and the view
or document member variables aren't updated.</P>
<P>
<H2><A NAME="Heading10"></A>Changing Property Sheets to Wizards</H2>
<P>Here's a piece of information that surprises most people: A wizard is just a special
property sheet. Instead of tabbed pages on each sheet that allow users to fill in
the information in any order or to skip certain pages entirely, a wizard has Back,
Next, and Finish buttons to move users through a process in a certain order. This
forced sequence makes wizards terrific for guiding your application's users through
the steps needed to complete a complex task. You've already seen how AppWizard in
Visual C++ makes it easy to start a new project. You can create your own wizards
suited to whatever application you want to build. In the following sections, you'll
see how easy it is to convert a property sheet to a wizard.</P>
<P>
<H3><A NAME="Heading11"></A>Running the Wizard Demo Application</H3>
<P>To understand Wizards, this section will show you the Wizard Demo application,
which is built in much the same way as the Property Sheet Demo application that you
created earlier in this chapter. This chapter won't present step-by-step instructions
to build Wizard Demo. You will be able to build it yourself if you want, using the
general steps presented earlier and the code snippets shown here.</P>
<P>When you run the Wizard Demo application, the main window appears, looking very
much like the Property Sheet Demo main window. The File menu now includes a Wizard
item; choosing File Wizard brings up the wizard shown in Figure 12.17.</P>
<P><A HREF="javascript:popUp('12uvc17.gif')"><B>FIG. 12.17</B></A><B> </B><I>The
Wizard Demo application displays a wizard rather than a property sheet.</I></P>
<P>The wizard isn't too fancy, but it does demonstrate what you need to know to program
more complex wizards. As you can see, this wizard has three pages. On the first page
is an edit control and three buttons: Back, Next, and Cancel. The Back button is
disabled because there's no previous page to go back to. The Cancel button enables
users to dismiss the wizard at any time, canceling whatever process the wizard was
guiding users through. The Next button causes the next page in the wizard to appear.</P>
<P>You can change whatever is displayed in the edit control if you like. However,
the magic really starts when you click the Next button, which displays Page 2 of
the wizard (see Figure 12.18). Page 2 contains a check box and the Back, Next, and
Cancel buttons. Now the Back button is enabled, so you can return to Page 1 if you
want to. Go ahead and click the Back button. The wizard tells you that the check
box must be checked (see Figure 12.19). As you'll soon see, this feature of a wizard
enables you to verify the contents of a specific page before allowing users to advance
to another step.</P>
<P><A HREF="javascript:popUp('12uvc18.gif')"><B>FIG. 12.18</B></A><B> </B><I>In Page
2 of the wizard, the Back button is enabled.</I></P>
<P>After checking the check box, you can click the Back button to move back to Page
1 or click Next to advance to Page 3. Assuming that you advance to Page 3, you see
the display shown in Figure 12.20. Here, the Next button has changed to the Finish
button because you are on the wizard's last page. If you click the Finish button,
the wizard disappears.</P>
<P><A HREF="javascript:popUp('12uvc19.gif')"><B>FIG. 12.19</B></A><B> </B><I>You
must select the check box before the wizard will let you leave Page 2.</I></P>
<P><A HREF="javascript:popUp('12uvc20.gif')"><B>FIG. 12.20</B></A><B> </B><I>This
is the last page of the Wizard Demo Application's wizard.</I></P>
<H3><I></I></H3>
<H3><A NAME="Heading12"></A>Creating Wizard Pages</H3>
<P>As far as your application's resources go, you create wizard pages exactly as
you create property sheet pages--by creating dialog boxes and changing the dialog
box styles. The dialog titles--Page 1 of 3, Page 2 of 3, and Page 3 of 3--are hardcoded
onto each dialog box. You associate each dialog box resource with an object of the
CPropertyPage class. Then, to take control of the pages in your wizard and keep track
of what users are doing with the wizard, you override the OnSetActive(), OnWizardBack(),
OnWizardNext(), and OnWizardFinish() functions of your property page classes. Read
on to see how to do this.</P>
<P>
<H3><A NAME="Heading13"></A>Displaying a Wizard</H3>
<P>The File, Wizard command is caught by CWizView's OnFileWizard() function. It's
very similar to the OnPropSheet() function in the Property Sheet demo, as you can
see from Listing 12.3. The first difference is the call to SetWizardMode() before
the call to DoModal(). This function call tells MFC that it should display the property
sheet as a wizard rather than as a conventional property sheet. The only other difference
is that users arrange for property sheet changes to be accepted by clicking Finish,
not OK, so this code checks for ID_WIZFINISH rather than IDOK as a return from DoModal().</P>
<P>
<H4>Listing 12.3&#160;&#160;CWizView::OnFileWizard()</H4>
<PRE>void CWizView::OnFileWizard() 
{
     CWizSheet wizSheet(&quot;Sample Wizard&quot;, this, 0);
     wizSheet.m_page1.m_edit = m_edit;
     wizSheet.m_page2.m_check = m_check;
     wizSheet.SetWizardMode();
     int result = wizSheet.DoModal();
     if (result == ID_WIZFINISH)
     {
          m_edit = wizSheet.m_page1.m_edit;
          m_check = wizSheet.m_page2.m_check;
          Invalidate();
     }
</PRE>
<PRE>}
</PRE>
<H3><A NAME="Heading14"></A>Setting the Wizard's Buttons</H3>
<P>MFC automatically calls the OnSetActive() member function immediately upon displaying
a specific page of the wizard. So, when the program displays Page 1 of the wizard,
the CPage1 class's OnSetActive() function is called. You add code to this function
that makes the wizard behave as you want. CPage1::OnSetActive() looks like Listing
12.4.</P>
<P>
<H4>Listing 12.4&#160;&#160;CPage1::OnSetActive()</H4>
<PRE>BOOL CPage1::OnSetActive() 
{
     CPropertySheet* parent = (CPropertySheet*)GetParent();
     parent-&gt;SetWizardButtons(PSWIZB_NEXT);
     return CPropertyPage::OnSetActive();
</PRE>
<PRE>}
</PRE>
<P>OnSetActive() first gets a pointer to the wizard's property sheet window, which
is the page's parent window. Then the program calls the wizard's SetWizardButtons()
function, which determines the state of the wizard's buttons. SetWizardButtons()
takes a single argument, which is a set of flags indicating how the page should display
its buttons. These flags are PSWIZB_BACK, PSWIZB_NEXT, PSWIZB_FINISH, and PSWIZB_DISABLEDFINISH.
Because the call to SetWizardButtons() in Listing 12.4 includes only the PSWIZB_NEXT
flag, only the Next button in the page will be enabled.</P>
<P>Because the CPage2 class represents Page 2 of the wizard, its call to SetWizardButtons()
enables the Back and Next buttons by combining the appropriate flags with the bitwise
OR operator (|), like this:</P>
<P>
<PRE>parent-&gt;SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
</PRE>
<P>Because Page 3 of the wizard is the last page, the CPage3 class calls SetWizardButtons()
like this:</P>
<P>
<PRE>parent-&gt;SetWizardButtons(PSWIZB_BACK | PSWIZB_FINISH);
</PRE>
<P>This set of flags enables the Back button and provides a Finish button instead
of a Next button.</P>
<P>
<H3><A NAME="Heading15"></A>Responding to the Wizard's Buttons</H3>
<P>In the simplest case, MFC takes care of everything that needs to be done in order
to flip from one wizard page to the next. That is, when users click a button, MFC
springs into action and performs the Back, Next, Finish, or Cancel command. However,
you'll often want to perform some action of your own when users click a button. For
example, you may want to verify that the information that users entered into the
currently displayed page is correct. If there's a problem with the data, you can
force users to fix it before moving on.</P>
<P>To respond to the wizard's buttons, you override the OnWizardBack(), OnWizardNext(),
and OnWizardFinish() member functions. Use the Message Maps tab of ClassWizard to
do this; you'll find the names of these functions in the Messages window when a property
page class is selected in the Class Name box. When users click a wizard button, MFC
calls the matching function which does whatever is needed to process that page. An
example is the way the wizard in the Wizard Demo application won't let you leave
Page 2 until you've checked the check box. This is accomplished by overriding the
functions shown in Listing 12.5.</P>
<P>
<H4>Listing 12.5&#160;&#160;Responding to Wizard Buttons</H4>
<PRE>LRESULT CPage2::OnWizardBack() 
{
     CButton *checkBox = (CButton*)GetDlgItem(IDC_CHECK1);
     if (!checkBox-&gt;GetCheck())
     {
          MessageBox(&quot;You must check the box.&quot;);
          return -1;
     }
     return CPropertyPage::OnWizardBack();
}
LRESULT CPage2::OnWizardNext() 
{
     UpdateData();
     if (!m_check)
     {
          MessageBox(&quot;You must check the box.&quot;);
          return -1;
     }
     return CPropertyPage::OnWizardNext();
</PRE>
<PRE>}
</PRE>
<P>These functions demonstrate two ways to examine the check box on Page 2. OnWizardBack()
gets a pointer to the page's check box by calling the GetDlgItem() function. With
the pointer in hand, the program can call the check box class's GetCheck() function,
which returns a 1 if the check box is checked. OnWizardNext() calls UpdateData()
to fill all the CPage2 member variables with values from the dialog box controls
and then looks at m_check. In both functions, if the box isn't checked, the program
displays a message box and returns -1 from the function. Returning -1 tells MFC to
ignore the button click and not change pages. As you can see, it is simple to arrange
for different conditions to leave the page in the Back or Next direction.</P>
<H1></H1>
<CENTER>
<P>
<HR>
<A HREF="../ch11/ch11.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch13/ch13.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 + -