📄 ch15.htm
字号:
<HTML>
<HEAD>
<TITLE>Special Edition Using Visual C++ 5 - Chapter 15</TITLE>
<LINK REL="Next" HREF="ch16.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch16.htm">
<LINK REL="Previous" HREF="ch14.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch14.htm"></HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H2><B>Chapter 15</B></H2>
<H2><B>Building an ActiveX Server Application</B></H2>
<hr>
<P>Just as AppWizard builds ActiveX containers, it also builds ActiveX servers. However, unlike containers, the AppWizard code is complete, so there isn't much work to do for improving the AppWizard code. This chapter builds a version of ShowString that
is only a server and discusses how to build another version that is both a container and a server. You also learn about ActiveX documents and how they can be used in other applications.</P>
<ul>
<li><B>Transforming ShowString into a Server</B></P>
<P> An ActiveX server can supply its documents to ActiveX container applications like the one in the previous chapter. This section shows you how to build one and how they work.</P>
<li><B>Container and Server Applications</B></P>
<P> An application can be both a container and a server at the same time. This section discusses the implications of nested objects.</P>
<li><B>ActiveX Documents</B></P>
<P> ActiveX document objects take being an ActiveX server one step further. This section explains what an ActiveX document object is, how to make one, and gives you a peek at what Windows will become.</P>
</ul>
<H3><B>Adding Server Capabilities to ShowString</B></H3>
<P>Like <A HREF="index14.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index14.htm" target="text">Chapter 14</A>, "Building an ActiveX Container Application," this chapter starts by building an ordinary server application with AppWizard and then adds the functionality that makes it ShowString. This
is far quicker than adding ActiveX functionality to ShowString, because ShowString doesn't have much code and can be written quickly.</P>
<P><B> AppWizard's Server Boilerplate</B></P>
<P>Build the new ShowString in a different directory, making almost exactly the same AppWizard choices as when you built versions of ShowString in <A HREF="index09.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index09.htm" target="text">Chapter 9</A>, "Building a Complete Application: ShowString,"
and <A HREF="index14.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index14.htm" target="text">Chapter 14</A>, "Building an ActiveX Container Application." Call it ShowString, and choose an MDI application with no database support. In AppWizard's Step 3, select full server as your compound document
support. This enables the check box for ActiveX document support. Leave this deselected for now. Later in this chapter you see the consequences of selecting this option. Continue 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, the AppWizard dialog boxes refer to compound document support. Many of the class names that are used throughout this chapter have <font color="#008000">Ole</font> in their names as well. 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 many differences between the application you have just generated and a do-nothing application without ActiveX server support. These differences are explained in the next few sections.</P>
<P><B>Menus</B></P>
<P>There are two new menus in an ActiveX server application. The first, called IDR_SHOWSTTYPE_SRVR_IP, is shown in Figure 15.1. When an item is being edited in place, the container in-place menu (called IDR_SHOWSTTYPE_CNTR_IP<font color="#008000">
</font>in the container version of ShoeString) is combined with the server in-place menu, IDR_SHOWSTTYPE_SRVR_IP, to build the in-place menu as shown in Figure 15.2. The double separators in each partial menu show where the menus are joined.</P>
<A HREF="Qfigs01.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch15/Qfigs01.gif"><b>Fig. 15.1</b></A>
<P><I>AppWizard adds another menu for editing in place.</I></P>
<A HREF="Qfigs02.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch15/Qfigs02.gif"><b>Fig. 15.2</b></A>
<P><I>The container and server in-place menus are interlaced during in place editing.</I></P>
<P>The second new menu is IDR_SHOWSTTYPE_SRVR_EMB, used when an embedded item is being edited in a separate window. Figure 15.3 shows this new menu next to the more familiar IDR_SHOWSTTYPE menu, which is used when ShowString is acting not as a server but
as an ordinary application. The <U>F</U>ile menus have different items: IDR_SHOWSTTYPE_SRVR_EMB has <U>U</U>pdate in place of <U>S</U>ave, and Save Copy <U>A</U>s in place of Save <U>A</U>s. This is because the item the user is working on in the separate
window is not a document of its own, but is embedded in another document. <U>F</U>ile, <U>U</U>pdate updates the embedded item; <U>F</U>ile, Save Copy <U>A</U>s does not save the whole document, just a copy of this embedded portion.</P>
<A HREF="Qfigs03.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch15/Qfigs03.gif"><b>Fig. 15.3</b></A>
<P><I>The embedded menu has different items under </I><I><U>F</U></I><I>ile than the usual menu.</I></P>
<P><I>CShowStringApp</I></P>
<P>Another member variable has been added to this class. It is declared in showstring.h as:</P>
<pre><font color="#008000">COleTemplateServer m_server;</font></pre>
<p><font color="#008000">COleTemplateServer</font> handles the majority of the work involved in connecting documents to code, as you will see.</P>
<P>The following line is added at the top of showstring.cpp:</P>
<pre><font color="#008000">#include "IpFrame.h"</font></pre>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P>This sets up the class <font color="#008000">CInPlaceFrame</font>, discussed later in this chapter. Just before <font color="#008000">InitInstance()</font>, the lines shown in Listing 15.1 are added:</P>
<P><I>Listing 15.1—excerpt from ShowString.cpp—</I><I><font color="#008000">CLSID</font></I></P>
<pre><font color="#008000">// This identifier was generated to be statistically unique for </font></pre>
<pre><font color="#008000">// your app. You may change it if you prefer to choose a specific </font></pre>
<pre><font color="#008000">// identifier.</font></pre>
<pre><font color="#008000">// {0B1DEE40-C373-11CF-870C-00201801DDD6}</font></pre>
<pre><font color="#008000">static const CLSID clsid =</font></pre>
<pre><font color="#008000">{ 0xb1dee40, 0xc373, 0x11cf, </font></pre>
<pre><font color="#008000"> { 0x87, 0xc, 0x0, 0x20, 0x18, 0x1, 0xdd, 0xd6 } };</font></pre>
<P>The numbers will be different in your code. This Class ID identifies your server application and document type. Applications that support several kinds of documents (for example, text and graphics) use a different CLSID for each type of document.</P>
<P>As it did for the OLE container version of ShowString, <font color="#008000">CShowStringApp::InitInstance()</font> has several changes from the non-ActiveX ShowString you developed in <A HREF="index09.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index09.htm" target="text">Chapter 9</A>, “Building a
Complete Application: ShowString.” The code in Listing 15.2 initializes the ActiveX (OLE) libraries:</P>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P><I>Listing 15.2—excerpt from ShowString.cpp—</I><I><font color="#008000">Initializing Libraries</font></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>While still in <font color="#008000">CShowStringApp::InitInstance()</font>, after the <font color="#008000">MultiDocTemplate</font> is initialized, but before the call to <font color="#008000">AddDocTemplate()</font>, the following line is added to
register the menu used for in-place editing and for separate-window editing:</P>
<pre><font color="#008000">pDocTemplate->SetServerInfo(</font></pre>
<pre><font color="#008000"> IDR_SHOWSTTYPE_SRVR_EMB, IDR_SHOWSTTYPE_SRVR_IP,</font></pre>
<pre><font color="#008000"> RUNTIME_CLASS(CInPlaceFrame));</font></pre>
<P>A change that was not in the container version is connecting the template for the document to the class ID, like this:</P>
<pre><font color="#008000">// Connect the COleTemplateServer to the document template.</font></pre>
<pre><font color="#008000"> // The COleTemplateServer creates new documents on behalf</font></pre>
<pre><font color="#008000"> // of requesting OLE containers by using information</font></pre>
<pre><font color="#008000"> // specified in the document template.</font></pre>
<pre><font color="#008000"> m_server.ConnectTemplate(clsid, pDocTemplate, FALSE);</font></pre>
<P>Now when a user chooses Create New when inserting an object, the document used for that creation will be available.</P>
<P>When a server application is launched to edit an item in place or in a separate window, the system DLLs add <font color="#008000">/Embedded</font> to the invoking command line. But if the application is already running, and it is an MDI application, a
new copy is not launched. Instead, a new MDI window is opened in that application. That particular piece of magic is accomplished with one function call, as shown in Listing 15.3.</P>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P><I>Listing 15.3—excerpt from ShowString.cpp—</I><I><font color="#008000">Registering running MDI </font></I><I><font color="#008000">apps</font></I></P>
<pre><font color="#008000"> // Register all OLE server factories as running. This enables the</font></pre>
<pre><font color="#008000"> // OLE libraries to create objects from other applications.</font></pre>
<pre><font color="#008000"> COleTemplateServer::RegisterAll();</font></pre>
<pre><font color="#008000"> // Note: MDI applications register all server objects without regard</font></pre>
<pre><font color="#008000"> // to the /Embedding or /Automation on the command line.</font></pre>
<P>After parsing the command line, the AppWizard boilerplate code checks to see if this application is being launched as an embedded (or automation) application. If so, there is no need to continue with the initialization, so this function returns, as
shown in Listing 15.4.</P>
<p><img src="cd_rom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/cd_rom.gif" hspace=10>
<P><I>Listing 15.4—excerpt from ShowString.cpp—</I><I><font color="#008000">checking how the app was </font></I><I><font color="#008000">launched</font></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. </font></pre>
<pre><font color="#008000"> // Don't show the main window in this case.</font></pre>
<pre><font color="#008000"> return TRUE;</font></pre>
<pre><font color="#008000"> }</font></pre>
<P>If the application is being run stand-alone, execution continues with a registration update:</P>
<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_INPLACE_SERVER);</font></pre>
<P>ActiveX information is stored in the Registry. (The Registry is discussed in <A HREF="index08.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index08.htm" target="text">Chapter 8</A>, “Persistence and File I/O.”) When a user chooses <U>I</U>nsert, <U>O</U>bject or <U>E</U>dit, Insert Object, the
Registry provides the list of object types that can be inserted. So, before ShowString can appear in such a list, it must be registered. Many developers add code to their install programs to register their server applications, and MFC takes this one step
further, registering the application every time it is run. If the application files are moved or changed, the registration is automatically updated the next time the application is run stand-alone.</P>
<P> <I>CShowStringDoc</I></P>
<P>The document class, <font color="#008000">CShowStringDoc</font>, now inherits from <font color="#008000">COleServerDoc</font> rather than <font color="#008000">CDocument</font>. As well, the following line is added at the top of showstringdoc.cpp:</P>
<pre><font color="#008000">#include "SrvrItem.h"</font></pre>
<P>This header file describes the server item class, <font color="#008000">CShowStringSrvrItem</font>, discussed in the <font color="#008000">CShowStringSrvrItem</font> subsection of this section. The constructor, <font
color="#008000">CShowStringDoc::CShowStringDoc()</font>, has the following line added:</P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -