?? ch15.htm
字號(hào):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
<!--
function popUp(pPage) {
var fullURL = document.location;
var textURL = fullURL.toString();
var URLlen = textURL.length;
var lenMinusPage = textURL.lastIndexOf("/");
lenMinusPage += 1;
var fullPath = textURL.substring(0,lenMinusPage);
popUpWin = window.open('','popWin','resizable=yes,scrollbars=no,width=525,height=394');
figDoc= popUpWin.document;
zhtm= '<HTML><HEAD><TITLE>' + pPage + '</TITLE>';
zhtm += '<link rel="stylesheet" href="/includes/stylesheets/ebooks.css"></head>';
zhtm += '<BODY bgcolor="#FFFFFF">';
zhtm += '<IMG SRC="' + fullPath + pPage + '">';
zhtm += '<P><B>' + pPage + '</B>';
zhtm += '</BODY></HTML>';
window.popUpWin.document.write(zhtm);
window.popUpWin.document.close();
// Johnny Jackson 4/28/98
}
//-->
</SCRIPT>
<link rel="stylesheet" href="/includes/stylesheets/ebooks.css">
<TITLE>Special Edition Using Visual C++ 6 -- Ch 15 -- Building an ActiveX Server Application</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF">
<CENTER>
<H1><IMG SRC="../button/que.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM" BORDER="0"><BR>
Special Edition Using Visual C++ 6</H1>
</CENTER>
<CENTER>
<P><A HREF="../ch14/ch14.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch16/ch16.htm"><IMG
SRC="../button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"
BORDER="0"></A><A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A>
<HR>
</CENTER>
<CENTER>
<H1>- 15 -</H1>
<H1>Building an ActiveX Server Application</H1>
</CENTER>
<UL>
<LI><A HREF="#Heading1">Adding Server Capabilities to ShowString</A>
<UL>
<LI><A HREF="#Heading2">AppWizard's Server Boilerplate</A>
<LI><A HREF="#Heading3">Showing a String Again</A>
</UL>
<LI><A HREF="#Heading4">Applications That Are Both Container and Server</A>
<UL>
<LI><A HREF="#Heading5">Building Another Version of ShowString</A>
<LI><A HREF="#Heading6">Nesting and Recursion Issues</A>
</UL>
<LI><A HREF="#Heading7">Active Documents</A>
<UL>
<LI><A HREF="#Heading8">What Active Documents Do</A>
<LI><A HREF="#Heading9">Making ShowString an Active Document Server</A>
</UL>
</UL>
<P>
<HR SIZE="4">
<CENTER>
<H1></H1>
</CENTER>
<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>
<P>
<H2><A NAME="Heading1"></A>Adding Server Capabilities to ShowString</H2>
<P>Like Chapter 14, "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>
<H3><A NAME="Heading2"></A>AppWizard's Server Boilerplate</H3>
<P>Build the new ShowString in a different directory, making almost exactly the same
AppWizard choices as when you built versions of ShowString in Chapter 8, "Building
a Complete Application: ShowString," and Chapter 14. 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, initial status bar, printing and print preview, context sensitive
Help, and 3D controls. Finally, select source file comments and a shared DLL. Finish
AppWizard and, if you want, build the project.</P>
<BLOCKQUOTE>
<P>
<HR>
<strong>NOTE::</strong> 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 Ole in their names as well. Although 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 for awhile. 
<HR>
</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>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
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>
<P><A HREF="javascript:popUp('15uvc01.gif')"><B>FIG. 15.1</B></A><B> </B><I>AppWizard
adds another menu for editing in place.</I></P>
<P><A HREF="javascript:popUp('15uvc50.gif')"><B>FIG. 15.2</B></A><B> </B><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 File menus have different items: IDR_SHOWSTTYPE_SRVR_EMB
has Update in place of Save, and Save Copy As in place of Save As. 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. File, Update updates the embedded item; File,
Save Copy As doesn't save the whole document, just a copy of this embedded portion.</P>
<P><A HREF="javascript:popUp('15uvc02.gif')"><B>FIG. 15.3</B></A><B> </B><I>The embedded
menu has different items under File than the usual menu.</I></P>
<P><B><I>CShowStringApp</I>  </B>Another member variable has been added
to this class. It is declared in ShowString.h as:</P>
<P>
<PRE>COleTemplateServer m_server;
</PRE>
<P>COleTemplateServer 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>
<P>
<PRE>#include "IpFrame.h"
</PRE>
<P>This sets up the class CInPlaceFrame, discussed later in this chapter. Just before
InitInstance(), the lines shown in Listing 15.1 are added.</P>
<P>
<H4>Listing 15.1  Excerpt from ShowString.cpp--CLSID</H4>
<PRE>// This identifier was generated to be statistically unique for
// your app. You may change it if you prefer to choose a specific
// identifier.
// {0B1DEE40-C373-11CF-870C-00201801DDD6}
static const CLSID clsid =
{ 0xb1dee40, 0xc373, 0x11cf,
</PRE>
<PRE> { 0x87, 0xc, 0x0, 0x20, 0x18, 0x1, 0xdd, 0xd6 } };
</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, CShowStringApp::InitInstance()
has several changes from the non-ActiveX ShowString you developed in Chapter 8. The
code in Listing 15.2 initializes the ActiveX (OLE) libraries.</P>
<P>
<H4>Listing 15.2  Excerpt from ShowString.cpp--Initializing Libraries</H4>
<PRE> // Initialize OLE libraries
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
</PRE>
<PRE> }
</PRE>
<P>While still in CShowStringApp::InitInstance(), after the CMultiDocTemplate is
initialized but before the call to AddDocTemplate(), the following line is added
to register the menu used for in-place editing and for separate-window editing:</P>
<P>
<PRE>pDocTemplate->SetServerInfo(
IDR_SHOWSTTYPE_SRVR_EMB, IDR_SHOWSTTYPE_SRVR_IP,
RUNTIME_CLASS(CInPlaceFrame));
</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>
<P>
<PRE>// Connect the COleTemplateServer to the document template.
// The COleTemplateServer creates new documents on behalf
// of requesting OLE containers by using information
// specified in the document template.
m_server.ConnectTemplate(clsid, pDocTemplate, FALSE);
</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 /Embedding 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>
<H4>Listing 15.3  Excerpt from ShowString.cpp--Registering Running MDI
Apps</H4>
<PRE> // Register all OLE server factories as running. This enables the
// OLE libraries to create objects from other applications.
COleTemplateServer::RegisterAll();
// Note: MDI applications register all server objects without regard
</PRE>
<PRE> // to the /Embedding or /Automation on the command line.
</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>
<H4>Listing 15.4  Excerpt from ShowString.cpp--Checking How the App was
Launched</H4>
<PRE> // Check to see if launched as OLE server
if (cmdInfo.m_bRunEmbedded || cmdInfo.m_bRunAutomated)
{
// Application was run with /Embedding or /Automation.
// Don't show the main window in this case.
return TRUE;
</PRE>
<PRE> }
</PRE>
<P>If the application is being run standalone, execution continues with a registration
update:</P>
<P>
<PRE>// When a server application is launched standalone, it is a good idea
// to update the system Registry in case it has been damaged.
m_server.UpdateRegistry(OAT_INPLACE_SERVER);
</PRE>
<P>ActiveX information is stored in the Registry. (The Registry is discussed in Chapter
7, "Persistence and File I/O.") When a user chooses Insert, Object or Edit,
Insert Object, the Registry provides the list of object types that can be inserted.
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 standalone.</P>
<P><B><I>CShowStringDoc</I>  </B>The document class, CShowStringDoc, now
inherits from COleServerDoc rather than CDocument. As well, the following line is
added at the top of ShowStringdoc.cpp:</P>
<P>
<PRE>#include "SrvrItem.h"
</PRE>
<P>This header file describes the server item class, CShowStringSrvrItem, discussed
in the CShowStringSrvrItem subsection of this section. The constructor, CShowStringDoc::CShowStringDoc(),
has the following line added:</P>
<P>
<PRE> EnableCompoundFile();
</PRE>
<P>This turns on the use of compound files.</P>
<P>There is a new public function inlined in the header file so that other functions
can access the server item:</P>
<P>
<PRE>CShowStringSrvrItem* GetEmbeddedItem()
{ return (CShowStringSrvrItem*)COleServerDoc::GetEmbeddedItem(); }
</PRE>
<P>This calls the base class GetEmbeddedItem(), which in turn calls the virtual function
OnGetEmbeddedItem(). That function must be overridden in the ShowString document
class as shown in Listing 15.5.</P>
<P>
<H4>Listing 15.5  ShowStringDoc.cpp--CShowStringDoc::OnGetEmbeddedItem()</H4>
<PRE>COleServerItem* CShowStringDoc::OnGetEmbeddedItem()
{
// OnGetEmbeddedItem is called by the framework to get the
// COleServerItem that is associated with the document.
// It is only called when necessary.
CShowStringSrvrItem* pItem = new CShowStringSrvrItem(this);
ASSERT_VALID(pItem);
return pItem;
</PRE>
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -