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

📄 ch17.htm

📁 VC 21天 学习VC 的好东西
💻 HTM
📖 第 1 页 / 共 4 页
字号:
file and remove the include from this file. Because you are not creating any instances
of the drawing class, the application file doesn't need to know about anything in
the DLL.</P>
<P>Once you make all those changes, open the header file for the document class.
Edit the document class declaration: Change the function type of the GetDrawing function
to return a pointer to an object array, remove the drawing class variable, and add
an object array variable, as in Listing 17.12. Make only these three changes; do
not change anything else in the class declaration.</P>
<P>
<H4>LISTING 17.12. THE CTestAppDoc CLASS DECLARATION.</H4>
<PRE>1:  class CTestAppDoc : public CDocument
2:  {
3:  protected: // create from serialization only
4:      CTestAppDoc();
5:      DECLARE_DYNCREATE(CTestAppDoc)
6:  .
7:  .
8:  .
9:  // Implementation
10: public:
11:     CObArray* GetDrawing();
12:     virtual ~CTestAppDoc();
13: .
14: .
15: .
16: private:
17:     CObArray m_oaLines;
18: };
</PRE>

<DL>
	<DT><B>Modifying the Document Functions</B></DT>
</DL>

<P>Now that you've made the general changes to the test application, it's time to
start making the functionality changes. All the calls to a class method of the drawing
object must be changed to the appropriate function call in the new DLL.</P>

<P>The changes necessary in the OnNewDocument function consist of dropping the function
call to pass the CRect to the drawing object and replacing the NewDocument function
call with the new DLL function--in this instance, ModArtNewDrawing, as shown in line
19 in Listing 17.13.</P>
<P>
<H4>LISTING 17.13. THE CTestAppDoc OnNewDocument FUNCTION.</H4>
<PRE>1:  BOOL CTestAppDoc::OnNewDocument()
2:  {
3:      if (!CDocument::OnNewDocument())
4:          return FALSE;
5:
6:      // TODO: add reinitialization code here
7:      // (SDI documents will reuse this document)
8:
9:      // Get the position of the view
10:     POSITION pos = GetFirstViewPosition();
11:     // Did we get a valid position?
12:     if (pos != NULL)
13:     {
14:         // Get a pointer to the view
15:         CView* pView = GetNextView(pos);
16:         RECT lWndRect;
17:         // Get the display area rectangle
18:         pView-&gt;GetClientRect(&amp;lWndRect);
19:         // Create a new drawing
20:         ModArtNewDrawing(lWndRect, &amp;m_oaLines);
21:     }
22:
23:     return TRUE;
24: }
</PRE>
<P>In the Serialize function, change the drawing object Serialize function call to
the new DLL serialization function--in this case, ModArtSerialize, as in Listing
17.14.</P>
<P>
<H4>LISTING 17.14. THE CTestAppDoc Serialize FUNCTION.</H4>
<PRE>1: void CTestAppDoc::Serialize(CArchive&amp; ar)
2: {
3:     // Serialize the drawing
4:     ModArtSerialize(ar, &amp;m_oaLines);
5: }
</PRE>
<P>For the DeleteContents function, you need to change the call to the ClearDrawing
function to the new DLL function, ModArtClearDrawing, as in line 5 of Listing 17.15.</P>
<P>
<H4>LISTING 17.15. THE CTestAppDoc DeleteContents FUNCTION.</H4>
<PRE>1: void CTestAppDoc::DeleteContents()
2: {
3:     // TODO: Add your specialized code here and/or call the base class
4:     // Delete the drawing
5:     ModArtClearDrawing(&amp;m_oaLines);
6:
7:     CDocument::DeleteContents();
8: }
</PRE>
<P>Finally, for the GetDrawing function, you need to change the function declaration
to designate that it's returning a pointer to an object array, just as you did in
the header file. Next, you need to change the variable that is being returned to
the object array variable that you added to the header file, as in Listing 17.16.</P>
<P>
<H4>LISTING 17.16. THE CTestAppDoc GetDrawing FUNCTION.</H4>
<PRE>1: CObArray* CTestAppDoc::GetDrawing()
2: {
3:     // Return the drawing object
4:     return &amp;m_oaLines;
5: }
</PRE>
<H4>Modifying the View Functions</H4>
<P>Switching to the view class, there's only one simple change to make to the OnDraw
function. In this function, you need to change the type of pointer retrieved from
the GetDrawing function from a drawing object to an object array object, as in line
9 of Listing 17.17. Next, call the DLL function, ModArtDraw, to perform the drawing
on the window, as shown in line 11.</P>
<P>
<H4>LISTING 17.17. THE CTestAppView OnDraw FUNCTION.</H4>
<PRE>1:  void CTestAppView::OnDraw(CDC* pDC)
2:  {
3:      CModTestAppDoc* pDoc = GetDocument();
4:      ASSERT_VALID(pDoc);
5:
6:      // TODO: add draw code for native data here
7:
8:      // Get the drawing object
9:      CObArray* m_oaLines = pDoc-&gt;GetDrawing();
10:     // Draw the drawing
11:     ModArtDraw(pDC, m_oaLines);
12: }
</PRE>
<P>After making all these changes to the test application, you are ready to compile
and test it. You should find that the application is working just as it did with
the previous DLL. You can also play around with it, going back and changing the DLL,
copying the new DLL into the debug directory for the test application, and seeing
how the changes are reflected in the behavior of the test application.</P>


<BLOCKQUOTE>
	<P>
<HR>
<STRONG>CAUTION:</STRONG> The particular example of a regular DLL that you developed in
	this exercise is still not usable by other programming languages. The reason is that
	you are passing MFC classes as the arguments for each of the DLL's functions. This
	still limits the usage to other applications that are built using MFC. To make this
	DLL truly portable, you need to pass the bare-bones structures instead of the classes
	(such as the RECT structure instead of the CRect class) and then convert the structures
	to the classes inside the DLL.
<HR>


</BLOCKQUOTE>

<H2><A NAME="Heading11"></A>Summary</H2>
<P>Today you learned about two more ways that you can package your functionality
for other programmers. You learned how you can easily package your classes as an
MFC extension DLL and how easily it can be used by a Visual C++ application. You
saw how you can make changes to the DLL without having to recompile the applications
that use it. You also learned what's involved in creating a regular DLL that can
be used with other, non-Visual C++ applications. You saw how you needed to convert
the exported classes from the DLL into standard C-style functions and what's involved
in adapting an application to use this style of DLL.</P>
<P>
<H2><A NAME="Heading12"></A>Q&amp;A</H2>

<DL>
	<DT></DT>
	<DD><B>Q How can I convert the regular DLL so that it can be used by non-Visual C++
	applications?</B>
	<P>
	<DT><B></B></DT>
	<DD><B>A</B> First, you have to make all the arguments to the functions use the bare-bones
	structures, instead of the MFC classes. For instance, to convert the ModArtNewDrawing
	function, change it to receive the RECT structure instead of the CRect class and
	also to receive a generic pointer instead of a pointer to an object array. You have
	to make the conversions to the appropriate classes in the DLL, as in lines 4 through
	9 in Listing 17.18.
	<P>
</DL>

<H4>LISTING 17.18. THE ModArtNewDrawing FUNCTION.</H4>
<PRE>1:  extern &quot;C&quot; void PASCAL EXPORT ModArtNewDrawing(RECT spRect, 
        &Acirc;LPVOID lpoaLines)
2:  {
3:      AFX_MANAGE_STATE(AfxGetStaticModuleState());
4:      CRect pRect;
5:      pRect.top = spRect.top;
6:      pRect.left = spRect.left;
7:      pRect.right = spRect.right;
8:      pRect.bottom = spRect.bottom;
9:      CObArray* poaLines = (CObArray*)lpoaLines;
10:     // Normal function body here
11:     int m_lNumLines;
12:     int m_lCurLine;
13:
14:     // Initialize the random number generator
15:     srand((unsigned)time(NULL));
16:     // Determine how many lines to create
17:     m_lNumLines = rand() % 50;
18:     // Are there any lines to create?
19:     if (m_lNumLines &gt; 0)
20:     {
21:         // Loop through the number of lines
22:         for (m_lCurLine = 0; m_lCurLine &lt; m_lNumLines; m_lCurLine++)
23:         {
24:             // Create the new line
25:             NewLine(pRect, poaLines);
26:         }
27:     }
28: }
</PRE>

<DL>
	<DT></DT>
	<DD>You also have to add functions to create and destroy the object array, with the
	application storing the object array as a generic pointer as in Listing 17.19.
	<P>
</DL>

<H4>LISTING 17.19. THE ModArtInit FUNCTION.</H4>
<PRE>1: extern &quot;C&quot; LPVOID PASCAL EXPORT ModArtInit()
2: {
3:     AFX_MANAGE_STATE(AfxGetStaticModuleState());
4:     // Create the object array
5:     return (LPVOID)new CObArray;
6: }
</PRE>

<DL>
	<DT></DT>
	<DD><B>Q When do I need to recompile the applications that use my DLLs?</B>
	<P>
	<DT><B></B></DT>
	<DD><B>A</B> Whenever you change any of the exported function calls. Changing, adding,
	or removing arguments to any of these functions would mean recompiling the applications
	that use the DLL. If you are working with an MFC extension DLL, the applications
	that use the DLL need to be recompiled if the public interface for the exported classes
	change or a new function or variable is added or removed. It doesn't matter if the
	application isn't using any of the functions that were changed; it's still good practice
	to recompile the applications, just to be sure.
	<P>
</DL>

<H2><A NAME="Heading13"></A>Workshop</H2>
<P>The Workshop provides quiz questions to help you solidify your understanding of
the material covered and exercises to provide you with experience in using what you've
learned. The answers to the quiz questions and exercises are provided in Appendix
B, &quot;Answers.&quot;</P>
<P>
<H3><A NAME="Heading14"></A>Quiz</H3>

<DL>
	<DT></DT>
	<DD><B>1. </B>What kind of DLL do you have to create to make classes in the DLL available
	to applications?
	<P>
	<DT></DT>
	<DD><B>2. </B>What do you have to add to the class to export it from a DLL?
	<P>
	<DT></DT>
	<DD><B>3. </B>What kind of DLL can be used with other programming languages?
	<P>
	<DT></DT>
	<DD><B>4. </B>If you make changes in a DLL, do you have to recompile the applications
	that use the DLL?
	<P>
	<DT></DT>
	<DD><B>5. </B>What function does the LIB file provide for a DLL?
	<P>
</DL>

<H3><A NAME="Heading15"></A>Exercises</H3>

<DL>
	<DT></DT>
	<DD><B>1. </B>Separate the line class into its own MFC extension DLL and use it with
	the second (regular) DLL.
	<P>
	<DT></DT>
	<DD><B>2. </B>Alter the line class DLL so that it uses a consistent line width for
	all lines.
</DL>

<H1></H1>
<CENTER

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -