⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch10.htm

📁 用VC开发activeX控件的电子书,很不错的
💻 HTM
📖 第 1 页 / 共 5 页
字号:
		<TD ALIGN="LEFT" VALIGN="TOP">out</TD>
		<TD ALIGN="LEFT" VALIGN="TOP">Parameter is returned from callee to caller.</TD>
	</TR>
	<TR ALIGN="LEFT" rowspan="1">
		<TD ALIGN="LEFT" VALIGN="TOP">in, out</TD>
		<TD ALIGN="LEFT" VALIGN="TOP">Parameter is passed from caller to callee, and the callee returns a parameter.</TD>
	</TR>
	<TR ALIGN="LEFT" rowspan="1">
		<TD ALIGN="LEFT" VALIGN="TOP">out, retval</TD>
		<TD ALIGN="LEFT" VALIGN="TOP">Parameter is the return value of the method and is returned from callee to the caller.</TD>
	</TR>
</TABLE>
<BR>
Next compile the type library to create a new C++ header file defining your control
and its interfaces. After compiling, open the BCFControlInterfaces.h file, and copy
the <TT>CaptionMethod</TT> line.
<H3><A NAME="Heading14"></A>Listing 10.9 <SPACER TYPE="HORIZONTAL" SIZE="10">BCFCONTROLINTERFACES.H--Interface
File Created from the ODL File</H3>
<P><FONT COLOR="#0066FF"><TT>interface DECLSPEC_UUID(&quot;317512F1-3E75-11d0-BEBE-00400538977D&quot;)<BR>
IBCFControl : public IDispatch<BR>
{<BR>
public:<BR>
virtual /* [id] */ HRESULT STDMETHODCALLTYPE CaptionMethod( <BR>
/* [in] */ BSTR bstrCaption,<BR>
/* [optional][in] */ VARIANT varAlignment,<BR>
/* [retval][out] */ long __RPC_FAR *lRetVal) = 0; <BR>
<BR>
};</TT></FONT></P>
<P>Open the BCFControlCtl.h file, and paste the line into your class header file,
making sure that you remove the <TT>= 0</TT> from the prototype. To aid your implementation,
you also need to add an enumeration and two member variables to your class definition
(see Listing 10.10).
<H3><A NAME="Heading15"></A>Listing 10.10 <SPACER TYPE="HORIZONTAL" SIZE="10">BCFCONTROLCTL.H--Updated
Control Class Header File</H3>
<P><FONT COLOR="#0066FF"><TT>... <BR>
#include &quot;BCFControlInterfaces.H&quot;<BR>
#include &quot;Dispids.H&quot; <BR>
#include &quot;alignmentenums.h&quot; <BR>
typedef struct tagBCFCONTROLCTLSTATE <BR>
{<BR>
long lCaptionLength;<BR>
long lAlignment;<BR>
} BCFCONTROLCTLSTATE; <BR>
//=--------------------------------------------------------------------------=<BR>
// CBCFControlControl<BR>
//=--------------------------------------------------------------------------=<BR>
// our control.<BR>
//<BR>
class CBCFControlControl : public COleControl, public IBCFControl, <BR>
public ISupportErrorInfo <BR>
{<BR>
public:<BR>
// IUnknown methods<BR>
//<BR>
DECLARE_STANDARD_UNKNOWN(); <BR>
// IDispatch methods<BR>
//<BR>
DECLARE_STANDARD_DISPATCH(); <BR>
// ISupportErrorInfo methods<BR>
//<BR>
DECLARE_STANDARD_SUPPORTERRORINFO(); <BR>
// IBCFControl methods<BR>
//<BR>
// TODO: copy over the method declarations from BCFControlInterfaces.H<BR>
// don't forget to remove the PURE from them.<BR>
//<BR>
STDMETHOD(CaptionMethod)(THIS_ BSTR bstrCaption, VARIANT varAlignment,<BR>
long FAR* lRetVal);<BR>
STDMETHOD_(void, AboutBox)(THIS); <BR>
// OLE Control stuff follows:<BR>
//<BR>
CBCFControlControl(IUnknown *pUnkOuter);<BR>
virtual ~CBCFControlControl(); <BR>
// static creation function. all controls must have one of these!<BR>
//<BR>
static IUnknown *Create(IUnknown *); <BR>
private:<BR>
// overridables that the control must implement.<BR>
//<BR>
STDMETHOD(LoadBinaryState)(IStream *pStream);<BR>
STDMETHOD(SaveBinaryState)(IStream *pStream);<BR>
STDMETHOD(LoadTextState)(IPropertyBag *pPropertyBag, IErrorLog *pErrorLog);<BR>
STDMETHOD(SaveTextState)(IPropertyBag *pPropertyBag, BOOL fWriteDefault);<BR>
STDMETHOD(OnDraw)(DWORD dvAspect, HDC hdcDraw, LPCRECTL prcBounds,<BR>
LPCRECTL prcWBounds, HDC hicTargetDev, BOOL fOptimize);<BR>
virtual LRESULT WindowProc(UINT msg, WPARAM wParam, LPARAM lParam);<BR>
virtual BOOL RegisterClassData(void); <BR>
virtual HRESULT InternalQueryInterface(REFIID, void **);<BR>
virtual BOOL BeforeCreateWindow(DWORD *pdwWindowStyle, <BR>
DWORD *pdwExWindowStyle, LPSTR pszWindowTitle); <BR>
// private state information.<BR>
//<BR>
BCFCONTROLCTLSTATE m_state;<BR>
BCFCONTROLCTLSTATE m_DefaultState; <BR>
protected:<BR>
// storage variable for the caption<BR>
LPTSTR m_lptstrCaption;<BR>
}; <BR>
...</TT></FONT></P>
<P>The enumeration, which is in the include file Alignmentenums.h, is your list of
supported alignment styles (see Listing 10.11).
<H3><A NAME="Heading16"></A>Listing 10.11 <SPACER TYPE="HORIZONTAL" SIZE="10">ALIGNMENTENUMS.H--Alignment
Styles Enumeration</H3>
<P><FONT COLOR="#0066FF"><TT>typedef enum tagAlignmentEnum<BR>
{<BR>
EALIGN_LEFT = 0,<BR>
EALIGN_CENTER = 1,<BR>
EALIGN_RIGHT = 2,<BR>
}EALIGNMENT; <BR>
#define EALIGN_LEFT_TEXT &quot;Left&quot;<BR>
#define EALIGN_CENTER_TEXT &quot;Center&quot; <BR>
#define EALIGN_RIGHT_TEXT &quot;Right&quot;</TT></FONT></P>
<P>You added the <TT>lAlignment</TT> member variable into the <TT>BCFCONTROLCTLSTATE</TT>
structure, which is a member variable declared as <TT>m_state</TT>, in your control
class. Define the <TT>m_lptstrCaption</TT> variable as a member of the control class
rather than a member of the state structure--for persistence reasons; for now, suffice
it to say that you will make your life a lot easier by declaring your member variables
this way. You will address persistence and the use of the state structures in more
detail a little later in this chapter in the section &quot;Persistence.&quot; Also,
declare the member variable, <TT>lCaptionLength</TT>, which is related to the <TT>m_lptstrCaption</TT>
variable, which is needed for persistence reasons; for now, however, it will serve
no purpose.</P>
<P>In addition to the <TT>m_state</TT> variable, you need to add another member of
the same type called <TT>m_DefaultState</TT>. This structure is initialized in the
constructor to all of the default values that your control supports (see Listing
10.12). These values will be used later in your persistence implementation to determine
whether the properties have changed from their default values, and if not, the properties
will not be persisted. See the section entitled &quot;Persistence&quot; for more
information.
<H3><A NAME="Heading17"></A>Listing 10.12 <SPACER TYPE="HORIZONTAL" SIZE="10">BCFCONTROLCTL.CPP--Member
Variable Initialization</H3>
<P><FONT COLOR="#0066FF"><TT>//=--------------------------------------------------------------------------=<BR>
// CBCFControlControl::CBCFControlControl<BR>
//=--------------------------------------------------------------------------=<BR>
// &quot;Being born is like being kidnapped. And then sold into slavery.&quot;<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>
: COleControl(pUnkOuter, OBJECT_TYPE_CTLBCFCONTROL, (IDispatch *)this)<BR>
{<BR>
// initialize anything here ...<BR>
//<BR>
memset(&amp;m_state, 0, sizeof(BCFCONTROLCTLSTATE));<BR>
memset(&amp;m_DefaultState, 0, sizeof(BCFCONTROLCTLSTATE)); <BR>
// NULL terminate the string reference<BR>
m_lptstrCaption = new TCHAR[1];<BR>
m_lptstrCaption[0] = `\0'; <BR>
// set the alignment to the default of left<BR>
m_DefaultState.lAlignment = m_state.lAlignment = EALIGN_LEFT;<BR>
} <BR>
#pragma warning(default:4355) // using `this' in constructor</TT></FONT></P>
<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"></P>


<BLOCKQUOTE>
	<P><B>NOTE:</B> If you like interesting quotations, you will find that the BaseCtl
	code is sprinkled with them in appropriate places, as can be seen in Listing 10.12.

</BLOCKQUOTE>

<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"><BR>
<BR>
The <TT>CaptionMethod</TT> contains all of the code for getting the caption and the
alignment style and, like your MFC and ATL implementations, deals correctly with
the optional parameter.</P>
<P>Listing 10.13 shows the implementation of the <TT>CaptionMethod</TT>. Since the
method is used both for your <TT>IDispatch</TT> implementation and your custom interface,
it is implemented slightly different from its MFC counterpart. First you declare
an <TT>HRESULT</TT> return type. This return value is used by OLE to determine whether
the method call succeeded. The string parameter is passed in differently also. All
strings are passed as <TT>UNICODE</TT> in OLE. This is true even for MFC; the only
difference is that MFC hides from the developer the implementation details of how
the strings are managed; the developer simply uses the appropriate string data type
based on the target application and platform, that is, Win32 <TT>ANSI</TT> versus
Win32 <TT>UNICODE</TT>.
<H3><A NAME="Heading18"></A>Listing 10.13<SPACER TYPE="HORIZONTAL" SIZE="10"> BCFCONTROLCTL.CPP--CaptionMethod
Implementation</H3>
<P><FONT COLOR="#0066FF"><TT>STDMETHODIMP CBCFControlControl::CaptionMethod(BSTR
bstrCaption,<BR>
VARIANT varAlignment, long FAR * lRetVal)<BR>
{<BR>
HRESULT hResult = S_OK; <BR>
// return value initialized to failure result<BR>
*lRetVal = FALSE; <BR>
MAKE_ANSIPTR_FROMWIDE(lpctstrCaption, bstrCaption); <BR>
// if the variant is a long just use the value<BR>
if(VT_I4 == varAlignment.vt)<BR>
{<BR>
// assign the value to our member variable<BR>
m_state.lAlignment = varAlignment.lVal; <BR>
// set the return value<BR>
*lRetVal = TRUE;<BR>
}<BR>
// if the user didn't supply an alignment parameter we will assign the default<BR>
else if(VT_ERROR == varAlignment.vt || VT_EMPTY == varAlignment.vt)<BR>
{<BR>
// assign the value to our member variable<BR>
m_state.lAlignment = EALIGN_LEFT; <BR>
// set the return value<BR>
*lRetVal = TRUE;<BR>
}<BR>
else<BR>
{<BR>
// get a variant that we can use for conversion purposes<BR>
VARIANT varConvertedValue; <BR>
// initialize the variant<BR>
::VariantInit(&amp;varConvertedValue); <BR>
// see if we can convert the data type to something useful<BR>
// VariantChangeTypeEx() could also be used<BR>
if(S_OK == ::VariantChangeType(&amp;varConvertedValue,<BR>
(VARIANT *) &amp;varAlignment, 0, VT_I4))<BR>
{<BR>
// assign the value to our member variable <BR>
switch(varConvertedValue.lVal)<BR>
{<BR>
case EALIGN_CENTER: <BR>
m_state.lAlignment = EALIGN_CENTER;<BR>
break;<BR>
case EALIGN_RIGHT:<BR>
m_state.lAlignment = EALIGN_RIGHT;<BR>
break;<BR>
default:<BR>
m_state.lAlignment = EALIGN_LEFT;<BR>
break;<BR>
} <BR>
// set the return value<BR>
*lRetVal = TRUE;<BR>
}<BR>
else<BR>
{<BR>
// at this point we could either throw an error <BR>
// indicating there was a problem converting <BR>
// the data or change the return type of the method<BR>
// and return the HRESULT value from the <BR>
// the &quot;VariantChangeType&quot; call.<BR>
}<BR>
} <BR>
// if everything was OK<BR>
if(TRUE == *lRetVal)<BR>
{<BR>
// if we have a string<BR>
if(lpctstrCaption != NULL)<BR>
{<BR>
// if we have a string<BR>
if(m_lptstrCaption)<BR>
{<BR>
// delete the existing string<BR>
delete [] m_lptstrCaption; <BR>
// clear the reference just to be safe<BR>
m_lptstrCaption = NULL;<BR>
} <BR>
// allocate a new string<BR>
m_lptstrCaption = new TCHAR[lstrlen(lpctstrCaption) + 1]; <BR>
// assign the string to our member variable<BR>
lstrcpy(m_lptstrCaption, lpctstrCaption);<BR>
}<BR>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -