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

📄 ch20.htm

📁 VC使用大全。里面集合了VC使用的各种使用技巧。非常有用。
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<P>To implement the Windowless Activation option in Dieroll, override <font color="#008000">CDierollCtrl::GetControlFlags()</font> like this:</P>

<pre><font color="#008000">DWORD CDierollCtrl::GetControlFlags()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    return COleControl::GetControlFlags()| windowlessActivate;</font></pre>

<pre><font color="#008000">}</font></pre>

<P>Add the function quickly by right-clicking <font color="#008000">CDierollCtrl</font> in Class View and choosing Add Function. If you do this to Dieroll, build it, and reload the web page that uses it, you will notice no apparent effect, because Dieroll 
is such a lean control. You will at least notice that it still functions perfectly, and doesn't mind not having a window.</P>

<P>The next two options, Unclipped Device Context and Flicker-free Activation, are not available to windowless controls. In a control with a window, choosing Unclipped Device Context means that you are completely sure that you never draw outside the 
client rectangle of the control. Skipping the checks that make sure you don't means your control runs faster, though it could mean trouble if you have an error in your draw code. If you were to do this in Dieroll, the override of <font 
color="#008000">GetControlFlags()</font>would look like this:</P>

<pre><font color="#008000">DWORD CDierollCtrl::GetControlFlags()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    return COleControl::GetControlFlags()&amp; ~clipPaintDC;</font></pre>

<pre><font color="#008000">}</font></pre>

<P>Don't try to combine this with windowless activation: it doesn't do anything.</P>

<P>Flicker free activation is useful for controls which draw their inactive and active views identically. (Think back to <A HREF="index15.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index15.htm" target="text">Chapter 15</A>, &quot;Building an ActiveX Server Application,&quot; in which the server object was 
drawn in dimmed colors when the objects were inactive.)If there is no need to redraw, because the drawing code is the same, you can select this option and skip the second draw. Your users won't see an annoying flicker as the control activates, and 
activation will be a tiny bit quicker. If you were to do this in Dieroll, the <font color="#008000">GetControlFlags()</font>override would be:</P>

<pre><font color="#008000">DWORD CDierollCtrl::GetControlFlags()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    return COleControl::GetControlFlags()| noFlickerActivate;</font></pre>

<pre><font color="#008000">}</font></pre>

<P>Like unclipped device context, don't try to combine this with windowless activation: it doesn't do anything.</P>

<P>Mouse pointer notifications, when inactive, enable more controls to turn off the activate when visible option. If the only reason to be active is to have a window to process mouse interactions, this option will divert those interactions to the 
container through an <font color="#008000">IPointerInactive</font> interface. To enable this option in an application that is already built, you override <font color="#008000">GetControlFlags()</font>again:</P>

<pre><font color="#008000"> DWORD CDierollCtrl::GetControlFlags()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    return COleControl::GetControlFlags()| pointerInactive;</font></pre>

<pre><font color="#008000">}</font></pre>

<P>Now your code will receive <font color="#008000">WM_SETCURSOR</font> and <font color="#008000">WM_MOUSEMOVE</font> messages through message map entries, even though you have no window. The container, whose window your control is using, will send these 
messages to you through the IPointerInactive interface.</P>

<P>The other circumstance under which you might want to process window messages while still inactive, and so without a window, is if the user drags something over your control and drops it. The control needs to activate at that moment, so that it has a 
window to be a drop target. You can arrange that with an override to <font color="#008000">GetActivationPolicy()</font>:</P>

<pre><font color="#008000">DWORD CDierollCtrl::GetActivationPolicy()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    return POINTERINACTIVE_ACTIVATEONDRAG;</font></pre>

<pre><font color="#008000">}</font></pre>

<P>Don't bother doing this if your control isn't a drop target, of course.</P>

<P>The problem with relying on the container to pass on your messages through the <font color="#008000">IPointerInactive</font> interface is that the container may have no idea such an interface exists, and have no plans to pass your messages on with it. 
If you think your control might end up in such a container, then don't remove the <font color="#008000">OLEMISC_ACTIVATEWHENVISIBLE</font> flag from the block of code, like the one in Listing 20.6</P>

<P><I>Listing 20.6&#151;Excerpt from DierollCtl.cpp&#151;Finetuning activates when </I><I>visible</I></P>

<pre><font color="#008000">/////////////////////////////////////////////////////////////////////////////</font></pre>

<pre><font color="#008000">// Control type information</font></pre>

<pre><font color="#008000">static const DWORD BASED_CODE _dwDierollOleMisc =</font></pre>

<pre><font color="#008000">    OLEMISC_ACTIVATEWHENVISIBLE |</font></pre>

<pre><font color="#008000">    OLEMISC_SETCLIENTSITEFIRST |</font></pre>

<pre><font color="#008000">    OLEMISC_INSIDEOUT |</font></pre>

<pre><font color="#008000">    OLEMISC_CANTLINKINSIDE |</font></pre>

<pre><font color="#008000">    OLEMISC_RECOMPOSEONRESIZE;</font></pre>

<pre><font color="#008000">IMPLEMENT_OLECTLTYPE(CDierollCtrl, IDS_DIEROLL, _dwDierollOleMisc)</font></pre>

<P>Instead, combine another flag, <font color="#008000">OLEMISC_IGNOREACTIVATEWHENVISIBLE</font>, with these flags using the bitwise <I>or</I> operator. This oddly named flag is meaningful to containers that understand <font 
color="#008000">IPointerInactive</font>, and means, in effect &quot;I take it back, don't activate when visible after all.&quot; Containers that don't understand <font color="#008000">IPointerInactive</font> don't understand this flag either, and your 
control will activate when visible, and thus be around to catch mouse messages in these containers.</P>

<P>Optimized drawing code is only useful to controls that will be sharing the container with a number of other drawing controls. As you may recall from <A HREF="index06.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index06.htm" target="text">Chapter 6</A>, &quot;Drawing On the Screen,&quot; the typical 
pattern for drawing a view of any kind is to set the brush, pen, or other GDI object to a new value, saving the old, then use the GDI object, then restore it to the saved value. If there are a number of controls doing this in turn, all those restore steps 
could be skipped in favour of one restore at the end of all the drawing. The container saves all the GDI object values before instructing the controls to redraw, and restores them all afterwards.</P>

<P>If you would like your control to take advantage of this, there are two changes to be made. First, if a pen or other GDI object is to remain connected between draw calls, it must not go out of scope. That means any local pens, brushes, and fonts should 
be converted to member variables so that they stay in scope between function calls. Second, the code to restore the old objects should be surrounded by an if statement that calls <font color="#008000">COleControl::IsOptimizedDraw()</font>to see if the 
restoration is necessary. A typical draw routine would set up the colors, then proceed like this:</P>

<pre><font color="#008000">...</font></pre>

<pre><font color="#008000">if(!m_pen.m_hObject)</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    m_pen.CreatePen(PS_SOLID, 0, forecolor);</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">if(!m_brush.m_hObject)</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    m_brush.CreateSolidBrush(backcolor);</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">CPen* savepen = pdc-&gt;SelectObject(&amp;m_pen);</font></pre>

<pre><font color="#008000">CBrush* savebrush = pdc-&gt;SelectObject(&amp;m_brush);</font></pre>

<pre><font color="#008000">...</font></pre>

<pre><font color="#008000">// use device context</font></pre>

<pre><font color="#008000">...</font></pre>

<pre><font color="#008000">if(!IsOptimizedDraw())</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    pdc-&gt;SelectObject(savepen);</font></pre>

<pre><font color="#008000">    pdc-&gt;SelectObject(savebrush);</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">...</font></pre>

<P>The device context has the addresses of the member variables, so when it lets go of them at the direction of the container, their <font color="#008000">m_hObject</font> member becomes NULL. As long as it is not <font color="#008000">NULL</font> there 
is no need to reset the device context, and if this container supports optimized drawing code there is no need to restore it either.</P>

<P>If you select this optimized drawing code option with AppWizard, the <font color="#008000">if</font> statement with the call to <font color="#008000">IsOptimizedDraw()</font>is added to your draw code, with some comments to remind you what to do.</P>

<P>The last of the optimization options, loads properties asynchronously, and(?) is covered in the next section.</P>

<H3><A ID="I8" NAME="I8"><B>Speeding Control Coads with Asynchronous Properties</B></A></H3>

<P>Asynchronous refers to spreading out activities over time, and not insisting that one activity be complete before another can begin. In the context of the web, it's worth harking back to the features that made Netscape Navigator better than Mosaic, way 
back when it was first released. The number one benefit cited by people who were on the web then was that the Netscape browser, unlike Mosaic, could display text while pictures were still loading. This is classic asynchronous behavior. You don't have to 
wait until the huge image files have transferred to see what the words on the page are and whether the images are worth waiting for.</P>

<P>Faster Internet connections and more compact image formats have lessened some of the concerns about waiting for images. Still, being asynchronous is a good thing. For one thing, waiting for video clips, sound clips, and executable code has made many 
web users long for the good old days when they only had to wait 30 seconds for pages to find all their images.</P>

<P><A ID="I9" NAME="I9"><B>Properties</B></A></P>

<P>The die that comes up in your web page is the default die appearance. There's no way for the user to access the properties of the control. The web page developer can, using the &lt;PARAM&gt; tag inside the &lt;OBJECT&gt; tag.(Browsers that ignore 
OBJECT also ignore PARAM.)Here's the PARAM tag to add to your HTML between &lt;OBJECT&gt; and &lt;/OBJECT&gt; to include a die with a number rather than dots:</P>

<pre><font color="#008000">&lt;PARAM NAME=&quot;Dots&quot; value=&quot;0&quot;&gt;</font></pre>

<P>The PARAM tag has two attributes: NAME provides a name that matches the external ActiveX name(<font color="#008000">Dots</font> in this case)and value provides the value(0, or <font color="#008000">FALSE</font>, in this case.)The die displays with a 
number.</P>

<P>In order to demonstrate the value of asynchronous properties, Dieroll needs to have some big properties. So, since this is a demonstration application, the next step is to add a big property. A natural choice is to give the user more control over the 
appearance of the die. The user(which means the web page designer if the control is being used in a web page)can specify an image file and use that as the background for the die. Before you see how to make that happen, imagine what the web page reader will 
have to wait for when loading a page that uses Dieroll:</P>

<ul>

<li> The HTML has to be loaded from the server</P>

<li> The browser lays out the text and non-text elements and starts to display text</P>

<li> The browser searches the Registry for the CLSID of the control</P>

<li> If necessary, the control is downloaded, using the CODEBASE parameter</P>

<li> The control properties are initialized using the PARAM tags</P>

<li> The control runs and draws itself</P>

</ul>

<P>When Dieroll gains another property, an image file that might be quite large, there will be another delay while the image file is retrieved from wherever it is kept. If nothing happens in the meantime, the web page reader will eventually tire of 
staring at an empty square and go away to another page. Using asynchronous properties means that the control can draw itself roughly and start to be useful, even while the large image file is still being downloaded. For Dieroll, drawing the dots on a plain 
background using <font color="#008000">GetBackColor()</font>will do until the image file is ready.</P>

<P><A ID="I10" NAME="I10"><B>Using BLOBs</B></A></P>

<P>A BLOB is a Binary Large OBject. It's a generic name for things like the image file we are about to add to the Dieroll control. The way a control talks to a BLOB is through a moniker. That's not new, it's just that monikers have always been hidden away 
inside OLE. If you already understood them, you will have a great deal more to learn about them, because things are changing with the introduction of asynchronous monikers. If you've never heard of them before, no problem. Eventually there will be all 
sorts of asynchronous monikers, but at the moment only URL monikers have been implemented. These are a way for ActiveX to connect BLOB properties to URLs. If you're prepared to trust ActiveX to do this for you, you can achieve some amazing things. The 
remainder of this subsection explains how to work with URL monikers to load BLOB properties asynchronously.</P>

<P>Remember, the idea here is that the control will start drawing itself even before it has all of its properties. Your OnDraw()code will be structured like this:</P>

<pre><font color="#008000">// prepare to draw</font></pre>

<pre><font color="#008000">if(AllPropertiesAreLoaded)</font></pre>

⌨️ 快捷键说明

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