📄 ch11.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<!--last modified on Tue, Apr 15, 1997 11:35 AM-->
<HTML>
<HEAD>
<!-- This document was created from RTF source by rtftohtml version 3.0.1 -->
<META NAME="GENERATOR" Content="Symantec Visual Page 1.0">
<META NAME="Author" Content="Steph Mineart">
<title>ActiveX Programming with Visual C++ -- Chapter 11</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF">
<H1>Chapter 11<BR>
Advanced ActiveX Control Development with BaseCtl</H1>
<UL>
<LI><A HREF="#Heading1">Advanced ActiveX Control Development with BaseCtl</A>
<UL>
<LI><A HREF="#Heading2">Creating Properties</A>
<UL>
<LI><A HREF="#Heading3">Creating Asynchronous Properties</A>
<LI><A HREF="#Heading4">Listing 11.1 BCFCONTROLCTL.H--Modified BCFControlControl
Class Definition</A>
<LI><A HREF="#Heading5">Listing 11.2 BCFCONTROLCTL.CPP--BCFControlControl Constructor
Implementation Change</A>
<LI><A HREF="#Heading6">Listing 11.3 BCFCONTROLCTL.CPP--OnData Function</A>
<LI><A HREF="#Heading7">Listing 11.4 DISPIDS.H--Add Data Path Property Dispid</A>
<LI><A HREF="#Heading8">Listing 11.5 BCFCONTROL.ODL--BCFControl ODL Implementation</A>
<LI><A HREF="#Heading9">Listing 11.6 BCFCONTROLCTL.H--ReadyState Property Prototype</A>
<LI><A HREF="#Heading10">Listing 11.7 BCFCONTROLCTL.CPP--Member Initialization</A>
<LI><A HREF="#Heading11">Listing 11.8 BCFCONTROLCTL.CPP--Property Implementation</A>
<LI><A HREF="#Heading12">Listing 11.9 BCFCONTROLCTL.CPP--OnData Implementation</A>
<LI><A HREF="#Heading13">Static and Dynamic Property Enumeration</A>
<LI><A HREF="#Heading14">Listing 11.10 PERPROPERTYBROWSING.H--IPerPropertyBrowsing
Interface Macro</A>
<LI><A HREF="#Heading15">Listing 11.11 BCFCONTROLCTL.H--IPerPropertyBrowsing Interface
Declaration</A>
<LI><A HREF="#Heading16">Listing 11.12 BCFCONTROLCTL.CPP--QueryInterface Implementation
of IPerPropertyBrowsing</A>
<LI><A HREF="#Heading17">Listing 11.13 BCFCONTROLCTL.CPP--IPerPropertyBrowsing Implementation</A>
</UL>
<LI><A HREF="#Heading18">Drawing the Control</A>
<UL>
<LI><A HREF="#Heading19">Optimized Drawing</A>
<LI><A HREF="#Heading20">Listing 11.14 BCFCONTROLCTL.CPP--Optimized Drawing</A>
<LI><A HREF="#Heading21">Listing 11.15 BCFCONTROLCTL.CPP--BeforeDestroyWindow Implementation</A>
</UL>
<LI><A HREF="#Heading22">Adding Clipboard and Drag and Drop Support</A>
<UL>
<LI><A HREF="#Heading23">Clipboard Support</A>
<LI><A HREF="#Heading24">Listing 11.16 IDATAOBJECT.H--IDataObject Interface Macro</A>
<LI><A HREF="#Heading25">Listing 11.17 IENUMFORMATETC--IEnumFORMATETC Interface Macro</A>
<LI><A HREF="#Heading26">Listing 11.18 BCFCONTROLCTL.H--Clipboard Support Implementation--Header
File</A>
<LI><A HREF="#Heading27">Listing 11.19 BCFCONTROLCTL.CPP--Constructor Member Initialization</A>
<LI><A HREF="#Heading28">Listing 11.20 BCFCONTROLCTL.CPP--QueryInterface Update</A>
<LI><A HREF="#Heading29">Listing 11.21 BCFCONTROLCTL.CPP--WM_KEYDOWN Message Handler</A>
<LI><A HREF="#Heading30">Listing 11.22 BCFCONTROLCTL.CPP--CopyDataToClipboard Implementation</A>
<LI><A HREF="#Heading31">Listing 11.23 BCFCONTROLCTL.CPP--PrepareDataForTransfer
Implementation</A>
<LI><A HREF="#Heading32">Listing 11.24 BCFCONTROLCTL.CPP--CopyStgMedium Implementation</A>
<LI><A HREF="#Heading33">Listing 11.25 BCFCONTROLCTL.CPP--IDataObject Implementation</A>
<LI><A HREF="#Heading34">Listing 11.26 BCFCONTROLCTL.CPP--IEnumFORMATETC Implementation</A>
<LI><A HREF="#Heading35">Listing 11.27 BCFCONTROLCTL.CPP--OnKeyDown Implementation</A>
<LI><A HREF="#Heading36">Listing 11.28 BCFCONTROCTL.H--Clipboard Target Implementation--
Header File</A>
<LI><A HREF="#Heading37">Listing 11.29 BCFCONTROLCTL.CPP--GetDataFromClipboard Implementation</A>
<LI><A HREF="#Heading38">Listing 11.30 BCFCONTROLCTL.CPP--GetDataFromTransfer Implementation</A>
<LI><A HREF="#Heading39">Listing 11.31 BCFCONTROCTL.CPP--OnKeyDown Implementation</A>
<LI><A HREF="#Heading40">Adding Drag and Drop Support</A>
<LI><A HREF="#Heading41">Listing 11.32 IDROPSOURCE.H--IDropSource Interface</A>
<LI><A HREF="#Heading42">Listing 11.33 BCFCONTROCTL.H--IDropSource Interface Implementation</A>
<LI><A HREF="#Heading43">Listing 11.34 BCFCONTROLCTL.CPP--QueryInterface Update</A>
<LI><A HREF="#Heading44">Listing 11.35 BCFCONTROLCTL.CPP--WindowProc Implementation</A>
<LI><A HREF="#Heading45">Listing 11.36 BCFCONTROLCTL.CPP--Drop Source Implementation</A>
<LI><A HREF="#Heading46">Listing 11.37 IDROPTARGET.H--IDropTarget Interface</A>
<LI><A HREF="#Heading47">Listing 11.38 BCFCONTROLCTL.H--IDropTarget Implementation</A>
<LI><A HREF="#Heading48">Listing 11.39 BCFCONTROLCTL.CPP--QueryInterface Update</A>
<LI><A HREF="#Heading49">Listing 11.40 BCFCONTROLCTL.CPP--AfterCreateWindow Implementation</A>
<LI><A HREF="#Heading50">Listing 11.41 BCFCONTROLCTL.CPP--IDropTarget Implementation</A>
<LI><A HREF="#Heading51">Custom Clipboard and Drag and Drop Formats</A>
<LI><A HREF="#Heading52">Listing 11.42 BCFCONTROLCTL.H--Custom Data Format Member
Variables</A>
<LI><A HREF="#Heading53">Listing 11.43 BCFCONTROLCTL.CPP--Register the Custom Format</A>
<LI><A HREF="#Heading54">Listing 11.44 BCFCONTROCTL.CPP--PrepareDataForTransfer Update</A>
<LI><A HREF="#Heading55">Listing 11.45 BCFCONTROLCTL.CPP--GetDataFromTransfer Update</A>
<LI><A HREF="#Heading56">Listing 11.46 BCFCONTROLCTL.CPP--IEnumFORMATETC::Next Update</A>
<LI><A HREF="#Heading57">Listing 11.47 BCFCONTROLCTL.CPP--IEnumFORMATETC::GetData
Update</A>
</UL>
<LI><A HREF="#Heading58">Subclassing Existing Windows Controls</A>
<UL>
<LI><A HREF="#Heading59">Listing 11.48 BCFCONTROLSUBCTL.CPP--RegisterClassData Implementation</A>
</UL>
<LI><A HREF="#Heading60">Dual-Interface Controls</A>
<LI><A HREF="#Heading61">Other ActiveX Features</A>
<UL>
<LI><A HREF="#Heading62">Windowless Activation</A>
<LI><A HREF="#Heading63">Listing 11.49 BCFCONTROLCTL.H--BCFControControl ActiveX
Implementation</A>
<LI><A HREF="#Heading64">Listing 11.50 BCFCONTROLNOWIN.H--BCFControlNoWinControl
ActiveX Implementation</A>
<LI><A HREF="#Heading65">Unclipped Device Context</A>
<LI><A HREF="#Heading66">Flicker-Free Activation</A>
<LI><A HREF="#Heading67">Mouse Pointer Notifications When Inactive</A>
<LI><A HREF="#Heading68">Listing 11.51 BCFCONTROLNOWIN.H--Mouse Notifications</A>
<LI><A HREF="#Heading69">Optimized Drawing Code</A>
<LI><A HREF="#Heading70">Loads Properties Asynchronously</A>
</UL>
<LI><A HREF="#Heading71">From Here...</A>
</UL>
</UL>
<P>
<HR SIZE="4">
<H1><A NAME="Heading1"></A>Advanced ActiveX Control Development with BaseCtl</H1>
<UL>
<LI><B>Asynchronous properties</B>
<SPACER TYPE="VERTICAL" SIZE="2">
Supporting asynchronous properties in the BaseCtl sample shows what is happening
behind the scenes when properties are loaded asynchronously.
<P>
<LI><B>Property enumeration</B>
<SPACER TYPE="VERTICAL" SIZE="2">
Property enumeration is exposed through a simple COM interface, which is easy to
add given the BaseCtl architecture.
<P>
<LI><B>Optimized drawing</B>
<SPACER TYPE="VERTICAL" SIZE="2">
Optimized drawing has positive effects on the performance of the control. Like MFC
and ATL, BaseCtl support of optimized drawing is trivial.
<P>
<LI><B>Clipboard and Drag and Drop</B>
<SPACER TYPE="VERTICAL" SIZE="2">
Adding Clipboard and Drag and Drop support to your BaseCtl implementation is similar
to the MFC and ATL implementations.
<P>
<LI><B>Windows and dual-interface controls</B>
<SPACER TYPE="VERTICAL" SIZE="2">
Subclassing an existing Windows control reduces development time when creating new
control implementations. Like ATL, BaseCtl ActiveX control implementations support
dual-interface by default.
<P>
<LI><B>Advanced ActiveX</B>
<SPACER TYPE="VERTICAL" SIZE="2">
The BaseCtl framework supports the advanced ActiveX features in this chapter.
</UL>
<P>This chapter expands upon the information in <A HREF="ch10.htm">Chapter 10</A>
about creating a basic BaseCtl ActiveX control, so reading Chapter 10 prior to this
chapter is necessary. In addition to the features that you are familiar with, such
as Clipboard and Drag and Drop support, you will learn how to implement asynchronous
properties and optimized drawing, which are the result of the adoption of OC 96 specification.
<H2><A NAME="Heading2"></A>Creating Properties</H2>
<P><A HREF="ch10.htm">Chapter 10</A> tells you how to add the various types of properties
to your control implementation. One type of property has yet to be examined: asynchronous
properties.
<H3><A NAME="Heading3"></A>Creating Asynchronous Properties</H3>
<P><I>Asynchronous properties </I>are those properties that typically represent a
large amount of data, such as a text or bitmap file, and are loaded as a background
process so as not to interfere with the normal processing of the control and the
container. This statement can be somewhat misleading. Asynchronous refers only to
the <I>call</I> to load the data; it does not refer to the actual loading.</P>
<P>For example, a control uses a bitmap as its background and has defined the bitmap
as an asynchronous property. If OLE determines that the bitmap is already on the
local machine, the data is considered to be available to the control and, subsequently,
will instruct the control that <I>all </I>of the data is available. If OLE determines
that the bitmap is not available on the local machine, OLE will load the data as
fast as possible and inform the control as data becomes available. After the data
is in a location that is considered accessible, the property essentially behaves
as any other property would. If you require the asynchronous loading of the data
regardless of its location, you must implement it yourself.</P>
<P>To allow for asynchronous property support, you have to modify your class definition
slightly. Listing 11.1 shows the changes that were made to your <TT>BCFControlControl</TT>
class header file.</P>
<P>The BaseCtl class <TT>COleControl</TT> does not provide support for asynchronous
properties. You need to take advantage of the BaseCtl class <TT>CInternetControl</TT>
in order to do that.</P>
<P>You need to include the Internet.h file and derive the class <TT>BCFControlControl</TT>
from <TT>CInternetControl</TT>, which is derived from the base class <TT>COleControl</TT>.
You also add the method <TT>OnData</TT> as your callback function. The callback function
is what OLE uses to notify your control that data is being downloaded and is required
for asynchronous property support.
<H3><A NAME="Heading4"></A>Listing 11.1 <SPACER TYPE="HORIZONTAL" SIZE="10">BCFCONTROLCTL.H--Modified
BCFControlControl Class <TT>Definition</TT></H3>
<P><FONT COLOR="#0066FF"><TT>. . . <BR>
// class declaration for the BCFControl control.<BR>
//<BR>
#ifndef _BCFCONTROLCONTROL_H_ <BR>
#include "IPServer.H"<BR>
#include "CtrlObj.H"<BR>
#include "BCFControlInterfaces.H"<BR>
#include "Dispids.H"<BR>
#include "internet.h" <BR>
#include "alignmentenums.h" <BR>
typedef struct tagBCFCONTROLCTLSTATE<BR>
{<BR>
long lCaptionLength;<BR>
long lAlignment;<BR>
OLE_COLOR ocBackColor;<BR>
} BCFCONTROLCTLSTATE; <BR>
//=-------------------------------------------------------------------------=<BR>
// CBCFControlControl<BR>
//=-------------------------------------------------------------------------=<BR>
// our control.<BR>
//<BR>
class CBCFControlControl : public CInternetControl, public IBCFControl, public ISupportErrorInfo<BR>
{ <BR>
. . . <BR>
// OnData is called asynchronously as data for an <BR>
// object or property arrives...<BR>
virtual HRESULT OnData(DISPID propId, DWORD bscfFlag, IStream * strm, <BR>
DWORD dwSize); <BR>
// private state information.<BR>
//<BR>
BCFCONTROLCTLSTATE m_state; <BR>
. . .<BR>
</TT></FONT></P>
<P>Listing 11.2 shows your changes to the implementation of your constructor to enable
asynchronous property support. Your constructor implementation is trivial since your
only change is to replace the <TT>COleControl</TT> constructor declaration with <TT>CInternetControl</TT>.
Note the pearls of wisdom from the authors of the BaseCtl sample.
<H3><A NAME="Heading5"></A>Listing 11.2<SPACER TYPE="HORIZONTAL" SIZE="10"> BCFCONTROLCTL.CPP--BCFControlControl
Constructor Implementation Change</H3>
<P><FONT COLOR="#0066FF"><TT>//=-------------------------------------------------------------------------=<BR>
// CBCFControlControl::CBCFControlControl<BR>
//=-------------------------------------------------------------------------=<BR>
// "Being born is like being kidnapped. And then sold into slavery."<BR>
// - andy warhol (1928 - 87)<BR>
//<BR>
// Parameters:<BR>
// IUnknown * - [in]<BR>
//<BR>
// Notes:<BR>
//<BR>
#pragma warning(disable:4355) // using `this' in constructor<BR>
CBCFControlControl::CBCFControlControl<BR>
(<BR>
IUnknown *pUnkOuter<BR>
)<BR>
: CInternetControl(pUnkOuter, OBJECT_TYPE_CTLBCFCONTROL, (IDispatch *)this)<BR>
{<BR>
// initialize anything here <BR>
...<BR>
</TT></FONT></P>
<P>Listing 11.3 shows the <TT>OnData</TT> function that you added to your source
file. For now, you just add the function shell; you will add the specific implementation
after you add your data path property.
<H3><A NAME="Heading6"></A>Listing 11.3 <SPACER TYPE="HORIZONTAL" SIZE="10">BCFCONTROLCTL.CPP--OnData
Function</H3>
<P><FONT COLOR="#0066FF"><TT>... <BR>
HRESULT CBCFControlControl::OnData(DISPID propId, DWORD bscfFlag, IStream * strm,
<BR>
DWORD dwSize)<BR>
{<BR>
HRESULT hr = NOERROR; <BR>
return(hr); <BR>
}<BR>
</TT></FONT></P>
<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"></P>
<BLOCKQUOTE>
<P><B>NOTE:</B> We experienced some link problems when compiling our BCFControl sample
code, as follows: <TT>Unresolved external: CreateURLMoniker</TT> <TT>Unresolved external:
RegisterBindStatusCallback</TT> Even though the functions are declared in urlmon.h
and should be implemented in uuid.lib, we found that we had to link with Urlmon.lib
to resolve the functions.
</BLOCKQUOTE>
<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"><BR>
<BR>
Before you add your specific implementation code to support the asynchronous property,
you need to add the stock property <TT>ReadyState</TT> to your control.</P>
<P>You also need to add a user-defined property for your data path variable. This
property is used to store the location of the asynchronous properties data. This
location can be any valid pathname, including URL and UNC paths.</P>
<P>First you need to declare a dispid for your data path property (see Listing 11.4).
You use the OLE defined dispid for the <TT>ReadyState</TT> property.
<H3><A NAME="Heading7"></A>Listing 11.4 <SPACER TYPE="HORIZONTAL" SIZE="10">DISPIDS.H--Add
Data Path Property Dispid</H3>
<P><FONT COLOR="#0066FF"><TT>. . . <BR>
//=-------------------------------------------------------------------------=<BR>
// for the BCFControl control<BR>
// properties & methods<BR>
// <BR>
#define dispidAlignment 1<BR>
#define dispidCaptionMethod 2<BR>
#define dispidCaptionProp 3 <BR>
#define dispidTextDataPath 4 <BR>
. . .</TT></FONT></P>
<P>Next you add the two new properties to your ODL file (see Listing 11.5). Note
that you add only a method for getting the <TT>ReadyState</TT> property, and not
a method for setting the property, which has the effect of creating a read-only property.
<H3><A NAME="Heading8"></A>Listing 11.5 <SPACER TYPE="HORIZONTAL" SIZE="10">BCFCONTROL.ODL--BCFControl
ODL Implementation</H3>
<P><FONT COLOR="#0066FF"><TT>. . . <BR>
[uuid(317512F1-3E75-11d0-BEBE-00400538977D), helpstring("BCFControl Control"),<BR>
hidden, dual, odl]<BR>
interface IBCFControl : IDispatch<BR>
{<BR>
// properties<BR>
[id(dispidAlignment), propget] HRESULT Alignment([out, retval] long * Value);<BR>
[id(dispidAlignment), propput] HRESULT Alignment([in] long Value);<BR>
[id(DISPID_BACKCOLOR), propget] HRESULT BackColor([out, retval] OLE_COLOR * Value);<BR>
[id(DISPID_BACKCOLOR), propput] HRESULT BackColor([in] OLE_COLOR Value);<BR>
[id(DISPID_READYSTATE), propget] HRESULT ReadyState([out, retval] long * Value);<BR>
[id(dispidTextDataPath), propget] HRESULT TextDataPath([out, retval] BSTR * Value);<BR>
[id(dispidTextDataPath), propput] HRESULT TextDataPath([in] BSTR Value); <BR>
// methods . . .<BR>
</TT></FONT></P>
<P>You need to add a member variable to your state structure to store the state of
the control's asynchronous properties, and you also add a string length member that
will be used later in your persistence routines.</P>
<P>You also need to add your function prototypes of the property <TT>get/set</TT>
methods to your class header file (see Listing 11.6). Remember that the prototype
is generated automatically when the ODL file is compiled.</P>
<P>Finally you add a string member to hold the value of the property.
<H3><A NAME="Heading9"></A>Listing 11.6 <SPACER TYPE="HORIZONTAL" SIZE="10">BCFCONTROLCTL.H--ReadyState
Property Prototype</H3>
<P><FONT COLOR="#0066FF"><TT>. . . <BR>
typedef struct tagBCFCONTROLCTLSTATE<BR>
<BR>
{<BR>
<BR>
long lCaptionLength;<BR>
<BR>
long lAlignment;<BR>
<BR>
OLE_COLOR ocBackColor;<BR>
<BR>
long lReadyState;<BR>
<BR>
long lTextDataPathLength;<BR>
<BR>
} BCFCONTROLCTLSTATE; <BR>
//=-------------------------------------------------------------------------=<BR>
<BR>
// CBCFControlControl<BR>
<BR>
//=-------------------------------------------------------------------------= <BR>
. . . <BR>
// IBCFControl methods<BR>
<BR>
//<BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -