?? ch16.htm
字號:
and then don't implement a Set function.</P>
<P><A HREF="javascript:popUp('16uvc01.gif')"><B>FIG. 16.1</B></A><B> </B><I>ClassWizard's
Automation page handles most of the work of building an Automation server.</I></P>
<P>For the purposes of this chapter, you'll add the two centering flags to the CShowStringDoc
class with Get and Set functions and add the string and color properties as direct-access
properties. To do so, follow these steps:</P>
<DL>
<DT></DT>
<DD><B>1. </B>Make sure that CShowStringDoc is the selected class, and then click
the Add Property button to bring up the Add Property dialog box.
<P>
<DT></DT>
<DD><B>2. </B>Type <B>String</B> in the External Name box. ClassWizard types along
with you, filling in the Variable Name and Notification Function boxes for you.
<P>
<DT></DT>
<DD><B>3. </B>Choose CString from the drop-down list box for Type. The dialog box
should resemble Figure 16.2.
<P>
<DT></DT>
<DD><B>4. </B>Click OK, click Add Property again, and then add Color as a direct-access
property (see Figure 16.3). Use short as the data type.
<P>
<DT></DT>
<DD><B>5. </B>Click OK, click Add Property again, and then add HorizCenter.
<P>
<DT></DT>
<DD><B>6. </B>Choose BOOL for the type and then select the Get/Set Methods radio
button. The Variable Name and Notification Function boxes are replaced by Get Function
and Set Function, already filled in, as shown in Figure 16.4. (If the type changes
from BOOL, choose BOOL again.) Click OK.
<P>
<DT></DT>
<DD><B>7. </B>Add VertCenter in the same way that you added HorizCenter.
<P>
</DL>
<P><A HREF="javascript:popUp('16uvc02.gif')"><B>FIG. 16.2</B></A><B> </B><I>Add String
as a direct-access property.</I></P>
<P><A HREF="javascript:popUp('16uvc03.gif')"><B>FIG. 16.3</B></A><B> </B><I>Add Color
as a direct-access property.</I></P>
<P><A HREF="javascript:popUp('16uvc04.gif')"><B>FIG. 16.4</B></A><B> </B><I>Add HorizCenter
as a Get/Set method property.</I></P>
<BLOCKQUOTE>
<P>
<HR>
<BR>
<strong>CAUTION:</strong><B> </B>After you click OK to add a property, you can't change
the type, external name, or other properties of the property. You have to delete
it and then add one that has the new type, or external name, or whatever. Always
look over the Add Property dialog box before clicking OK.
<HR>
</BLOCKQUOTE>
<P>Figure 16.5 shows the ClassWizard summary of exposed properties and methods. The
details of each property are shown in the Implementation box below the list of properties.
In Figure 16.5, VertCenter is highlighted, and the Implementation box reminds you
that VertCenter has a Get function and a Set function, showing their declarations.
Click OK to close ClassWizard.</P>
<P><A HREF="javascript:popUp('16uvc05.gif')"><B>FIG. 16.5</B></A><B> </B><I>ClassWizard
provides a summary of the properties you've added.</I></P>
<P>It should come as no surprise that as a result of these additions, ClassWizard
has changed the header and source files for CShowStringDoc. Listing 16.7 shows the
new dispatch map in the header file.</P>
<P>
<H4>Listing 16.7  ShowStringDoc.h--Dispatch Map</H4>
<PRE>//{{AFX_DISPATCH(CShowStringDoc)
CString m_string;
afx_msg void OnStringChanged();
short m_color;
afx_msg void OnColorChanged();
afx_msg BOOL GetHorizCenter();
afx_msg void SetHorizCenter(BOOL bNewValue);
afx_msg BOOL GetVertCenter();
afx_msg void SetVertCenter(BOOL bNewValue);
//}}AFX_DISPATCH
</PRE>
<PRE>DECLARE_DISPATCH_MAP()
</PRE>
<P>Two new member variables have been added: m_string and m_color.</P>
<BLOCKQUOTE>
<P>
<HR>
<strong>NOTE:</strong> It's natural to wonder whether these are actually public member variables;
they aren't. Just above this dispatch map is this line:</P>
<PRE>DECLARE_MESSAGE_MAP()</PRE>
<P>That macro, when it expands, declares a number of protected variables. Because
these declarations are immediately afterward, they are protected member variables
and protected functions. They're accessed in just the same way that protected message-catching
functions are--they're called by a member function hidden in the class that directs
traffic by using these maps.
<HR>
</BLOCKQUOTE>
<P>A block of code has been added in the source file, but it's boring, as you can
see by looking at Listing 16.8.</P>
<P>
<H4>Listing 16.8  ShowStringDoc.cpp--Notification, Get, and Set Functions</H4>
<PRE>/////////////////////////////////////////////////////////
// CShowStringDoc commands
void CShowStringDoc::OnColorChanged()
{
// TODO: Add notification handler code
}
void CShowStringDoc::OnStringChanged()
{
// TODO: Add notification handler code
}
BOOL CShowStringDoc::GetHorizCenter()
{
// TODO: Add your property handler here
return TRUE;
}
void CShowStringDoc::SetHorizCenter(BOOL bNewValue)
{
// TODO: Add your property handler here
}
BOOL CShowStringDoc::GetVertCenter()
{
// TODO: Add your property handler here
return TRUE;
}
void CShowStringDoc::SetVertCenter(BOOL bNewValue)
{
// TODO: Add your property handler here
</PRE>
<PRE>}
</PRE>
<P>The class still doesn't have member variables for the centering flags. (You might
have decided to implement these in some other way than as two simple variables, so
ClassWizard doesn't even try to guess what to add.) Add them by hand to the header
file, ShowStringDoc.h, as private member variables:</P>
<P>
<PRE>// Attributes
private:
BOOL m_horizcenter;
BOOL m_vertcenter;
</PRE>
<P>Now you can write their Get and Set functions; Listing 16.9 shows the code.</P>
<P>
<H4>Listing 16.9  ShowStringDoc.cpp--Get and Set Functions for the Centering
<BR>
Flags</H4>
<PRE>BOOL CShowStringDoc::GetHorizCenter()
{
return m_horizcenter;
}
void CShowStringDoc::SetHorizCenter(BOOL bNewValue)
{
m_horizcenter = bNewValue;
}
BOOL CShowStringDoc::GetVertCenter()
{
return m_vertcenter;
}
void CShowStringDoc::SetVertCenter(BOOL bNewValue)
{
m_vertcenter = bNewValue;
</PRE>
<PRE>}
</PRE>
<H3><A NAME="Heading4"></A>The OnDraw() Function</H3>
<P>Restoring the member variables takes you halfway to the old functionality of ShowString.
Changing the view's OnDraw() function will take you most of the rest of the way.</P>
<P>To write a version of OnDraw() that shows a string properly, you have a fair amount
of background work to do. Luckily, you can open an old version of ShowString from
your own work in Chapter 8, "Building a Complete Application: ShowString,"
and paste in the following bits of code. (If any of this code is unfamiliar to you,
Chapter 8 explains it fully.) First, CShowStringDoc::OnNewDocument() in Listing 16.10
should initialize the member variables.</P>
<P>
<H4>Listing 16.10  ShowStringDoc.cpp--CShowStringDoc::OnNewDocument()</H4>
<PRE>BOOL CShowStringDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
m_string = "Hello, world!";
m_color = 0; //black
m_horizcenter = TRUE;
m_vertcenter = TRUE;
return TRUE;
</PRE>
<PRE>}
</PRE>
<P>Next, edit the document's Serialize function. Listing 16.11 shows the new code.</P>
<P>
<H4>Listing 16.11  ShowStringDoc.cpp--CShowStringDoc::Serialize()</H4>
<PRE>void CShowStringDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << m_string;
ar << m_color;
ar << m_horizcenter;
ar << m_vertcenter;
}
else
{
ar >> m_string;
ar >> m_color;
ar >> m_horizcenter;
ar >> m_vertcenter;
}
</PRE>
<PRE>}
</PRE>
<P>Finally, the view's OnDraw() function in Listing 16.12 actually shows the string.</P>
<P>
<H4>Listing 16.12  ShowStringView.cpp--CShowStringView::OnDraw()</H4>
<PRE>void CShowStringView::OnDraw(CDC* pDC)
{
CShowStringDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
COLORREF oldcolor;
switch (pDoc->GetColor())
{
case 0:
oldcolor = pDC->SetTextColor(RGB(0,0,0)); //black
break;
case 1:
oldcolor = pDC->SetTextColor(RGB(0xFF,0,0)); //red
break;
case 2:
oldcolor = pDC->SetTextColor(RGB(0,0xFF,0)); //green
break;
}
int DTflags = 0;
if (pDoc->GetHorizcenter())
{
DTflags |= DT_CENTER;
}
if (pDoc->GetVertcenter())
{
DTflags |= (DT_VCENTER|DT_SINGLELINE);
}
CRect rect;
GetClientRect(&rect);
pDC->DrawText(pDoc->GetString(), &rect, DTflags);
pDC->SetTextColor(oldcolor);
</PRE>
<PRE>}
</PRE>
<P>When you added m_string, m_color, m_horizcenter, and m_vertcenter to the document
with ClassWizard, they were added as protected member variables. This view code needs
access to them. As you can see, the view calls public functions to get to these member
variables of the document.</P>
<BLOCKQUOTE>
<P>
<HR>
<strong>NOTE:</strong> You could have chosen instead to make the view a friend to the document
so that it could access the member variables directly, but that would give view functions
the capability to use and change all private and protected member variables of the
document. This more limited access is more appropriate and better preserves encapsulation.
Encapsulation and other object-oriented concepts are discussed in Appendix A, "
C++ Review and Object-Oriented Concepts."
<HR>
</BLOCKQUOTE>
<P>Several functions already in the document class access these variables, but they're
protected functions for use by ActiveX. The four public functions you'll add won't
be able to use those names, because they're taken, and will have to have not-so-good
names. Add them inline, as shown in Listing 16.13, to ShowStringDoc.h.</P>
<P>
<H4>Listing 16.13  ShowStringDoc.h--Public Access Functions</H4>
<PRE>public:
CString GetDocString() {return m_string;}
int GetDocColor() {return m_color;}
BOOL GetHorizcenter() {return m_horizcenter;}
</PRE>
<PRE> BOOL GetVertcenter() {return m_vertcenter;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -