📄 ch10.htm
字号:
// properties<BR>
// <BR>
// methods<BR>
//<BR>
[id(DISPID_ABOUTBOX)]<BR>
void AboutBox(void);<BR>
}; <BR>
// event interface for CBCFControlSubWin controls ...<BR>
//<BR>
[<BR>
uuid(02456be2-3fb7-11d0-bec1-00400538977d),<BR>
helpstring("Event interface for BCFControlSubWin control"),<BR>
hidden<BR>
]<BR>
dispinterface DBCFControlSubWinEvents {<BR>
properties:<BR>
methods:<BR>
}; <BR>
// coclass for CBCFControlSubWin controls<BR>
//<BR>
[<BR>
uuid(02456be3-3fb7-11d0-bec1-00400538977d),<BR>
helpstring("BCFControlSubWin control")<BR>
]<BR>
coclass BCFControlSubWin {<BR>
[default] interface IBCFControlSubWin;<BR>
[default, source] dispinterface DBCFControlSubWinEvents;<BR>
}; <BR>
};</TT></FONT></P>
<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"></P>
<BLOCKQUOTE>
<P><B>CAUTION:</B><BR>
When combining several OCXs, you <I>must</I> delete any .tlb files that may have
already been created to update the dependencies of the project. Occasionally, Visual
C++ will compile more that one type library into different directories and use the
incorrect version when compiling the resources for the control. In the case where
you have new information that is added to the ODL file, the result will be that the
type library has not appeared to have changed, which can be a major problem for applications,
such as VB, that depend on the type library for information about the component being
used.
</BLOCKQUOTE>
<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"><BR>
<BR>
Open the BCFControlNoWin.rc and BCFControlSubWin.rc resource files. Copy the property
page dialogs and the string and bitmap resources to the BCFControl resource file.
Rename the bitmaps to <TT>RESID_TOOLBOX_BITMAP1</TT>, <TT>RESID_TOOLBOX_BITMAP2</TT>,
and <TT>RESID_TOOLBOX_BITMAP3</TT>, respectively. <BR>
<BR>
<IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"></P>
<BLOCKQUOTE>
<P><B>NOTE:</B> If you experience problems opening the resource files because of
dependencies on the type library, you can either compile the ODL files into the type
library or open the resource files in text mode and edit the files manually.
</BLOCKQUOTE>
<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"><BR>
<BR>
After combining the resources, you need to combine your Resource.h files as well
(see Listing 10.4). Make sure that the constant values match their corresponding
resources.
<H3><A NAME="Heading7"></A>Listing 10.4 <SPACER TYPE="HORIZONTAL" SIZE="10">RESOURCE.H--Combined
Resource.h Files</H3>
<P><FONT COLOR="#0066FF"><TT>//=--------------------------------------------------------------------------=<BR>
<BR>
// Resource.H<BR>
//=--------------------------------------------------------------------------=<BR>
// Copyright 1995 Microsoft Corporation. All Rights Reserved.<BR>
//<BR>
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF <BR>
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO <BR>
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A <BR>
// PARTICULAR PURPOSE.<BR>
//=--------------------------------------------------------------------------=<BR>
//<BR>
// resource IDs.<BR>
//<BR>
#ifndef _RESOURCE_H_ <BR>
#define RESID_TOOLBOX_BITMAP1 1<BR>
#define RESID_TOOLBOX_BITMAP2 2<BR>
#define RESID_TOOLBOX_BITMAP3 3 <BR>
//=--------------------------------------------------------------------------=<BR>
// Strings<BR>
// <BR>
// this must be defined for any server that has propety pages. it must be one<BR>
// thousand.<BR>
//<BR>
#define IDS_PROPERTIES 1000 <BR>
// this is defined for all inproc servers that use satellite localization. it<BR>
// must be 1001<BR>
//<BR>
#define IDS_SERVERBASENAME 1001 <BR>
#define IDS_BCFCONTROL_GENERALPAGETITLE 2003<BR>
#define IDS_BCFCONTROL_GENERALDOCSTRING 2004<BR>
#define IDS_BCFCONTROLNOWIN_GENERALPAGETITLE 2005<BR>
#define IDS_BCFCONTROLNOWIN_GENERALDOCSTRING 2006<BR>
#define IDS_BCFCONTROLSUBWIN_GENERALPAGETITLE 2007<BR>
#define IDS_BCFCONTROLSUBWIN_GENERALDOCSTRING 2008<BR>
#define IDS_BCFCONTROL_ABOUTBOXVERB 2009<BR>
#define IDS_BCFCONTROLNOWIN_ABOUTBOXVERB 2010<BR>
#define IDS_BCFCONTROLSUBWIN_ABOUTBOXVERB 2011 <BR>
//=--------------------------------------------------------------------------=<BR>
// Dialog Stuff<BR>
//<BR>
#define IDD_PROPPAGE_BCFCONTROLGENERAL 2000<BR>
#define IDD_PROPPAGE_BCFCONTROLNOWINGENERAL 2001<BR>
#define IDD_PROPPAGE_BCFCONTROLSUBWINGENERAL 2002 <BR>
#define _RESOURCE_H_ <BR>
#endif // _RESOURCE_H_</TT></FONT></P>
<P>Combine all of the LocalObj.h files (see Listing 10.5). Be sure to renumber the
constants so that they are not the same since they are used to identify each control
and property page in your application.
<H3><A NAME="Heading8"></A>Listing 10.5 <SPACER TYPE="HORIZONTAL" SIZE="10">LOCALOBJ.H--Combined
LocalObj.h File</H3>
<P><FONT COLOR="#0066FF"><TT>//=--------------------------------------------------------------------------=<BR>
// LocalObjects.H<BR>
//=--------------------------------------------------------------------------= <BR>
... <BR>
// **** ADD ALL NEW OBJECTS TO THIS LIST ****<BR>
// <BR>
#define OBJECT_TYPE_CTLBCFCONTROL 0<BR>
#define OBJECT_TYPE_PPGBCFCONTROLGENERAL 1<BR>
#define OBJECT_TYPE_CTLBCFCONTROLNOWIN 2<BR>
#define OBJECT_TYPE_PPGBCFCONTROLNOWINGENERAL 3<BR>
#define OBJECT_TYPE_CTLBCFCONTROLSUBWIN 4<BR>
#define OBJECT_TYPE_PPGBCFCONTROLSUBWINGENERAL 5 <BR>
#define _LOCALOBJECTS_H_ <BR>
#endif // _LOCALOBJECTS_H_</TT></FONT></P>
<P>Last you update the bitmap resource constant for each of your control header files.
Listing 10.6 shows the change that needs to be made to each of the control header
files.
<H3><A NAME="Heading9"></A>Listing 10.6<SPACER TYPE="HORIZONTAL" SIZE="10"> BCFCONTROLCTL.H--Update
the Bitmap Source</H3>
<P><FONT COLOR="#0066FF"><TT>extern const GUID *rgBCFControlPropPages [];<BR>
DEFINE_CONTROLOBJECT(BCFControl,<BR>
&CLSID_BCFControl,<BR>
"BCFControlCtl",<BR>
CBCFControlControl::Create,<BR>
1,<BR>
&IID_IBCFControl,<BR>
"BCFControl.HLP",<BR>
&DIID_DBCFControlEvents,<BR>
OLEMISC_SETCLIENTSITEFIRST | OLEMISC_ACTIVATEWHENVISIBLE | <BR>
OLEMISC_RECOMPOSEONRESIZE | OLEMISC_CANTLINKINSIDE | OLEMISC_INSIDEOUT,<BR>
0, // no IPointerInactive policy by default<BR>
RESID_TOOLBOX_BITMAP1,<BR>
"BCFControlWndClass",<BR>
1,<BR>
rgBCFControlPropPages,<BR>
0, <BR>
NULL);</TT></FONT></P>
<P>Be sure to make the same change to the BCFControlNoWinCtl.h and BCFControlSubWinCtl.h
header files using the ID's RESID_TOOLBOX_BITMAP2 and RESID_TOOLBOX_BITMAP3, respectively.</P>
<P>All of the basic source files are now added to the control project. The next step
in any control project is to ensure that the project contains registration support.
Without registration, the control cannot be used by any application.
<H2><A NAME="Heading10"></A>Control Registration</H2>
<P>Control registration support is handled completely by the BaseCtl framework and
is hidden from the developer. Some of the registration information is part of the
<TT>DEFINE_CONTROLOBJECT</TT> structure (see Listing 10.7), which you looked at earlier
in this chapter. See the BaseCtl documentation about the specific information that
can be changed.
<H3><A NAME="Heading11"></A>Listing 10.7<SPACER TYPE="HORIZONTAL" SIZE="10"> BCFCONTROLCTL.H--DEFINE_CONTROLOBJECT
Structure</H3>
<PRE><FONT COLOR="#0066FF">// TODO: if you have an array of verbs, then add an extern here with the name</FONT></PRE>
<P><FONT COLOR="#0066FF"><TT><BR>
// of it, so that you can include it in the DEFINE_CONTROLOBJECT.<BR>
// ie. extern VERBINFO m_BCFControlCustomVerbs [];<BR>
//<BR>
extern const GUID *rgBCFControlPropPages [];<BR>
DEFINE_CONTROLOBJECT(BCFControl,<BR>
&CLSID_BCFControl,<BR>
"BCFControlCtl",<BR>
CBCFControlControl::Create,<BR>
1,<BR>
&IID_IBCFControl,<BR>
"BCFControl.HLP",<BR>
&DIID_DBCFControlEvents,<BR>
OLEMISC_SETCLIENTSITEFIRST | <BR>
OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_RECOMPOSEONRESIZE | <BR>
OLEMISC_CANTLINKINSIDE | OLEMISC_INSIDEOUT,<BR>
0, // no IPointerInactive policy by default<BR>
RESID_TOOLBOX_BITMAP1,<BR>
"BCFControlWndClass",<BR>
1,<BR>
rgBCFControlPropPages,<BR>
0, <BR>
NULL);</TT></FONT></P>
<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"></P>
<BLOCKQUOTE>
<P><B>NOTE:</B> The BaseCtl basic project does not by default contain support for
registering the control automatically when the project is compiled. You must ensure
that the control is properly registered before using it, especially if you recently
switched between debug and release versions.
</BLOCKQUOTE>
<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"><BR>
<BR>
You can now compile and register the control you've created, but it won't be of much
use because it doesn't contain any methods, properties, or events, which are the
basis of every ActiveX control.
<H2><A NAME="Heading12"></A>Creating Methods</H2>
<P>Now that you've successfully created your ActiveX control project, you can add
a <I>method, </I>which is one of the basic aspects of component development.</P>
<P>For the purposes of the sample control, you add a method called <TT>CaptionMethod</TT>.
The method accepts two parameters, the second being optional. The first parameter
is a string that the control displays within its client area, and the second, optional
parameter is the alignment of the caption within the client area, either left, right,
or center.</P>
<P>When creating methods, properties, and events for your control, you always start
with the ODL file. When the ODL file is compiled, a C++ header file is created that
defines all of the interfaces and methods of the control. From the header file, you
cut and paste the method, property, and event prototypes into your control implementation.
The one thing about your BaseCtl (and ATL) implementation that is different from
your MFC implementation is that your control supports dual-interfaces by default.
All methods, properties, and events must be written using dual-interface syntax rules,
which you get into a little later in this chapter.</P>
<P>First you need to add an entry to the Dispids.h file. Dispids are the constant
values used by the <TT>IDispatch</TT> routines to locate the correct method or property
being invoked through the <TT>IDispatch</TT> interface. Dispids can be any unique
number including negative numbers. Be careful when using negative values, however,
since the system-defined dispids are all negative. You are better off staying with
only positive values. Listing 10.8 shows the dispid entry that you added for your
<TT>CaptionMethod</TT>.
<H3><A NAME="Heading13"></A>Listing 10.8<SPACER TYPE="HORIZONTAL" SIZE="10"> DISPIDS.H--Dispid
for CaptionMethod</H3>
<P><FONT COLOR="#0066FF"><TT>#define dispidCaptionMethod 2</TT></FONT></P>
<P>Next you need to add the new method to your ODL file. From the Project Workspace
window, select the File View, and open the BCFControl.odl file. Listing 10.9 shows
the method that you added to the <TT>BCFControl</TT>'s primary dispatch interface.</P>
<P>The <TT>dispidCaptionMethod</TT> constant is used for the <TT>id</TT> of the method,
the return type is <TT>HRESULT</TT>--because it's dual-interface, and the name is
<TT>CaptionMethod</TT>. The parameters are de-fined as a <TT>BSTR</TT>, named <TT>lpctstrCaption</TT>,
and a <TT>VARIANT</TT>, named <TT>varAlignment</TT>. Your last parameter is actually
your return value and is defined as a <TT>long</TT> pointer, named <TT>RetVal</TT>.
You also added the direction that the parameters flow in the form of <TT>[in]</TT>
and <TT>[out]</TT> parameter attributes. (See Table 10.2 for a complete description
of the possible attributes that can be used.)</P>
<P>Parameter attributes are used to aid development tools, such as VB, in determining
how parameters are used within a function call. A tool like VB will hide the details
of how parameters are handled--for example, creating and destroying memory--based
on the parameter direction attributes and other attributes in the type library. The
type library is the description of your component to the tools that will use it and
is why it is so important to ActiveX component development.
<TABLE BORDER="1" WIDTH="100%">
<CAPTION><B>Table 10.2</B><SPACER TYPE="HORIZONTAL" SIZE="10"><B>Parameter Flow Attributes</B></CAPTION>
<TR ALIGN="LEFT" rowspan="1">
<TD ALIGN="LEFT" VALIGN="TOP"><B>Direction</B></TD>
<TD ALIGN="LEFT" VALIGN="TOP"><B>Description</B></TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD ALIGN="LEFT" VALIGN="TOP">in</TD>
<TD ALIGN="LEFT" VALIGN="TOP">Parameter is passed from caller to callee.</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -