📄 ch27.htm
字号:
Repository.
On the first page of the Object Repository is an icon you can select if you want
to create an Automation object. After selecting the Automation Object icon, you are
presented with a dialog, as shown in Figure 27.1.<BR>
<BR>
<A
NAME="Heading11"></A><A HREF="27ebu01.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/27/27ebu01.jpg">FIGURE 27.1.</A><FONT COLOR="#000077">
</FONT><I>Selecting the Automation object from the Object Repository.</I></P>
<P>You can fill in the fields of this dialog as you like, or you can put in the
following
default values:</P>
<PRE><FONT COLOR="#0066FF">Class Name: TMyDCOM
OLE Class Name: MyProj.MyDCom
Description: My DCOM Object
Instancing: Multiple Instance
</FONT></PRE>
<P>When you're done, BCB spits out two pages of code as shown in
Listing 27.1 and
Listing 27.2. As you can see, I have, for the sake of fidelity to the compiler's
output and contrary to habit, left in the mystifying series of dashes inserted by
the compiler.<BR>
<BR>
<A NAME="Heading12"></A><FONT
COLOR="#000077"><B>Listing 27.1. The header file produced
by the BCB OLE Automation Wizard.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">//--------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//--------------------------------------------------------------------------
#include <vcl\OleAuto.hpp>
#include <vcl\Classes.hpp>
//--------------------------------------------------------------------------
class TMyDCom : public
TAutoObject
{
private:
public:
__fastcall TMyDCom();
__automated:
};
//--------------------------------------------------------------------------
#endif
</FONT></PRE>
<P><A NAME="Heading13"></A><FONT COLOR="#000077"><B>Listing 27.2. The
main source
file produced by the OLE Automation Wizard.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">//--------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------
__fastcall TMyDCom::TMyDCom()
: TAutoObject()
{
}
//--------------------------------------------------------------------------
void __fastcall RegisterTMyDCom()
{
TAutoClassInfo AutoClassInfo;
AutoClassInfo.AutoClass = __classid(TMyDCom);
AutoClassInfo.ProgID = "MyProj.MyDCom";
AutoClassInfo.ClassID = "{FCB9F540-87FF-11D0-BCD7-0080C80CF1D2}";
AutoClassInfo.Description = "My
DCOM Object";
AutoClassInfo.Instancing = acMultiInstance;
Automation->RegisterClass(AutoClassInfo);
}
//--------------------------------------------------------------------------
#pragma startup RegisterTMyDCom
//---------------------------------------------------------------------------
</FONT></PRE>
<P>The <TT>RegisterTMyDCOM</TT> procedure is used to register your object with the
system--that is, to list it in the Registry. The details of this process
are described
in the section called "Registration Issues." For now, you need only take
note of the <TT>ClassID</TT> assigned to your object because you will need this ID
when you try to call the object from another machine, as described in
the next section.</P>
<P>The act of registering the object is not something you necessarily have to understand
because it will occur automatically whenever you run the client application of which
<TT>TMyDCOM</TT> is a part.
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The object will be registered repeatedly,
whenever you run the program, which ensures that you will find it easy to register
the object, while simultaneously requiring very
little overhead in terms of system
resources. If you move the application to a new location, you can register this change
with the system by running it once. This capability guarantees that the old items
associated with your CLSID will be erased,
and new items will be filled in their
place. Registering a class ID multiple times does not mean that you will end up with
multiple items in the Registry because each registration of a CLSID will overwrite
the previous registration. All OLE servers
worth their name provide this service.
For example, Word and Excel update the Registry each time they are run.
<HR>
</BLOCKQUOTE>
<P>Besides the registration procedure, the other key part of the code generated by
the Automation expert is the
class definition found at the top of the header:</P>
<PRE><FONT COLOR="#0066FF">class TMyDCom : public TAutoObject
{
private:
public:
__fastcall TMyDCom();
__automated:
};
</FONT></PRE>
<P>This code has two sections, one called
<TT>private</TT> and the other called <TT>automated</TT>.
In the __<TT>automated</TT> section, you can declare methods or properties that you
want to call across program or machine boundaries. In other words, any methods or
properties that you declare
in this space will automatically be marshaled for you
by the underlying <TT>IDispatch</TT> object encapsulated by <TT>TAutoObject</TT>.</P>
<P>Consider the following code fragments:</P>
<PRE><FONT COLOR="#0066FF">class TSimpleDCOM : public TAutoObject
{
private:
public:
virtual __fastcall TSimpleDCOM();
__automated:
AnsiString __fastcall GetName();
int __fastcall Square(int A);
};
AnsiString __fastcall TSimpleDCOM::GetName()
{
return "SimpleDCOM";
}
int __fastcall
TSimpleDCOM::Square(int A)
{
return A * A;
}
</FONT></PRE>
<P>This object has two methods: one that states the name of the object and one that
can square an integer. These two methods are declared in the <TT>automated</TT> section
of the object,
so they can be accessed from another program via another program.</P>
<P>The <TT>TSimpleDCOM</TT> object exports two methods that <TT>IDispatch</TT> will
automatically marshal for you across application or machine boundaries. You can go
on adding
methods to this object as you like. Any data that you want to add to the
object should go in the <TT>private</TT> section, and any methods or properties that
you don't want to export should also go in the <TT>private</TT> section. All methods
that you
want to call from inside another application should go in the <TT>automated</TT>
section. You should declare these exported methods as <TT>__fastcall</TT>.</P>
<P>Some limits to the marshaling will be done for you by <TT>IDispatch</TT>. In particular,
the following types are legal to use in the declarations for the methods or properties
in the <TT>automated</TT> section:</P>
<PRE><FONT COLOR="#0066FF">int,
float,
double,
Currency,
TDateTime,
AnsiString,
WordBool
Short
String
unsigned short
Variant
</FONT></PRE>
<P>The following types are illegal to use in the declarations for the methods or
properties in the <TT>automated</TT> section:</P>
<PRE><FONT COLOR="#0066FF">arrays
char *
void *
structs
</FONT></PRE>
<P>For additional
information, see the "Automating properties and methods"
section in the online help for the VCL.</P>
<P>The apparent limitations created by the lack of support from <TT>IDispatch</TT>
for custom types can be considerably mitigated by an
intelligent use of variant arrays.
These structures can be so helpful that I have added a section later in this chapter
called "Using Variant Arrays to Pass Data" to describe their use.</P>
<P>The complete source for a simple DCOM server is
shown in Listing 27.3 through
Listing 27.6. Notice that <TT>OleAuto</TT> is included in this project. This unit
is essential to OLE Automation programming with the VCL.<BR>
<BR>
<A NAME="Heading15"></A><FONT COLOR="#000077"><B>Listing 27.3. The
heading for the
SimpleObject file from the EasyDCOM project.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// SimpleObject.h
// EasyDCOM
// Copyright (c) 1997 by Charlie Calvert
//
#ifndef SimpleObjectH
#define SimpleObjectH
#include <vcl\oleauto.hpp>
#include <vcl\Classes.hpp>
class TSimpleDCOM : public TAutoObject
{
private:
public:
virtual __fastcall TSimpleDCOM();
__automated:
AnsiString __fastcall GetName();
int
__fastcall Square(int A);
};
#endif
</FONT></PRE>
<P><A NAME="Heading16"></A><FONT COLOR="#000077"><B>Listing 27.4. The main source
file of an OLE Automation object.</B></FONT></P>
<PRE><FONT
COLOR="#0066FF">///////////////////////////////////////
// SimpleObject.cpp
// EasyDCOM
// Copyright (c) 1997 by Charlie Calvert
//
#include <vcl\vcl.h>
#pragma hdrstop
#undef RegisterClass
#include "SimpleObject.h"
int
Initialization();
static int Initializer = Initialization();
__fastcall TSimpleDCOM::TSimpleDCOM()
: TAutoObject()
{
}
AnsiString __fastcall TSimpleDCOM::GetName()
{
return "SimpleDCOM";
}
int __fastcall
TSimpleDCOM::Square(int A)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -