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

📄 ch16.htm

📁 VC使用大全。里面集合了VC使用的各种使用技巧。非常有用。
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<HTML>

<HEAD>

<TITLE>Special Edition Using Visual C++ 5 - Chapter 16</TITLE>

<LINK REL="Next" HREF="ch17.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch17.htm">

<LINK REL="Previous" HREF="ch15.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch15.htm"></HEAD>

<BODY BGCOLOR="#FFFFFF" TEXT="#000000">



<H2><B>Chapter 16</B></H2>

<H2><B>Building an Automation Server</B></H2>

<hr>

<P>Automation, fomerly called OLE Automation and then ActiveX Automation, is about writing code that other programs can call. Other programs call your code, not in the insulated manner of a DLL, but directly. The jargon is that your code <I>exposes</I> 
both <I>methods</I> (functions) and <I>properties</I> (variables) to other applications. The good part is that if your application is an automation server, you don't have to create a macro language for your application; you only have to make hooks for a 
more universal macro language, Visual Basic for Applications, to grab onto.</P>

<ul>

<li> <B>ShowString as an automation server</B></P>

<P>  An automation server is straightforward to build, as you'll see in this section.</P>

<li> <B>Visual Basic as an automation controller</B></P>

<P>  Once built, your automation server must be tested. You can use Visual Basic or DispTest (included with Visual C++) to test automation servers.</P>

<li> <B>Type libraries</B></P>

<P>  For those who want to know what's going on behind the scenes, this chapter introduces you to the ODL file and what it means.</P>

</ul>

<H3><B>Designing ShowString Again</B></H3>

<P>If you've been building the sample applications throughout this book, you can probably design ShowString in your sleep by now, but it's time to do it once again. This time, ShowString is not going to have a <U>T</U>ools, <U>O</U>ptions 
menu&#151;instead, other programs will directly set the string and other display options. The member variables in the document will be the same, and the code in <font color="#008000">OnDraw()</font> will be the same as in all the other implementations of 
ShowString.</P>

<P><B>AppWizard's Automation Boilerplate</B></P>

<P>To build the version of ShowString that is an automation server, first use AppWizard to create an empty shell. Run AppWizard as usual, but in a different directory from your other versions of ShowString. Make almost exactly the same AppWizard choices 
as before: call it ShowString and then choose an MDI application and no database support. In AppWizard's Step 4, choose No Compound Ddocument Support(the radio buttons at the top of the dialog box) but turn on support for Automation. Continue through the 
AppWizard process, selecting a docking toolbar, status bar, printing and print preview, context-sensitive Help, and 3-D controls. Finally, select source file comments and a shared DLL.</P>

<blockquote><p><img src="note.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/note.gif">

<P>Even though the technology is now called ActiveX, and ActiveX Automation is starting to be known simply as Automation, the AppWizard dialog boxes refer to Compound Document Support. As well, many of the class names that are used throughout this chapter 
have <font color="#008000">Ole</font> in their names, and comments refer to OLE. While Microsoft has changed the name of the technology, it has not propagated that change throughout Visual C++ yet. You will have to live with these contradictions until the 
next release of Visual C++.</P>

<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>

<P>There are just a few differences in this application from the do-nothing application without Automation support, primarily in the application object and the document.</P>

<P><B><I>CShowStringApp</I></B></P>

<P>The application object, CShowStringApp, has a number of changes. In the source file, just before <font color="#008000">InitInstance()</font>, the code shown in Listing 16.1 has been added:</P>

<p><i>Listing 16.1&#151;ShowString.cpp&#151;CLSID</i></p>

<pre><font color="#008000">// This identifier was generated to be statistically unique for your app.</font></pre>

<pre><font color="#008000">// You may change it if you prefer to choose a specific identifier.</font></pre>

<pre><font color="#008000">// {61C76C05-70EA-11D0-9AFF-0080C81A397C}</font></pre>

<pre><font color="#008000">static const CLSID clsid =</font></pre>

<pre><font color="#008000">{ 0x61c76c05, 0x70ea, 0x11d0, { 0x9a, 0xff, 0x0, 0x80, 0xc8, </font></pre>

<pre><font color="#008000">    0x1a, 0x39, 0x7c } };</font></pre>

<P>The numbers will be different in your code. This class ID identifies your automation application.</P>

<p><font color="#008000">CShowStringApp::InitInstance()</font> has several changes. The lines of code in Listing 16.2 initialize the ActiveX (OLE) libraries.</P>

<P><I>Listing 16.2&#151;ShowString.cpp&#151;Initializing Libraries</I></P>

<pre><font color="#008000">     // Initialize OLE libraries</font></pre>

<pre><font color="#008000">     if (!AfxOleInit())</font></pre>

<pre><font color="#008000">     {</font></pre>

<pre><font color="#008000">          AfxMessageBox(IDP_OLE_INIT_FAILED);</font></pre>

<pre><font color="#008000">          return FALSE;</font></pre>

<pre><font color="#008000">     }</font></pre>

<P>As with the server application, <font color="#008000">InitInstance()</font> goes on to connect the document template to the <font color="#008000">COleTemplateServer</font>, after the document template has been initialized:</P>

<pre><font color="#008000">     m_server.ConnectTemplate(clsid, pDocTemplate, FALSE);</font></pre>

<P>Then <font color="#008000">InitInstance()</font> checks to see if the server is being launched to edit an embedded object or as an automation server; if so, there is no need to display the main window, so the function returns early, as shown in Listing 
16.3.</P>

<P><I>Listing 16.3&#151;ShowString.cpp&#151;How the app was launched</I></P>

<pre><font color="#008000">     // Check to see if launched as OLE server</font></pre>

<pre><font color="#008000">     if (cmdInfo.m_bRunEmbedded || cmdInfo.m_bRunAutomated)</font></pre>

<pre><font color="#008000">     {</font></pre>

<pre><font color="#008000">          // Application was run with /Embedding or /Automation.  Don't show the</font></pre>

<pre><font color="#008000">          //  main window in this case.</font></pre>

<pre><font color="#008000">          return TRUE;</font></pre>

<pre><font color="#008000">     }</font></pre>

<pre><font color="#008000">     // When a server application is launched stand-alone, it is a good idea</font></pre>

<pre><font color="#008000">     //  to update the system registry in case it has been damaged.</font></pre>

<pre><font color="#008000">     m_server.UpdateRegistry(OAT_DISPATCH_OBJECT);</font></pre>

<pre><font color="#008000">     COleObjectFactory::UpdateRegistryAll();</font></pre>

<P>If ShowString is being run as a stand-alone application, the code in Listing 16.3 updates the Registry as discussed in <A HREF="index15.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index15.htm" target="text">Chapter 15</A>, &quot;Building an ActiveX Server Application.&quot;</P>

<P><B><I>CShowStringDoc</I></B></P>

<P>The document class, <font color="#008000">CShowStringDoc</font>, still inherits from <font color="#008000">CDocument</font> rather than from any OLE document class, but that's where the similarities to the old non-OLE <font 
color="#008000">CShowStringDoc</font> end. The first block of new code in ShowStringDoc.cpp is right after the message map and is shown in Listing 16.4</P>

<P><I>Listing 16.4&#151;ShowStringDoc.cpp&#151;Dispatch Map</I></P>

<pre><font color="#008000">BEGIN_DISPATCH_MAP(CShowStringDoc, CDocument)</font></pre>

<pre><font color="#008000">     //{{AFX_DISPATCH_MAP(CShowStringDoc)</font></pre>

<pre><font color="#008000">          // NOTE - the ClassWizard will add and remove mapping macros here.</font></pre>

<pre><font color="#008000">          //      DO NOT EDIT what you see in these blocks of generated code!</font></pre>

<pre><font color="#008000">     //}}AFX_DISPATCH_MAP</font></pre>

<pre><font color="#008000">END_DISPATCH_MAP()</font></pre>

<P>This is an empty <I>dispatch map</I>. A dispatch map is like a message map, in that it maps events in the real world into function calls within this C++ class. When you expose methods and properties of this document with ClassWizard, the dispatch map 
will be updated.</P>

<P>After the dispatch map is another unique identifier, the <font color="#008000">IID (interface </font><font color="#008000">identifier)</font>. As Listing 16.5 shows, the IID is added as a static member, like the <font color="#008000">CLSID</font>.</P>

<P><I>Listing 16.5&#151;ShowStringDoc.cpp&#151;IID</I></P>

<pre><font color="#008000">// Note: we add support for IID_IShowString to support typesafe binding</font></pre>

<pre><font color="#008000">//  from VBA.  This IID must match the GUID that is attached to the </font></pre>

<pre><font color="#008000">//  dispinterface in the .ODL file.</font></pre>

<pre><font color="#008000">// {61C76C07-70EA-11D0-9AFF-0080C81A397C}</font></pre>

<pre><font color="#008000">static const IID IID_IShowString =</font></pre>

<pre><font color="#008000">{ 0x61c76c07, 0x70ea, 0x11d0, { 0x9a, 0xff, 0x0, 0x80, </font></pre>

<pre><font color="#008000">    0xc8, 0x1a, 0x39, 0x7c } };</font></pre>

<P>Then the <I>interface map</I> looks like this:</P>

<pre><font color="#008000">BEGIN_INTERFACE_MAP(CShowStringDoc, CDocument)</font></pre>

<pre><font color="#008000">     INTERFACE_PART(CShowStringDoc, IID_IShowSt, Dispatch)</font></pre>

<pre><font color="#008000">END_INTERFACE_MAP()</font></pre>

<P>An interface map hides ActiveX functions like <font color="#008000">QueryInterface()</font> from you, the programmer, and, like a message map, allows you to think at a more abstract level. ShowString will not have multiple entries in the interface map, 
but many applications do. Entries in the interface map are managed for you by ClassWizard.</P>

<P>The document constructor has some setting up to do. The AppWizard code is in Listing 16.6.</P>

<P><I>Listing 16.6&#151;ShowStringDoc.cpp&#151;Constructor</I></P>

<pre><font color="#008000">CShowStringDoc::CShowStringDoc()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">     // TODO: add one-time construction code here</font></pre>

<pre><font color="#008000">     EnableAutomation();</font></pre>

<pre><font color="#008000">     AfxOleLockApp();</font></pre>

<pre><font color="#008000">}</font></pre>

<p><font color="#008000">EnableAutomation()</font> does just what its name suggests: it enables automation for this document. <font color="#008000">AfxOleLockApp()</font> is used to ensure that an application is not closed while one of its documents is 
still in use elsewhere. Imagine that a user has two applications open that use ShowString objects. When the first application is closed, ShowString should not be closed, because it is needed by the other application. ActiveX technology implements this by 
keeping a count, within the framework, of the number of active objects. <font color="#008000">AfxOleLockApp()</font> increases this count. If it is nonzero when the user tries to close an application, the application is hidden but not actually closed.</P>

<P>It shouldn't be surprising, then, to see the destructor for ShowString's document:</P>

<pre><font color="#008000">CShowStringDoc::~CShowStringDoc()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">     AfxOleUnlockApp();</font></pre>

<pre><font color="#008000">}</font></pre>

<p><font color="#008000">AfxOleUnlockApp()</font> decreases the count of active objects so that eventually, the application can be closed.</P>

<P><B>Properties to Expose</B></P>

<P>At this point, you have an automation server that does not expose any methods or properties. Also, the four member variables of the document that have been in all the previous versions of ShowString have not been added to this version. These member 
variables are the following:</P>

<ul>

<li> <font color="#008000">string</font>.The string to be shown</P>

<li> <font color="#008000">color</font>.0 for black, 1 for red, and 2 for green</P>

<li> <font color="#008000">horizcenter</font>.<font color="#008000">TRUE</font> if the string should be centered horizontally</P>

<li> <font color="#008000">vertcenter</font>.<font color="#008000">TRUE</font> if the string should be centered vertically</P>

</ul>

⌨️ 快捷键说明

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