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

📄 ch04.htm

📁 本书详述了VC++环境下网络化多媒体对象技术编程
💻 HTM
📖 第 1 页 / 共 5 页
字号:
}; <BR>
for (int i=0;i&lt;sizeof(arr)/sizeof(arr[0]);i++) <BR>
{ <BR>
if (InlineIsEqualGUID(*arr[i],riid)) <BR>
return S_OK; <BR>
} <BR>
return S_FALSE; <BR>
} // constructor <BR>
CTracker::CTracker() <BR>
{ <BR>
AFX_MANAGE_STATE(AfxGetStaticModuleState()); // To keep the application running as
LONG as an <BR>
// OLE automation object is active <BR>
::AfxOleLockApp(); // setup our timer resolution <BR>
m_lTimeBegin = timeBeginPeriod(1); <BR>
m_lHiResTime = m_lLastHiResTime = timeGetTime(); // get the current date and time
<BR>
CTime oTimeStamp = CTime::GetCurrentTime(); CString cstrFileName; // create a file
name based on the date <BR>
cstrFileName.Format(_T(&quot;%s.tracklog&quot;), (LPCTSTR) // open a file <BR>
m_fileLog = fopen(cstrFileName, _T(&quot;a&quot;)); <BR>
<BR>
// if we have a file handle <BR>
if(m_fileLog) <BR>
{ <BR>
// output some starting information <BR>
fprintf(m_fileLog, _T(&quot;************************\n&quot;)); <BR>
fprintf(m_fileLog, _T(&quot;Start %s\n&quot;), <BR>
(LPCTSTR) oTimeStamp.Format(&quot;%B %#d, %Y, %I:%M %p&quot;)); <BR>
fprintf(m_fileLog, _T(&quot;\n&quot;)); <BR>
} <BR>
} // destructor <BR>
CTracker::~CTracker() <BR>
{ <BR>
AFX_MANAGE_STATE(AfxGetStaticModuleState()); // if we have a file handle <BR>
if(m_fileLog) <BR>
{ <BR>
// output some closing information <BR>
CTime oTimeStamp = CTime::GetCurrentTime(); <BR>
fprintf(m_fileLog, _T(&quot;\n&quot;)); <BR>
fprintf(m_fileLog, _T(&quot;End %s\n&quot;), <BR>
oTimeStamp.Format(&quot;%B %#d, %Y, %I:%M %p&quot;)); <BR>
fprintf(m_fileLog,_T(&quot;************************\n&quot;)); // close the file
<BR>
fclose(m_fileLog); <BR>
} <BR>
<BR>
// if we have valid timer services <BR>
if(m_lTimeBegin == TIMERR_NOERROR) <BR>
// reset the timer to its original state <BR>
timeEndPeriod(1); // no longer necessary to keep the application in memory <BR>
::AfxOleUnlockApp(); <BR>
}</TT></FONT></P>
<P>Finally you update the build settings for the project. Since the sample implementation
is using some timer functions defined in mmsystem.h, you also need to be linked with
the appropriate library file that contains their implementation. Under the <U>P</U>roject
menu, select the <U>S</U>ettings menu item. In the Project Settings dialog, from
the <U>S</U>ettings For drop-down list box, select the All Configurations entry.
Select the Link tab, and add the file winmm.lib to the Object/<U>l</U>ibrary modules
edit field. Click OK to close the dialog.</P>
<P>The basic support code needed for the sample implementation is now added. The
server will open a file in its constructor and leave the file open during its entire
lifetime. When the server is destroyed, the destructor will be called, and the file
will be closed.</P>
<P>The following section describes how to make the sample more meaningful by adding
methods and properties that are used to output data to the open file.
<H2><A NAME="Heading13"></A>Adding Methods</H2>
<P>An automation method consists of zero to <I>n </I>parameters and may or may not
have a return value. The term <I>method</I> is synonymous with function or subroutine,
depending on the particular language you are familiar with. Since your server is
<TT>IDispatch</TT>-based, you are limited to a specific set of data types. Only those
data types that are valid <TT>VARIANT</TT> data types can be passed or returned via
a method.</P>
<P>The rules for declaring parameters and how they are used is very much like those
for C++ and VB. Methods can pass parameters by value or by reference and may declare
them as optional, meaning that the parameter does not have to be supplied.</P>
<P>When passing a parameter by value, a copy of the data is sent to the method; when
passing a parameter by reference, the address of the parameter is passed, which allows
the method to change the data.</P>
<P>However, because you can't specify a default value in the traditional C++ sense,
optional parameters are handled a little differently than in C++. Optional parameters
must be passed as <TT>VARIANT</TT> data types, not as the actual data type they represent.</P>
<P>When using VB to access a method with optional parameters, VB will supply the
parameter if one has not been provided. With C++, you are still required to supply
a <TT>VARIANT</TT> parameter, even though it may not contain data.</P>
<P>As we stated at the beginning of the chapter, the sample Automation Server will
be used to log strings of data to a file. The server will define the method <TT>OutputLines</TT>
used by the user of the server to supply the string data that is written to the file.
The method will accept an array of strings and an optional indentation parameter
and will output the strings to the file. The indentation parameter is used to offset
the strings by <I>n </I>number of tab characters to provide simple, yet effective,
formatting to the data as it is output to the file.</P>
<P>Adding methods to an ATL project differs from the process for adding them with
MFC, which uses the ClassWizard that we are all familiar with. ATL uses a custom
ClassWizard that is accessed from the ClassView tab in the Project Workspace window
by right mouse clicking the interface that you are adding the method to. From the
ClassView tab in the Project Workspace window, select the <TT>ITracker</TT> class
from the list of <TT>ATLServer</TT> classes, click the right mouse button, and select
the Add <U>M</U>ethod menu item (see fig. 4.7). <A HREF="art/04/dfig07.jpg"><B><BR>
<BR>
FIG. 4.7</B></A> <I><BR>
Add a new method to the server object.</I></P>
<P>In the Add Method to Interface dialog (see fig. 4.8), add the Method <U>N</U>ame,
<TT>OutputLines</TT>, and the <U>P</U>arameters, <TT>[in] VARIANT * varOutputArray,
[in, optional] VARIANT varIndent, and [out, retval] VARIANT_BOOL * RetVal</TT>. Note
that you add all of the parameters and their corresponding IDL attributes within
this dialog. Table 4.2 contains a list of the parameter direction attributes that
you add and their meanings. You are not required to modify the IDL after the method
has been added. 
<TABLE BORDER="1">
	<CAPTION><B>Table 4.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"><TT>in</TT></TD>
		<TD ALIGN="LEFT" VALIGN="TOP">Parameter is passed from caller to callee.</TD>
	</TR>
	<TR ALIGN="LEFT" rowspan="1">
		<TD ALIGN="LEFT" VALIGN="TOP"><TT>out</TT></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"><TT>in</TT>, <TT>out</TT></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"><TT>out</TT>, <TT>retval</TT></TD>
		<TD ALIGN="LEFT" VALIGN="TOP">Parameter is the return value of the method and is returned from the callee to the
			caller.</TD>
	</TR>
</TABLE>
The <U>A</U>ttributes button displays a dialog for adding IDL attributes for the
entire function declaration. Click OK to close the dialog, and add the method to
your implementation. <A HREF="art/04/dfig08.jpg"><B><BR>
<BR>
FIG. 4.8</B></A> <I><BR>
Define the <TT>OutputLines </TT>method.</I></P>
<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"></P>


<BLOCKQUOTE>
	<P><B>NOTE:</B> All optional parameters must be of type <TT>VARIANT</TT>, and they
	must fall at the end of the parameter list. Optional parameters are not managed in
	any way by OLE. It is the server application's responsibility to determine whether
	the <TT>VARIANT</TT> parameter passed to the method contains data and to either use
	the data passed to the method or convert the data to a useful type if possible, or
	to ignore the parameter if invalid data was passed and use the default value if appropriate,
	or to inform the user of an error condition if one of the above conditions was not
	met.

</BLOCKQUOTE>

<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"> The ATL ClassWizard
will add an entry to the IDL file (see Listing 4.6) for the new method and will also
add the function prototype (see Listing 4.7) and implementation (see Listing 4.8)
to the header and source file of the object that the method is being added to. Note
that the ClassWizard automatically added the <TT>AFX_MANAGE_STATE</TT> macro to the
implementation, which is required for MFC support.
<H3><A NAME="Heading14"></A>Listing 4.6 ATLSERVER.IDL--OutputLines Method Added to
the IDL File by the ATL ClassWizard</H3>
<P><FONT COLOR="#0066FF"><TT><BR>
. . . [ <BR>
object, <BR>
uuid(03699612-809E-11D0-BEFF-00400538977D), <BR>
dual, <BR>
helpstring(&quot;ITracker Interface&quot;), <BR>
pointer_default(unique), <BR>
hidden <BR>
] <BR>
interface ITracker : IDispatch <BR>
{ <BR>
[id(1), helpstring(&quot;method OutputLines&quot;)] HRESULT OutputLines( <BR>
[in] VARIANT * varOutputArray, [in,optional] VARIANT <BR>
[out,retval] VARIANT_BOOL * RetVal); <BR>
}; . . . </TT></FONT></P>
<H3><A NAME="Heading15"></A>Listing 4.7 TRACKER.H--OutputLines Function Prototype
Added to the Tracker.h File</H3>
<P>
<P><FONT COLOR="#0066FF"><TT><BR>
. . . // ISupportsErrorInfo <BR>
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid); // ITracker <BR>
public: <BR>
STDMETHOD(OutputLines)(/*[in]*/ VARIANT * varOutputArray, <BR>
/*[in,optional]*/ VARIANT varIndent, <BR>
/*[out,retval]*/ VARIANT_BOOL * RetVal); protected: <BR>
FILE * m_fileLog; <BR>
long m_lTimeBegin; <BR>
long m_lHiResTime; <BR>
long m_lLastHiResTime; . . . </TT></FONT></P>
<H3><A NAME="Heading17"></A>Listing 4.8 TRACKER.CPP--OutputLines Function Implementation
Added to the Tracker.cpp File</H3>
<P>
<P><FONT COLOR="#0066FF"><TT><BR>
STDMETHODIMP CTracker::OutputLines(VARIANT * varOutputArray, VARIANT varIndent, <BR>
VARIANT_BOOL * RetVal) <BR>
{ <BR>
AFX_MANAGE_STATE(AfxGetStaticModuleState()) // TODO: Add your implementation code
here return S_OK; } </TT></FONT></P>
<P><TT>OutputLines</TT> is defined as having two parameters: <TT>varOutputArray</TT>,
as a <TT>VARIANT</TT> passed by reference, that will contain a string array of data
to output to the file; and <TT>varIndent</TT>, as a <TT>VARIANT</TT> passed by value,
that is also an optional parameter indicating the amount of indentation when writing
the string data to the file. The third parameter is actually the return type of the
method and is defined as a <TT>VARIANT</TT>_<TT>BOOL</TT>.</P>
<P>See <A HREF="ch03.htm">Chapter 3</A> regarding the use of Boolean data types and
the differences between VB and VC++. <BR>
<BR>
<IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"></P>


<BLOCKQUOTE>
	<P><B>NOTE:</B> If you are converting an existing ODL file to IDL, be sure to change
	all Boolean declarations to <TT>VARIANT_BOOL</TT>. Boolean in ODL refers to a 2-byte
	signed short data type, whereas Boolean in IDL is a 1-byte unsigned char data type
	and is not compatible with VB. To further complicate matters <TT>VARIANT_BOOL</TT>
	is an unrecognized data type in ODL, though not in IDL.

</BLOCKQUOTE>

<P><IMG SRC="bar.gif" WIDTH="480" HEIGHT="6" ALIGN="BOTTOM" BORDER="0"> <BR>
<BR>
Due to data type restrictions imposed by OLE Automation, you cannot pass arrays as
pa-rameters of methods. You can, however, pass <TT>VARIANT</TT> data types that can
contain arrays, thus the reason for defining <TT>varOutputArray</TT> as a <TT>VARIANT</TT>.
You are also required to pass <TT>varOutputArray</TT> by reference because the array
stored in the <TT>VARIANT</TT> does not get copied over when it is passed by value.</P>
<P>Optional parameters must fall at the end of the parameter list and must be of
type <TT>VARIANT</TT>. <TT>varIndent</TT> is an optional parameter that indents the
text output as an added formatting feature.</P>
<P>The last step is to add the <TT>m_lIndent</TT> member variable to the class declaration,
which is used in the <TT>OutputLines</TT> method implementation and later as a property
of the server (see Listing 4.9).
<H3><A NAME="Heading19"></A>Listing 4.9 TRACKER.H--m_1Indent Member Variable Added
to the Class Definition</H3>
<P>
<P><FONT COLOR="#0066FF"><TT><BR>
. . . // ISupportsErrorInfo <BR>
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid); // ITracker <BR>
public: <BR>
STDMETHOD(OutputLines)(/*[in]*/ VARIANT * varOutputArray, / *[in,optional]*/ VARIANT
varIndent, /*[out,retval]*/ VARIANT_BOOL * RetVal); protected: <BR>
FILE * m_fileLog; <BR>
long m_lTimeBegin; <BR>
long m_lHiResTime; <BR>
long m_lLastHiResTime; <BR>
long m_lIndent; }; </TT></FONT></P>
<P>Before adding the <TT>OutputLines</TT> implementation, you need to update the
constructor to initialize the <TT>m_lIndent</TT> member variable to a valid state
(see Listing 4.10).
<H3><A NAME="Heading21"></A>Listing 4.10 TRACKER.CPP--Member Initialization in the

⌨️ 快捷键说明

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