📄 ch02.htm
字号:
on the type of interface that can be created. An example of a
COM Object might be a simple implementation that performs calculations
of a large volume of user-defined data. Instead of copying the
data and passing it to the COM Object, it might be more useful
to pass a pointer to the data and allow the COM Object to manipulate
the data directly. Automation Server data type restrictions would
not allow for the creation of this kind of interface. COM does,
however. Although in this case, the COM Object can execute only
in-process because it needs direct access to the data.
<H2><A NAME="Heading7">Selecting the Right Tool for the Right
Job</A></H2>
<P>
Microsoft is going hog-wild with its tools development. Every
product coming out these days seems to have the capability of
building one kind of ActiveX component or another. Applications
like Visual C++, Visual Basic (VB), J++, Access, FoxPro, Microsoft
Word, and Microsoft Excel, just to name a few, can create anything
from ActiveX COM Objects to ActiveX Documents. This book addresses
creating ActiveX components by using Microsoft Visual C++ (VC++).
Deciding whether to use VC++ for your development is usually based
on one issue: limitations. All other products and tools capable
of creating ActiveX components are going to suffer from some form
of limitation. VC++ is the most powerful and flexible tool for
creating ActiveX components, and now that you have decided VC++
is the way to go, you need to decide on a development strategy.</P>
<P>
When creating your ActiveX component with Visual C++, you have
four options, which are all described in the following sections.
<H3><A NAME="Heading8">Microsoft Foundation Classes</A></H3>
<P>
The Microsoft Foundation Class Library (MFC) is the easiest choice
of all the tools available for ActiveX development. The VC++ IDE
(Integrated Development Environment) is designed specifically
with MFC in mind and provides very useful application and ClassWizards
for developing your application. MFC is robust and will probably
cover 90 percent of your application's needs. Unfortunately, like
every other software project that you have probably worked on,
the last 10 percent is where you spend 90 percent of your time.</P>
<P>
Going outside the bounds of what MFC defines can be difficult
and, in some cases, impossible. Take for example the requirement
to have an Object that is single instance only. No matter how
the Object is created by the client application, you always want
the same instance returned. Providing this kind of functionality
is impossible with MFC without modifying the built-in Class Factory
classes, and these are not normally exposed to the developer.</P>
<P>
Supporting dual-interfaces in Automation Servers is not impossible,
but it does cause enough changes in your code so that the ClassWizard
can no longer be used to completely maintain your methods and
properties. Some work will have to be done by hand. MFC does provide
a number of features and functions when developing ActiveX components,
but be prepared to live by its rules. Occasionally, you can bend
the rules, but you can almost never break them. The following
chapters discuss how to successfully bend the rules in MFC and
implement both single instance and dual-interface servers.</P>
<P>
A good rule of thumb when working with MFC is to avoid using the
built-in classes as much as possible by utilizing the basic Windows
API instead.</P>
<P>
Avoiding use of the MFC classes to solve your application problems
has two benefits. The first is that your application will generally
run faster; the second is that moving to an alternative development
tool such as ATL or BaseCtl will prevent a large amount of code
rewrite. A large portion of the MFC classes have equivalent Windows
API functions, especially in the area of GDI and drawing, and
is not that much of a departure from MFC. Basic storage classes,
such as lists and arrays, could be better provided by a general
purpose class library, such as the Standard Template Library (STL),
which can be used in combination with all of the ActiveX development
frameworks you will be seeing in this book.
<H3><A NAME="Heading9">ActiveX Template Library</A></H3>
<P>
ActiveX Template Library (ATL as it has come to be known), is
a newcomer to the ActiveX arena. It first appeared in the summer
of 1996 and quickly became a favorite among developers. Based
on the amount of development taking place by using ATL and the
fact that, unlike the BaseCtl framework, it is actually a supported
product, Microsoft and the industry have obviously seen ATL as
a viable platform for creating ActiveX components and it should
be around for a long time.</P>
<P>
The initial implementation, versions 1.0 and 1.1, focused on the
creation of small and fast Automation Servers and COM Objects.
With the introduction of 2.0, ATL expanded its coverage to include
ActiveX Controls and other ActiveX components. The level of integration
with the VC++ IDE originally consisted only of an AppWizard used
to create the basic ATL project, which, by the way, was more complete
than its MFC counterpart. Also the ClassWizard could be used to
maintain the Objects, methods, and properties as it can with MFC.
ATL version 2.0 and VC++ 5.0 are now fully integrated, supplying
the same level of tool support, such as AppWizards, ObjectWizards,
and ClassWizards.</P>
<P>
An added bonus to ATL is that it can be integrated into existing
MFC applications without dire consequences or enormous amounts
of work. This capability gives you complete freedom to develop
your component without the restrictions that MFC imposes, while
still being able to use nice MFC classes and features (like structures,
arrays, and lists, to name a few).
<H3><A NAME="Heading10">BaseControl Framework</A></H3>
<P>
BaseControl (BaseCtl) Framework and the ActiveX SDK is without
a doubt the most difficult route to choose for ActiveX component
development. The BaseCtl was first developed by the Visual Basic
4 (VB 4) development group in late 1995 and early 1996 in response
to growing demands for better performance when using OCXs and
VB. BaseCtl (then referred to as the "MarcWan" framework
because of its primary developer, Marc Wandschnieder at Microsoft)
was intended as a bare-bones framework to be used to create lightweight
OLE Controls.</P>
<P>
In an effort to quell the demand for tools to create OLE Controls,
the framework was put into the hands of various Control developers
and vendors who were in contact with Microsoft and the VB group.
At the Internet PDC, Microsoft packaged the BaseCtl Framework
as part of the ActiveX SDK, and the rest, as they say, is history.</P>
<P>
The BaseCtl has no integration with the VC++ environment. In fact,
the version of the BaseCtl framework that ships with the ActiveX
SDK is little more than sample programs from which you can create
new applications. Another version of the baseCtl framework that
has been available to members of the VB 4 and 5 beta testers actually
contains an AppWizard. The AppWizard used to create the base set
of source files is written in VB and is ad hoc at best. The BaseCtl
relies on a series of Object and library files that have to be
built by you, the developer, before they can be used. All of the
source files that come with the SDK and those generated by the
AppWizard depend on command-line compilation. With a little bit
of effort on your part, the projects can all be converted to VC++
projects, including the Object and library files that come with
the SDK. The documentation for the BaseCtl is rudimentary and
somewhat cryptic.</P>
<P>
Basic Control development with the BaseCtl framework can be difficult,
as well. A fair number of the functions and capabilities that
you're used to in MFC aren't present in the BaseCtl. A number
of the function names are different, and the architecture for
persistence is completely different. BaseCtl is meant to get the
job done with as little code as possible, and unfortunately it's
obvious.</P>
<P>
For those of you who have already written Controls in MFC and
want to port them to the BaseCtl, I have only one thing to say,
"Roll up your sleeves because it's going to get messy."
With the BaseCtl, you're expected to dig into the guts of the
framework and build a lot of the function yourself.</P>
<P>
One thing the BaseCtl has going for it is a fair number of samples.
When installing the BaseCtl, it is recommended that you install
the samples as well. Chances are that if you need to do something,
it's in one of the samples. VC++ has a nice feature called "Find
in Files." Take advantage of it. Another nice feature of
the BaseCtl is the capability to access all the source code in
the BaseCtl framework directly, so if you find a bug (and there
are a couple), you can fix it yourself and move on.</P>
<P>
Also, you have a lot more freedom to model your Control as you
want. For example, you have two Controls that you want to develop;
one is a Number Control, for basic numeric data input, and the
other is a Currency Control, for basic currency data input. Both
can rely heavily on the C++ inheritance model at the code and
interface levels by creating a BaseNumeric Control.</P>
<P>
You don't have this kind of freedom with MFC. BaseCtl should not
be taken lightly, and you can expect a lot of work when implementing
a component with it. Even worse, the results may not justify the
work. In one case, after converting an existing MFC Control to
the BaseCtl, a 40 percent improvement was realized in the average
load time of the two versions of the Control. You might think
"Wow--40 percent! That's pretty good." Unfortunately,
the load times were already so low for both Controls that you
literally had to have hundreds of Controls on the form before
the improvement was noticeable.
<H3><A NAME="Heading11">Create Your Own Framework</A></H3>
<P>
The last method for Control development is to just sit down and
do it. Get code from the class libraries, samples, books, and
so on, and come up with your own framework, tools, or whatever
you want. But you can expect the work to be hard and time-consuming.
To get an idea of how much work is actually involved, stop for
a minute and take a look at some of the source files in MFC, ATL,
and the BaseCtl. Literally thousands of lines of code have been
implemented over the course of months and even years. Due to the
constantly changing nature of OLE and ActiveX requirements, it
is wiser to choose an existing platform rather than trying to
reinvent the wheel.</P>
<P>
The key to successful Control development is not in the framework
that you choose to develop in, but in how you apply it.
<H2><A NAME="Heading12">Basic ActiveX Component Architecture</A>
</H2>
<P>
Before moving on to the actual implementation of each type of
ActiveX component, you need to review some of the basic concepts
and architecture surrounding each component.</P>
<P>
Even though you can develop a wide variety of ActiveX components--controls,
servers, documents, and so on--one thing is true for all of them:
Underlying every component is the Component Object Model or COM
architecture. COM defines the standard that all ActiveX components
rely on when interacting with other ActiveX components.</P>
<P>
In addition to COM, all ActiveX components are further defined
or restricted by the operating system in how they are created
and used. The type of ActiveX component you create will further
define or restrict your options when creating components. A wide
variety of choices are available to you as a developer and it
is important to understand the ramifications of each.
<H3><A NAME="Heading13">ActiveX Automation Servers</A></H3>
<P>
Probably the easiest to implement and most flexible form of ActiveX
component is the Automation Server. An <I>Automation Server</I>
is an application that contains one or more <TT>IDispatch</TT>-based
interfaces. An <I>interface</I> is a collection of related methods
and properties and an <TT>IDispatch</TT> interface is the name
of the COM interface that is used to generically invoke those
methods and properties. For more information on <TT>IDispatch</TT>
interfaces please see the VC++ books online. The capability to
define unique methods and properties for each server and have
them be accessible through a generic mechanism is the real power
of Automation Servers.</P>
<P>
An automation server may or may not be directly creatable by other
applications via a <TT>CreateObject</TT> or similar call. It is
possible to have what are referred to as nested objects that represent
a hierarchy of objects. A single creatable automation object is
responsible for the creation and distribution of other automation
objects. For example, an application may expose a Document automation
interface that can be created and manipulated by another application
but that only exposes a <TT>Page</TT> interface as a method call
to the document object. The lifetime of the <TT>Page</TT> object
is less than or equal to the <TT>Document</TT> object and cannot
exist on its own. (The terms object and server are used synonymously
throughout this book.)</P>
<P>
Three of the chapters in this book focus on creating ActiveX Automation
servers using MFC, ATL, and the BaseCtl framework. Each of the
tools has its own set of strengths and weaknesses and, depending
on your specific application requirements, will determine which
tool you should use.</P>
<P>
MFC is great for rapid development and ease of modification. Servers
created with MFC will be the largest and slowest of the three
types. Deviating from the standard MFC implementation of Automation
Servers can also be a limiting factor when using this tool. MFC's
greatest strength is its integration with the VC++ IDE and the
speed with which an implementation can be up and running. In only
minutes developers can create a server and implement its methods
and properties, assuming that they are familiar with the tools
available.</P>
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -