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

📄 ch21.htm

📁 VC使用大全。里面集合了VC使用的各种使用技巧。非常有用。
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<HTML>
<HEAD>
<TITLE>Special Edition Using Visual C++ 5 - Chapter 21</TITLE>
<LINK REL="Next" HREF="ch22.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch22.htm">
<LINK REL="Previous" HREF="ch20.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch20.htm"></HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">

<H2><B>Chapter 21</B></H2>
<H2><B>The Active Template 
Library</B></H2>
<hr>
<P>The Active Template Library, ATL, is a collection of C++ class templates that you can use to build ActiveX controls. These small controls generally do not use MFC at all. Writing an ActiveX control with ATL requires a lot more 
knowledge of COM and interfaces than writing an MFC ActiveX control, because MFC protects you from a lot of low-level COM concepts. Using ATL is not for the timid, but it pays dividends in smaller, tighter controls. This chapter will rewrite the Dieroll 
control of <A HREF="index17.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index17.htm" target="text">Chapter 17</A>, &quot;Building an ActiveX Control,&quot; and <A HREF="index20.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index20.htm" target="text">Chapter 20</A>, &quot;Building an Internet ActiveX Control,&quot; by using ATL. You will learn the important 
COM/ActiveX concepts that were skimmed over while you were using MFC. For a fuller examination of these concepts, be sure to read the electronic copy of &#147;ActiveX Programming with Visual C++,&#148; which is included in its entirety on the CD that comes 
with this book.</P>
<ul>
<li> <B>What is the Active Template Library?</B></P>
<P>  Using MFC makes controls easy to write, but big. The power of templates lets you leave MFC behind.</P>
<li> <B>ATL Wizards</B></P>
<P>  An AppWizard to create the project 
and an ObjectWizard to create a control or a property page make getting started simple.</P>
<li> <B>Properties and Persistence</B></P>
<P>  Exposing properties in an ATL control is a job for your custom interface.</P>
<li> <B>Events</B></P>
<P>  Your 
control can notify the application using it that something important has happened</P>
<li> <B>Using the control</B></P>
<P>  Microsoft's Control Pad is an easy way to test your control. So is Internet Explorer.</P>
</ul>
<H3><B>Why use the ATL?</B></H3>

<P>Building an ActiveX Control with MFC is quite simple, as you saw in Chapters <A HREF="index17.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index17.htm" target="text">17</A>, &#147;Building an ActiveX Control,&#148; and <A HREF="index20.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index20.htm" target="text">20</A>, &#147;Building an Internet ActiveX 
Control.&#148; You can get by without really knowing what a COM interface is, or how to use a type library. Your control can use all sorts of handy MFC classes, like CString and CWnd, can draw itself using CDC member functions, and more. The only downside 
is that users of your control need the MFC DLLs, and if those DLLs aren't on their system already, the delay while 700K or so of CAB file downloads will be significant.</P>
<P>The alternative is to get the ActiveX functionality from the Active Template 
Library (ATL) and to call Win32 SDK functions, just as C programmers did when writing for Windows in the days before Visual C++ and MFC. The Win32 SDK is a lot to learn, and won't be covered fully in this chapter. The good news is, if you're familiar with 
major MFC classes, like CWnd and CDC, you'll recognize a lot of these SDK functions even if you've never seen them before: many of the MFC member functions are just wrappers for SDK functions.</P>
<P>How much download time can you save? The MFC control 
from <A HREF="index20.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index20.htm" target="text">Chapter 20</A>, &#147;Building an Internet ActiveX Control.&#148; is about 30K, plus of course the MFC DLLs. The ATL control built in this chapter is at most 100K and is fully self-contained. With a few tricks you 
could get it down to 50K of control and 20K for the ATL DLL&#151;one-tenth the size of the total control and DLL from <A HREF="index20.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index20.htm" target="text">Chapter 20</A>!</P>
<H3><B>Using AppWizard to Get Started</B></H3>
<P>There's an AppWizard that knows 
how to make ATL controls, and it makes your job quite a bit simpler than it would have been without the wizard. As always, choose <U>F</U>ile, <U>N</U>ew and click the Projects tab on the New dialog. Fill in an appropriate directory and name the project 
DieRollControl, as shown in Figure 21.1. Click OK.</P>
<A HREF="KKfig01.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch21/KKfig01.gif"><b>Fig. 21.1</b></A>
<P><I>AppWizard makes creating an ATL control simple.</I></P>
<blockquote><p><img src="note.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/note.gif">
<P>It's tempting to name the project DieRoll, but 
later in this process you will be inserting a control into the project&#151;that control will be called DieRoll, so to avoid name conflicts, choose a longer name for the project.</P>
<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>
<P>There is only one step in the 
ATL COM AppWizard and it is shown in Figure 21.2. The default choices&#151;DLL control, no merging proxy/stub code, no MFC support&#151;are the right ones for this project. The file extension will be DLL rather than OCX as it was for MFC controls, but 
that's not an important difference. Click Finish.</P>
<A HREF="KKfig02.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch21/KKfig02.gif"><b>Fig. 21.2</b></A>
<P><I>Create a DLL control.</I></P>
<P>The New Project Information dialog box, shown in Figure 21.3, confirms the choices you have made. Click OK to 
create the project. </P>
<A HREF="KKfig03.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch21/KKfig03.gif"><b>Fig. 21.3</b></A>
<P><I>Your ATL choices are summarized before you create the project.</I></P>
<H3><B>Using the Object Wizard</B></H3>
<P>The ATL COM AppWizard created seven files, but you don't 
have a skeleton control yet. First you have to follow the instructions included in the Step 1 dialog box, and insert an ATL object into the project. </P>
<P><B>Adding a Control to the project</B></P>
<P>Choose <U>I</U>nsert, New <U>A</U>TL Object from the 
menu bar. This brings up the ATL Object Wizard, shown in Figure 21.4.</P>
<A HREF="KKfig04.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch21/KKfig04.gif"><b>Fig. 21.4</b></A>
<P><I>Add an ATL Control to Your Project.</I></P>
<P>There are several kinds of ATL objects you can add to your project, but at 
the moment you are interested only in controls, so select Controls in the list box on the left. The choices in the list box on the left become Full Control, Internet Explorer Control, or Property Page. If you know for certain that this control would be 
used only in Internet Explorer, perhaps as part of an intranet project, you could choose Internet Explorer Control and save a little space. This dieroll control might end up in any browser, in a VB app, or anywhere else for that matter, so a Full Control 
is the way to go. You'll add a property page later in this chapter. Select Full Control and click Next.</P>
<P><B>  Naming the control</B></P>
<P>Now the ATL Object Wizard Properties Dialog box appears. The first tab is the Names tab. Here you can 
customize all the names used for this control. Enter DieRoll for the short name of DieRoll and the rest will default to names based on it, as shown in Figure 21.5. You could change these names if you wanted, but there is no need to. Note that the 
<U>T</U>ype name, <font color="#008000">DieRoll Class</font>, is the name that will appear in the <U>I</U>nsert <U>O</U>bject dialog box of most containers. Since the MFC version of DieRoll is probably already in your Registry, having a different name for 
this version is actually a good thing. On other projects you might consider changing the type name.</P>
<A HREF="KKfig05.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch21/KKfig05.gif"><b>Fig. 21.5</b></A>
<P><I>Set the names of the files and the control.</I></P>
<P><B> Setting control attributes</B></P>

<P>Click the Attributes tab. Leave the default values: <U>A</U>partment Threading Model, <U>D</U>ual Interface, and <U>Y</U>es for Aggregation. Select the check boxes Support <U>I</U>SupportErrorInfo and Support Connection <U>P</U>oints. Leave Free 
Threaded <U>M</U>arshaler deselected, as shown in Figure 21.6 atuvc06.pcx. Each of these choices is discussed in the paragraphs that follow.</P>
<A HREF="KKfig06.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch21/KKfig06.gif"><b>Fig. 21.6</b></A>
<P><I>Set the COM properties of your control</I></P>

<P><B> Threading models</B></P>
<P>Avoid selecting the Single-Thread model even if your controls do not have any threading. In order to be sure that no two functions of such a control are running at the same time, all calls to methods of a single-threaded 
control must be marshalled through a proxy, which slows execution significantly. The Apartment setting is a better choice for new controls.. </P>
<P>The Apartment model refers to STA, or Single-Threaded Apartment model. This means that access to any 
resources shared by instances of the control (globals and statics) is through serialization. Instance data&#151;local automatic variables and objects dynamically allocated on the heap&#151;does not need this protection. This makes STA controls faster than 
single-threaded controls. Internet Explorer exploits STA in controls it contains. </P>
<blockquote><p><img src="tip.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/tip.gif">
<P>If the design for your control includes a lot of globals and statics, it may be a great deal of work to use the Apartment model. 
This is not a good reason to write a single-threaded control; it is a good reason to redesign your control as a more object-oriented system. </P>
<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>
<P>The Free threading (Multithreaded Apartment or MTA) model refers to 
controls that are threaded and that already include protection against thread collisions. While it might seem like a great idea to write a multithreaded control, using such a control in a non threaded or STA container will result in marshalling again, this 
time to protect the container against having two functions called at once. This, too, introduces inefficiencies. As well, there will be significant extra work for you, the developer, to create a free threaded control, since you must add the thread 
collision protection.</P>
<P>The Both option in the threading column asks the wizard to make a control that can be STA or MTA, avoiding inefficiences when used in a container that is single-threaded or STA, and exploiting the power of MTA models when 
available. You will have to add the threading-protection work, just as when you write an MTA control.</P>
<P>At the moment, controls for Internet Explorer should be STA. DCOM controls that may be accessed by several connections at once can benefit from 
being MTA. </P>
<P><B>  Dual and Custom interfaces</B></P>
<P>COM objects communicate through <I>interfaces</I>, a collection of function names that describe the possible behavior of a COM object. To use an interface, you get a pointer to it and then call 
a member function of the interface. All Automation servers and ActiveX controls have an IDispatch interface in addition to any other interfaces that may be specific to what the server or control is for. To call a method of a control, you can use the 
Invoke() method of the IDispatch interface, passing in the <font color="#008000">dispid</font> of the method you wish to invoke. (This technique was developed so that methods could be called from Visual Basic and other pointerless languages.)</P>
<P>Simply 
put, a <I>dual-interface</I> control lets you call methods both ways: by using a member function of a custom interface, or by using IDispatch. MFC controls only use IDispatch, but this is slower than using a custom interface. The Interface column on this 
dialog box lets you choose Dual or Custom: custom leaves IDispatch out of the picture altogether. Select Dual so that the control can be used from Visual Basic if necessary.</P>
<P><B> Aggregation</B></P>
<P>The third column, Aggregation, governs whether 
or not a COM class can use this COM class by containing a reference to an instance of it. Choosing Yes means that other COM objects may use this class; No means they cannot; Only means they must: this object cannot stand alone.</P>
<P><B> Other control 
settings</B></P>
<P>Selecting support for ISupportErrorInfo means that your control will be able to return richer error information to the container. Selecting support for Connection Points is vital for a control, like this one, that will fire events. 
Selecting Free-Threaded Marshaler is not required for an STA control.</P>
<P>Click the Miscellaneous tab and examine all the settings, which can be left at their default values (see Figure 21.7). The control should be opaque, with a solid background, and 
should use a normalized DC even though that's slightly less efficient, because your draw code will be much easier to write. </P>
<blockquote><p><img src="tip.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/tip.gif">
<P>If you'd like to see how a DC is normalized for an ATL control, remember that all the ATL 
source is available to you, just as the MFC source is. In Program Files\DevStudio\VC\atl\include\ATLCTL.CPP, you will find <font color="#008000">CComControlBase::OnDrawAdvanced()</font>, which normalizes a DC and calls <font color="#008000">OnDraw()</font> 
for you.</P>
<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>
<A HREF="KKfig07.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch21/KKfig07.gif"><b>Fig. 21.7</b></A>
<P><I>Leave the Miscellaneous properties at the defaults.</I></P>
<P><B> Supporting Stock Properties</B></P>
<P>Click the Stock Properties tab to 
specify which stock properties the control will support. To add support for a stock property, select it in the left Not Supported list box, then click the <font color="#008000">&gt;</font> button and it will be moved to the Supported list on the right. Add 
support for Background Color and Foreground Color, as shown in Figure 21.8. If you plan to support a lot of properties, use the <font color="#008000">&gt;&gt;</font> button to move them all to the supported list and then move back the ones you don't want 
to support.</P>
<A HREF="KKfig08.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch21/KKfig08.gif"><b>Fig. 21.8</b></A>
<P><I>Support Background Color and Foreground Color.</I></P>
<P>Click OK on the Object Wizard to complete the control creation. At this point you can build the project if you wish, though 
the control does nothing at the moment.</P>
<H3><B>Adding Properties to the Control</B></H3>
<P>The MFC versions of Dieroll featured three stock properties: <font color="#008000">BackColor</font>, <font color="#008000">ForeColor</font> and <font 
color="#008000">ReadyState</font>. The first two have been added already, but the <font color="#008000">ReadyState</font> stock properties must be added by hand. As well there are two custom properties, <font color="#008000">Number</font> and <font 
color="#008000">Dots</font>, and an asynchronous property, <font color="#008000">Image</font>.</P>
<P><B>  Code From Object Wizard</B></P>
<P>A COM class that implements or uses an interface does so by inheriting from a class representing that interface. 
Listing 21.1 shows all the classes that CDieRoll inherits from.</P>
<P><I>Listing 21.1&#151;Excerpt from DieRollControl.h&#151;Inheritance</I></P>
<pre><font color="#008000">class ATL_NO_VTABLE CDieRoll : </font></pre>
<pre><font color="#008000">     
public CComObjectRootEx&lt;CComSingleThreadModel&gt;,</font></pre>
<pre><font color="#008000">     public CComCoClass&lt;CDieRoll, &amp;CLSID_DieRoll&gt;,</font></pre>
<pre><font color="#008000">     public CComControl&lt;CDieRoll&gt;,</font></pre>

<pre><font color="#008000">     public CStockPropImpl&lt;CDieRoll, IDieRoll, &amp;IID_IDieRoll, &amp;LIBID_DIEROLLCONTROLLib&gt;,</font></pre>
<pre><font color="#008000">     public IProvideClassInfo2Impl&lt;&amp;CLSID_DieRoll, NULL, 
&amp;LIBID_DIEROLLCONTROLLib&gt;,</font></pre>
<pre><font color="#008000">     public IPersistStreamInitImpl&lt;CDieRoll&gt;,</font></pre>
<pre><font color="#008000">     public IPersistStorageImpl&lt;CDieRoll&gt;,</font></pre>
<pre><font color="#008000">     
public IQuickActivateImpl&lt;CDieRoll&gt;,</font></pre>
<pre><font color="#008000">     public IOleControlImpl&lt;CDieRoll&gt;,</font></pre>

⌨️ 快捷键说明

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