?? ch08.htm
字號:
<BLOCKQUOTE>
<P>
<HR>
<B> </B><FONT COLOR="#000077"><B>Time Saver:</B></FONT><B> </B>It's important to
remember that the <TT>DECLARE</TT> and <TT>IMPLEMENT</TT> macros are used in two
different places. A<TT> DECLARE</TT> macro, such as <TT>DECLARE_DYNCREATE</TT>, is
used in the class declaration. An <TT>IMPLEMENT</TT> macro, such as <TT>IMPLEMENT_DYNCREATE</TT>,
is used only in the class definition.
<HR>
</BLOCKQUOTE>
<H4><FONT COLOR="#000077">Creating an Object at Runtime</FONT></H4>
<P>There are two ways to create objects dynamically. The first method uses the C++
operator <TT>new</TT> to dynamically allocate an object from free storage.</P>
<PRE><FONT COLOR="#0066FF"><TT>CMyObject* pObject = new CMyObject;</TT>
</FONT></PRE>
<P>The second method is used primarily by the MFC framework and uses a special class,
<TT>CRuntimeClass</TT>, and the <TT>RUNTIME_CLASS</TT> macro. You can use <TT>CRuntimeClass</TT>
to determine the type of an object or to create a new object. Listing 8.9 creates
a <TT>CMyObject</TT> instance using the <TT>CRuntimeClass::CreateObject</TT> function.
<H4><FONT COLOR="#000077">TYPE: Listing 8.9. Creating an object at runtime using
CRuntimeClass.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>#include <afx.h></TT>
<TT>#include <iostream.h></TT>
<TT>#include "MyObj.h"</TT>
<TT>int main()</TT>
<TT>{</TT>
<TT> CRuntimeClass* pRuntime = RUNTIME_CLASS( CMyObject );</TT>
<TT> CObject* pObj = pRuntime->CreateObject();</TT>
<TT> ASSERT( pObj->IsKindOf(RUNTIME_CLASS(CMyObject)) );</TT>
<TT> CMyObject* pFoo = (CMyObject*)pObj;</TT>
<TT> pFoo->Set( "FooBar" );</TT>
<TT> cout << pFoo->Get() << endl;</TT>
<TT> delete pFoo;</TT>
<TT> return 0;</TT>
</FONT></PRE>
<P><TT>}</TT> Save the contents of Listing 8.9 as <TT>Runtime.cpp</TT> and add the
file to the Runtime project. Compile the project and if there are no errors, run
the project in a DOS window by following these steps:
<DL>
<DD>1. Open a DOS window from the Start button's Programs menu.<BR>
<BR>
2. Change the current directory to the project directory.<BR>
<BR>
3. Type <TT>Debug\Runtime</TT> in the DOS window. The program executes and outputs
<TT>FooBar</TT>.
</DL>
<P>Leave the DOS window open for now because you use it for the next example.
<H4><FONT COLOR="#000077">Testing for a Valid Object</FONT></H4>
<P>The MFC class library offers several diagnostic features. Most of these features
are in the form of macros that are used only in a debug version of your program.
This gives you the best of both worlds. When you are developing and testing your
program, you can use the MFC diagnostic functions to help ensure that your program
has as few errors as possible, although it runs with the additional overhead required
by the diagnostics. Later, when your program is compiled in a release version, the
diagnostic checks are removed and your program executes at top speed.</P>
<P>Three macros are commonly used in an MFC program:
<UL>
<LI><TT>ASSERT</TT> brings up an error message dialog box when an expression that
evaluates to <TT>FALSE</TT> is passed to it. This macro is compiled only in debug
builds.<BR>
<BR>
<LI><TT>VERIFY</TT> works exactly like <TT>ASSERT</TT> except that the evaluated
expression is always compiled, even for non-debug builds, although the expression
is not tested in release builds.<BR>
<BR>
<LI><TT>ASSERT_VALID</TT> tests a pointer to a <TT>CObject</TT> instance and verifies
that the object is a valid pointer in a valid state. A class derived from <TT>CObject</TT>
can override the <TT>AssertValid</TT> function to enable testing of the state of
an object.
</UL>
<P>The <TT>ASSERT</TT> and <TT>VERIFY</TT> macros are used with all expressions,
not just those involving <TT>CObject</TT>. Although they both test to make sure that
the evaluated expression is <TT>TRUE</TT>, there is an important difference in the
way these two macros work. When compiled for a release build, the <TT>ASSERT</TT>
macro and the expression it evaluates are completely ignored during compilation.
The <TT>VERIFY</TT> macro is also ignored, but the expression is compiled and used
in the release build.
<BLOCKQUOTE>
<P>
<HR>
<B> </B><FONT COLOR="#000077"><B>CAUTION:</B></FONT><B> </B>A common source of errors
in MFC programs is placing important code inside an <TT>ASSERT</TT> macro instead
of a <TT>VERIFY</TT> macro. If the expression is needed for the program to work correctly,
it belongs in a <TT>VERIFY</TT> macro, not an <TT>ASSERT</TT> macro. These functions
are used in examples throughout the rest of the book to test for error conditions.
<HR>
</BLOCKQUOTE>
<H4><FONT COLOR="#000077">Providing a Dump Function</FONT></H4>
<P>In addition to the diagnostic functions and macros in the previous section, <TT>CObject</TT>
declares a virtual function for displaying the contents of an object at runtime.
This function, <TT>Dump</TT>, is used to send messages about the current state of
the object to a debug window.</P>
<P>If you are debugging an MFC program, the messages are displayed in an output window
of the debugger. Add the source code from Listing 8.10 to the <TT>CMyObject</TT>
class declaration. The <TT>Dump</TT> function is usually placed in the implementation
section of the class declaration; in this example, it should be placed after the
declaration for <TT>m_szName</TT>. Because <TT>Dump</TT> is called only by the MFC
framework, it is usually declared as <TT>protected</TT> or <TT>private</TT>. Because
the <TT>Dump</TT> function is called only for debug builds, the declaration is surrounded
by <TT>#ifdef</TT> and <TT>#endif</TT> statements that remove the declaration for
<TT>Dump</TT> for release builds.
<H4><FONT COLOR="#000077">TYPE: Listing 8.10. Adding a Dump function to the CMyObject
declaration.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>#ifdef _DEBUG</TT>
<TT> void Dump( CDumpContext& dc ) const;</TT>
</FONT></PRE>
<P><TT>#endif</TT> Add the source code from Listing 8.11 to the <TT>MyObj.cpp</TT>
source code file. The implementation of the function is also bracketed by <TT>#ifdef</TT>
and <TT>#endif</TT> statements to remove the function for release builds.
<H4><FONT COLOR="#000077">TYPE: Listing 8.11. Adding the implementation of Dump to
CMyObject.</FONT></H4>
<PRE><FONT COLOR="#0066FF"><TT>#ifdef _DEBUG</TT>
<TT>void CMyObject::Dump( CDumpContext& dc ) const</TT>
<TT>{</TT>
<TT> CObject::Dump( dc );</TT>
<TT> dc << m_szName;</TT>
<TT>}</TT>
</FONT></PRE>
<P><TT>#endif</TT> The <TT>Dump</TT> function in Listing 8.11 calls the base class
version of <TT>Dump</TT> first. This step is recommended to get a consistent output
in the debug window. After calling <TT>CObject::Dump</TT>, member data contained
in the class is sent to the dump context using the insertion operator, <TT><<</TT>,
just as if the data was sent to <TT>cout</TT>.
<H2><FONT COLOR="#000077"><B>Summary</B></FONT></H2>
<P>In this hour, you looked at how messages are handled by a program written for
Windows, and you wrote a sample program that handles and displays some commonly used
mouse event messages. You also looked at the <TT>CObject</TT> and <TT>CWnd</TT> base
classes and learned how to add diagnostic features to your classes.
<H2><FONT COLOR="#000077"><B>Q&A</B></FONT></H2>
<DL>
<DD><B>Q I want to have runtime class identification support for my class, and I
also want to be able to create objects dynamically. I tried using the <TT>DECLARE_DYNAMIC</TT>
and <TT>DECLARE_DYNCREATE</TT> macros together in my header file and the <TT>IMPLEMENT_DYNAMIC</TT>
and <TT>IMPLEMENT_DYNCREATE</TT> macros in my source file, but I got lots of errors.
What happened?</B><BR>
<BR>
<B>A</B> The macros are cumulative; The <TT>xxx_DYNCREATE</TT> macros also include
work done by the <TT>xxx_DYNAMIC</TT> macros. The <TT>xxx_SERIAL</TT> macros also
include <TT>xxx_DYNCREATE</TT>. You must use only one set of macros for your application.<BR>
<BR>
<B>Q Why does the MouseTst program go to the trouble of invalidating part of the
view, then updating the window in <TT>OnDraw</TT>? Wouldn't it be easier to just
draw directly on the screen when a mouse click is received?</B><BR>
<BR>
<B>A</B> When the MouseTst window is overlapped by another window then uncovered,
the view must redraw itself; this code will be located in <TT>OnDraw</TT>. It's much
easier to use this code in the general case to update the display rather than try
to draw the output in multiple places in the source code.
</DL>
<H2><FONT COLOR="#000077"><B>Workshop</B></FONT></H2>
<P>The Workshop is designed to help you anticipate possible questions, review what
you've learned, and begin thinking ahead to putting your knowledge into practice.
The answers to the quiz are in Appendix B, "Quiz Answers."
<H3><FONT COLOR="#000077"><B>Quiz</B></FONT></H3>
<DL>
<DD>1. What is the default window procedure?<BR>
<BR>
2. Why are messages used to pass information in Windows programs?<BR>
<BR>
3. How is an application notified that the mouse is passing over one of its windows?<BR>
<BR>
4. What is a message map used for?<BR>
<BR>
5. What is the base class for most MFC classes?<BR>
<BR>
6. What is the <TT>CObject::Dump</TT> function used for?<BR>
<BR>
7. What is the difference between the <TT>ASSERT</TT> and <TT>VERIFY</TT> macros?<BR>
<BR>
8. What message is sent to an application when the user presses the primary mouse
button?<BR>
<BR>
9. How can you determine which source code lines in a message map are reserved for
use by ClassWizard?
</DL>
<H3><FONT COLOR="#000077"><B>Exercises</B></FONT></H3>
<DL>
<DD>1. Modify the MouseTst program to display the current mouse position as the mouse
is moved over the view.<BR>
<BR>
2. Add an <TT>ASSERT</TT> macro to ensure that <TT>pObj</TT> is not <TT>NULL</TT>
after it is created in <TT>Runtime.cpp</TT>.<FONT COLOR="#000077"></FONT>
</DL>
<CENTER>
<P>
<HR>
<A HREF="ch07.htm" tppabs="http://www.mcp.com/824169600/0-672/0-672-31242-5/ch07/ch07.htm"><IMG SRC="previous.gif" tppabs="http://www.mcp.com/824169600/0-672/0-672-31242-5/button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="ch09.htm" tppabs="http://www.mcp.com/824169600/0-672/0-672-31242-5/ch09/ch09.htm"><IMG
SRC="next.gif" tppabs="http://www.mcp.com/824169600/0-672/0-672-31242-5/button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"
BORDER="0"></A><A HREF="index-1.htm" tppabs="http://www.mcp.com/824169600/0-672/0-672-31242-5/index.htm"><IMG SRC="contents.gif" tppabs="http://www.mcp.com/824169600/0-672/0-672-31242-5/button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> <BR>
<BR>
<BR>
<IMG SRC="corp.gif" tppabs="http://www.mcp.com/824169600/0-672/0-672-31242-5/button/corp.gif" WIDTH="284" HEIGHT="45" ALIGN="BOTTOM" ALT="Macmillan Computer Publishing USA"
BORDER="0"></P>
<P>© <A HREF="copy.htm" tppabs="http://www.mcp.com/824169600/0-672/0-672-31242-5/copy.htm">Copyright</A>, Macmillan Computer Publishing. All
rights reserved.
</CENTER>
</BODY>
</HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -