?? ch23.htm
字號:
<H4><FONT COLOR="#000077">TYPE: Listing 23.1. Constructing a CMultiDocTemplate objectthat associates CDVTestDoc and CFormTest.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>CMultiDocTemplate* pDocTemplate;</TT><TT>pDocTemplate = new CMultiDocTemplate(</TT><TT> IDR_DVTESTTYPE,</TT><TT> RUNTIME_CLASS(CDVTestDoc),</TT><TT> RUNTIME_CLASS(CChildFrame), // custom MDI child frame</TT><TT> RUNTIME_CLASS(CFormTest)); // Change this line</TT></FONT></PRE><P><TT>AddDocTemplate(pDocTemplate);</TT> Because <TT>CFormTest</TT> is now used,the class declaration for <TT>CFormTest</TT> must be included into the <TT>DVTest.cpp</TT>source file. Add the following line after all other <TT>#include</TT> directivesat the top of the <TT>DVTest.cpp</TT> source file:</P><PRE><FONT COLOR="#0066FF"><TT>#include "FormTest.h"</TT></FONT></PRE><H3><FONT COLOR="#000077"><B>Handling Events and Messages in the Form View Class</B></FONT></H3><P>A form view must handle a wide variety of messages. Just like any view, it mustsupport several interfaces as part of the Document/View architecture. However, unlikeother views, a form view must also handle any controls contained by the view. Forexample, two events generated by controls must be handled in the <TT>CFormTest</TT>class:<UL> <LI>When the button labeled Apply is pressed, the view should update the document and prepare for a new entry.<BR> <BR> <LI>When the button labeled Close is pressed, the view should be closed.</UL><P>Use ClassWizard to add two message-handling functions for these events, usingthe values from Table 23.5.<H4><FONT COLOR="#000077">Table 23.5. Message-handling events added to the CFormTestclass.</FONT></H4><P><TABLE BORDER="1"> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP"><B>Object ID</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Message</B></TD> <TD ALIGN="LEFT" VALIGN="TOP"><B>Function Name</B></TD> </TR> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP"><TT>IDC_APPLY</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>BN_CLICKED</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>OnApply</TT></TD> </TR> <TR ALIGN="LEFT" rowspan="1"> <TD ALIGN="LEFT" VALIGN="TOP"><TT>IDC_CLOSE</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>BN_CLICKED</TT></TD> <TD ALIGN="LEFT" VALIGN="TOP"><TT>OnClose</TT></TD> </TR></TABLE></P><P>The code to handle control events is fairly straightforward. Edit the new functionsadded to the <TT>CFormTest</TT> class so that they look like the code in Listing23.2.<H4><FONT COLOR="#000077">TYPE: Listing 23.2. CFormTest functions used to handlecontrol messages.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>void CFormTest::OnApply()</TT><TT>{</TT><TT> CDVTestDoc* pDoc;</TT><TT> pDoc = (CDVTestDoc*)GetDocument();</TT><TT> ASSERT_VALID( pDoc );</TT><TT> CString szName;</TT><TT> m_edNames.GetWindowText( szName );</TT><TT> m_edNames.SetWindowText( "" );</TT><TT> m_edNames.SetFocus();</TT><TT> if( szName.GetLength() > 0 )</TT><TT> {</TT><TT> int nIndex = pDoc->AddName( szName );</TT><TT> m_lbNames.InsertString( nIndex, szName );</TT><TT> m_lbNames.SetCurSel( nIndex );</TT><TT> }</TT><TT>}</TT><TT>void CFormTest::OnClose()</TT><TT>{</TT><TT> PostMessage( WM_COMMAND, ID_FILE_CLOSE );</TT></FONT></PRE><P><TT>}</TT> You must manually add an include statement for the document class.At the top of the <TT>FormView.cpp</TT> file, add the following line just after allthe other <TT>#include</TT> directives:</P><PRE><FONT COLOR="#0066FF"><TT>#include "DVTestDoc.h"</TT></FONT></PRE><P>The <TT>OnApply</TT> function is split into three main parts:<UL> <LI>The document pointer is retrieved and verified, as in the <TT>OnDraw</TT> function discussed in Hour 9.<BR> <BR> <LI>The contents of the edit control are collected and stored in a <TT>CString</TT> object. After the string is collected, the control is cleared and the input focus is returned to the edit control. This enables the user to immediately make a new entry.<BR> <BR> <LI>If a string was entered, <TT>szName</TT> will have a length greater than zero. If so, the name is added to the document and the list box is updated. The <TT>SetCurSel</TT> function is used to scroll to the new list box item.</UL><P>The <TT>OnClose</TT> member function uses the <TT>PostMessage</TT> function tosend an <TT>ID_FILE_CLOSE</TT> message to the application. This has the same effectas selecting Close from the File menu.<H3><FONT COLOR="#000077"><B>Handling <TT>OnInitialUpdate</TT></B></FONT></H3><P>When using a form view, update it during <TT>OnInitialUpdate</TT>, as the viewis initially displayed. In Hour 9, <TT>CDVTestView</TT> used <TT>OnDraw</TT> to retrievethe document's contents and display the items in the view. The <TT>OnInitialUpdate</TT>function uses similar code, as shown in Listing 23.3. Before editing the code, addthe <TT>OnInitialUpdate</TT> function to the <TT>CFormTest</TT> class using ClassWizard.<H4><FONT COLOR="#000077">TYPE: Listing 23.3. Using OnInitialUpdate to retrieve datafrom the document.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>void CFormTest::OnInitialUpdate()</TT><TT>{</TT><TT> CFormView::OnInitialUpdate();</TT><TT> CDVTestDoc* pDoc = (CDVTestDoc*)GetDocument();</TT><TT> ASSERT_VALID(pDoc);</TT><TT> for( int nIndex = 0; nIndex < pDoc->GetCount(); nIndex++ )</TT><TT> {</TT><TT> CString szName = pDoc->GetName( nIndex );</TT><TT> m_lbNames.AddString( szName );</TT><TT> }</TT><TT>}</TT></FONT></PRE><BLOCKQUOTE> <P><HR><B> </B><FONT COLOR="#000077"><B>Time Saver:</B></FONT><B> </B>When a dialog box is displayed, the dialog resource is used to size the dialog box's window. A form view is not automatically sized this way, which leads to an unexpected display if you aren't aware of this behavior. However, you can resize the view to the exact dimensions of the dialog resource by using the <TT>ResizeParentToFit</TT> function. Add the following two lines of code to the <TT>CFormTest::OnInitialUpdate</TT> member function:</P> <PRE><FONT COLOR="#0066FF"><TT>ResizeParentToFit( FALSE );</TT><TT>ResizeParentToFit();</TT></FONT></PRE></BLOCKQUOTE><PRE><FONT COLOR="#0066FF"><TT></TT></FONT></PRE><BLOCKQUOTE> <P>Nope, it's not a typo; you must call <TT>ResizeParentToFit</TT> twice to make sure that the size is calculated correctly. The first call allows the view to expand and the second call shrinks the view to fit the dialog resource. <HR></BLOCKQUOTE><H3><FONT COLOR="#000077"><B>Preventing a View Class from Being Resized</B></FONT></H3><P>Like all views, you can resize a form view in three ways:<UL> <LI>By dragging the view's frame with the mouse<BR> <BR> <LI>By pressing the minimize icon<BR> <BR> <LI>By pressing the maximize icon</UL><P>Although the minimize button is handy, the other sizing methods are a problemfor form views. Because a form view looks like a dialog box and the control layoutis specified in the dialog resource, preventing the user from resizing is a goodidea.</P><P>The form view class doesn't actually have any control over the minimize and maximizebuttons--they belong to the frame, which also controls the capability to change thesize of the view by dragging it with a mouse. The <TT>CChildFrame</TT> class is theframe used by default in MDI applications, although you can change the frame classby using a different class name when the document template is created.</P><P>To remove the sizable frame and minimize button from the frame class, add twolines of code to the frame class <TT>PreCreateWindow</TT> member function. The <TT>PreCreateWindow</TT>function is called just before the window is created. This enables you to changethe style of the window, as shown in Listing 23.4.<H4><FONT COLOR="#000077">TYPE: Listing 23.4. Using the PreCreateWindow functionto change CChildFrame style attributes.</FONT></H4><PRE><FONT COLOR="#0066FF"><TT>BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)</TT><TT>{</TT><TT> // Mask away the thickframe and maximize button style bits.</TT><TT> cs.style &= ~WS_THICKFRAME;</TT><TT> cs.style &= ~WS_MAXIMIZEBOX;</TT><TT> return CMDIChildWnd::PreCreateWindow(cs);</TT></FONT></PRE><P><TT>}</TT> The <TT>&=</TT> operator is the C++ bitwise <TT>AND</TT> operator,which is used to clear or remove a bit that is set in a particular value. The tilde(<TT>~</TT>) is the C++ inversion operator, used to "flip" the individualbits of a particular value. These two operators are commonly used together to maskoff attributes that have been set using the bitwise OR operator. In Listing 23.4,the <TT>WS_THICKFRAME</TT> and <TT>WS_MAXIMIZEBOX</TT> attributes are cleared fromthe <TT>cs.style</TT> variable.</P><P>Compile and run the DVTest project. Figure 23.4 shows DVTest after a few nameshave been added to the list box.</P><P><A NAME="04"></A><A HREF="04.htm"><B>Figure 23.4.</B></A> <I><BR>DVTest after adding a form view to the project.</I><H2><FONT COLOR="#000077"><B>Using Multiple Views</B></FONT></H2><P>Programs written for Windows sometimes offer multiple views for their data. Forexample, many word processors offer print preview and layout views of a document,in addition to the normal WYSIWYG view that's used most of the time. Providing multipleviews for a single document is a different issue than allowing several differentdocuments to be open at the same time; each view actually is connected to a singledocument, as shown in Figure 23.5.</P><P><A NAME="05"></A><A HREF="05.htm"><B>Figure 23.5.</B></A> <I><BR>Multiple views connected to a single document in an MDI application.</I></P><P>The most common reason to use multiple views is because there are different waysof looking at information contained in a document. For example, a form view oftenis used to give detailed information about a particular item in a database; anotherview might be used for data entry; still another type of view might be used to providea summary of all items in the same database. Offering several views at the same timeprovides maximum flexibility for users of the program.</P><P>Because each of these views is connected to a single document, there must be someway to update the views when needed to keep them synchronized. When one of the viewschanges the document, all views must immediately be updated.<BLOCKQUOTE> <P><HR><B> </B><FONT COLOR="#000077"><B>Just a Minute:</B></FONT><B> </B>Using multiple views allows each view to be specialized for a particular purpose. If only a single view were allowed, that view would have to be extremely flexible to suit the needs of every user of your program. Creating specialized views for particular purposes allows each of these views to do a single job for which they are well suited. <HR></BLOCKQUOTE><H3><FONT COLOR="#000077"><B>How to Use Multiple Views</B></FONT></H3><P>Using multiple views in an MDI application is easy because the Document/View architecturekeeps the document and view classes separate from each other. The document classis mainly passive; it notifies the framework when views should be updated, but otherwiserelies on the view classes to change or request data stored in the document.</P><P>A new view is easily associated with an existing document. After a document classhas been modified to work with multiple views, any number of view classes can beadded to the program without further modifications to the document class. The followingsteps are required to modify an MDI program to use multiple views:<UL> <LI>Create a new view class in addition to any existing view associated with the document.<BR> <BR> <LI>Create shared resources, if needed, for the new view class.<BR> <BR> <LI>Add code to the view classes to properly handle the <TT>OnInitialUpdate</TT> and <TT>OnUpdate</TT> virtual functions.<BR> <BR> <LI>Modify the document class to call <TT>UpdateAllViews</TT> when the data contained in the document changes.<BR> <BR> <LI>Modify the application class so that it stores pointers to document templates it creates.<BR> <BR> <LI>Add code to the main frame class to handle menu selections that select a particular view.</UL><P>You will learn about each of these steps in the following sections. Because theDocument/View architecture is designed to support multiple views, you can rely onClassWizard to write much of the code for you. To reduce the amount of typing needed,continue to modify the DVTest program from Hour 9.<H3><FONT COLOR="#000077"><B>Creating a New View</B></FONT></H3><P>The first step in adding a new view to an existing document is to define the viewby creating a view class. Any type of view can be added to an existing MDI program.In this set of examples, the new view displays the names contained in the documentclass. The existing form view is used to add names to the <TT>DVTestDoc</TT> document.</P><P>The new view class, <TT>CDisplayView</TT>, is derived directly from <TT>CView</TT>.Because <TT>CDisplayView</TT> only displays information, it must support only two
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -