﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-激烈振动</title><link>http://www.cnblogs.com/vibration/</link><description>Visit My MSN Space</description><language>zh-cn</language><lastBuildDate>Mon, 06 Jul 2009 11:55:28 GMT</lastBuildDate><pubDate>Mon, 06 Jul 2009 11:55:28 GMT</pubDate><ttl>60</ttl><item><title>ATL3.0组件注册bug的解决方法</title><link>http://www.cnblogs.com/vibration/archive/2006/03/24/357700.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Fri, 24 Mar 2006 05:09:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2006/03/24/357700.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/357700.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2006/03/24/357700.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/357700.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/357700.html</trackback:ping><description><![CDATA[<p>ATL3.0编写的组件在注册时，如果组件所在目录包含中文路径，不能在注册表生产正确的路径，从而产生虽然注册成功，却不能使用的问题，因为在注册表记录的DLL路径中文部分有乱码。这个问题很久以前就发现，一直没有解决。前段时间在网上搜索到解决方案，并<A href="http://vibration.cnblogs.com/archive/2005/09/07/231915.html">转载</a>在blog上，却一直没有实际试用。今天企图使用，却发现不成功，昏倒，试了几次都不行。看来网上的代码还是不能轻信。不知道文章的作者有没有实际调试成功，不过思路是没错的，因此自己改了下，调通了，这里记录一下。<br><br>解决方案：修改STAREG.H文件，修改196行开始的AddChar 和 AddString函数，修改后的代码如下：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;AddChar(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pch)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">if&nbsp;(nPos&nbsp;==&nbsp;nSize)&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;realloc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">fix&nbsp;register&nbsp;bug&nbsp;with&nbsp;chinese&nbsp;path</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(nPos&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;nSize&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nSize&nbsp;</span><span style="COLOR: #000000">*=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(LPTSTR)&nbsp;CoTaskMemRealloc(p,&nbsp;nSize</span><span style="COLOR: #000000">*</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(TCHAR));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p[nPos</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pch;<br>#ifndef&nbsp;_UNICODE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(IsDBCSLeadByte(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pch))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p[nPos</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">(pch&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;TRUE;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;AddString(LPCOLESTR&nbsp;lpsz)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;USES_CONVERSION;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPCTSTR&nbsp;lpszT&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;OLE2CT(lpsz);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">lpszT)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddChar(lpszT);<br>#ifndef&nbsp;_UNICODE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">fix&nbsp;bug&nbsp;with&nbsp;chinese&nbsp;path</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(IsDBCSLeadByte(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">lpszT))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpszT</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpszT</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;TRUE;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span></div>
编译时必须使用_ATL_STATIC_REGISTRY，即静态链接ATL代码，而不使用ATL.dll，否则无效，因为正是ATL.dll的代码出了问题。<br>
<img src ="http://www.cnblogs.com/vibration/aggbug/357700.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48008/" target="_blank">IBM发布全球首款开源智能编译器</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>奇怪的引用错误及解决方法</title><link>http://www.cnblogs.com/vibration/archive/2005/11/16/277823.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Wed, 16 Nov 2005 07:52:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2005/11/16/277823.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/277823.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2005/11/16/277823.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/277823.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/277823.html</trackback:ping><description><![CDATA[碰到一个奇怪的问题。 <BR><BR><STRONG><U>症状</U></STRONG> <BR>在一个.net workspace中包含多个project，其中两个project应用了同一个.net assamply。这两个project其中一个编译正常，另一个则报错： <BR><FONT face="Times New Roman" color=#000000 size=3>error CS0246: The type or namespace name '***' could not be found (are you missing a using directive or an assembly reference?) </FONT><BR>居然说我没有正确引用，可是检查项目设置都没有问题。关闭workspace在打开，好了。第二天再编译，又有问题，晕了<IMG height=20 src="http://www.cnblogs.com/Emoticons/QQ/noidea.gif" width=20 border=0> <BR><STRONG><BR><U>错误原因</U></STRONG> <BR>google半天未果，自己研究。发现被引用的项目有一个Copy Local属性，默认为true，就是把应用的assamply拷贝到输出目录下。原来两个project都企图把同一个assamply拷贝过来，而拷贝成功后还锁定了这个文件。这样第一个项目操作成功并锁定文件后，第二个项目拷贝就失败了，因为无法覆盖被锁定的文件。 <BR><BR><U><STRONG>解决方法</STRONG> <BR></U>原因找到了，解决就不难了，把其中一个项目中的引用assambly的Copy Local属性改成false，再编译，就一切OK了<IMG height=19 src="http://www.cnblogs.com/Emoticons/emhot.gif" width=19 align=absMiddle border=0>&nbsp;同理，如果有多个project引用同一assamply，除了其中一个的Copy Local属性为true，其他改成false就行了。GAC中的assambly不存在此问题，因为默认Copy Local属性为false。 <BR><img src ="http://www.cnblogs.com/vibration/aggbug/277823.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48007/" target="_blank">IE颓势不减 微软下月公布最新浏览器架构</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>OLE2T在VS2003中转换中文失败的问题及解决方法</title><link>http://www.cnblogs.com/vibration/archive/2005/11/04/269008.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Fri, 04 Nov 2005 09:03:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2005/11/04/269008.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/269008.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2005/11/04/269008.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/269008.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/269008.html</trackback:ping><description><![CDATA[以前VC6的代码，从xml文件中读取属性文字（中文），返回BSTR类型，用OLE2T转换，然后显示，一直工作很正常，用来做本地化，比修改Res文件要方便的多。<BR><BR>同样的代码，在VS2003里面居然不能工作了，调试，发现BSTR返回正常，而通过OLE2T转换居然就全转成&#8220;???&#8221;了，晕。<IMG src="http://www.cnblogs.com/Emoticons/emrosesad.gif" align=absMiddle border=0><BR><BR>做了无数尝试，发现用unicode编译就正常。可是原来的VC6项目不论是否Unicode编译都正常的，要把一个项目全部转成Unicode还是有相当工作量的，似乎也并没有必要。<BR><BR>寻找解决方法，看了一堆ATL的代码，ATL7提供了OLE2T的代替品COLE2T，用一个重载是COLE2T(bstr, codepage)，发现给把第二个参数设置成CP_ACP，即ANSI code page就转换正常了。原来是codepage的问题，ATL搞了一大堆代码来获取转换用的codepage，看得人晕，而我要的只是ANSI code page。<BR><BR>继续找，终于找到了，ATL的代码通过一条宏定义进行了分支。如果定义了宏<SPAN style="COLOR: #0000ff">_CONVERSION_DONT_USE_THREAD_LOCALE</SPAN>，则对当前code page的请求简单返回CP_ACP，否则，就搞了一大堆代码从当前线程中查询。那么我们要做的就是定义这个宏就可以了。试了一下，果然如此<IMG src="http://www.cnblogs.com/Emoticons/emteeth.gif" align=absMiddle border=0><BR><BR>最终解决方案，在stdafx.h的所有包含文件前面加上：<BR><SPAN style="COLOR: #0000ff">#define</SPAN> _CONVERSION_DONT_USE_THREAD_LOCALE<BR><BR>搞定<IMG src="http://www.cnblogs.com/Emoticons/emsmiled.gif" align=absMiddle border=0><img src ="http://www.cnblogs.com/vibration/aggbug/269008.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48002/" target="_blank">竞争日趋激烈 微软欲借 Windows 7 扭转战局</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>标题栏按钮的WTL实现</title><link>http://www.cnblogs.com/vibration/archive/2005/09/20/240252.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Tue, 20 Sep 2005 02:45:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2005/09/20/240252.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/240252.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2005/09/20/240252.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/240252.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/240252.html</trackback:ping><description><![CDATA[<P><U><STRONG>起因</STRONG></U></P>
<P>上次完成了<A href="/vibration/archive/2005/09/14/236926.html">CAppBar</A>的代码后，就一直想在标题栏的关闭按钮前面加一个按钮，来控制自动隐藏的设置。在标题栏上加按钮并不算特别麻烦，主要是控制WM_NCPAINT，把想要的效果画上去。当然，原理不复杂，要实现的好却不容易。上网搜了一下，有一些简单的例子用来讲述原理，没有找到比较好的实现，更谈不上可复用的代码了，那么只好自己实现了。</P>
<P><U><STRONG>原理</STRONG></U></P>
<P>首选必须明白原理，想在标题栏上创建CButton这样窗口按钮的努力是徒劳的。标题栏属于Non-Client区域，不能在其上创建子窗口，唯一的方法就是响应WM_NCPAINT消息，通过Window DC画上去，当然，还需要处理一些其他的鼠标消息以得到按钮的效果。这样，实现的思路就和CAppBar差不多了，再创建一个模板类，于是，CCaptionButton&lt;T&gt;就诞生了。 先看看效果 <BR><IMG height=107 src="http://www.cnblogs.com/images/cnblogs_com/vibration/pic.JPG" width=110 border=0> </P>
<P><U><STRONG>按钮图片</STRONG></U></P>
<P>因为是画上去的按钮，我们需要准备一些按钮图片。一个按钮至少需要3个图片来表示3个状态: <BR></P>
<UL>
<LI>正常状态 
<LI>按下状态 
<LI>鼠标停留状态</LI></UL>另外，如果需要下面两种额外状态，就需要一共提供5个按钮图片 <BR>
<UL>
<LI>Checked状态 
<LI>Disabled状态</LI></UL>
<P>我们通过一个ImageList来组织这些按钮图片。一幅象下面这样的图片资源可以产生一个按钮需要的ImageList，当然也可以通过其他方式实现。 <BR><IMG height=16 src="http://www.cnblogs.com/images/cnblogs_com/vibration/pin.JPG" width=80 border=0> <BR>当添加一个标题栏按钮时，我们需要这些按钮图片，参数的类型是HIMAGELIST </P>
<P><U><STRONG>添加标题栏按钮</STRONG></U></P>
<P>我们需要支持多个标题栏按钮，因此在CCaptionButton类中，通过一个vector来维护所有按钮的信息。具体实现不多说了，就讲怎么使用吧，添加按钮的方法就是：</P><PRE> int AddButton(UINT uID, int cx, int cy, HIMAGELIST himl, LPCTSTR lpszHint=NULL);
</PRE>
<P>其中，uID是按钮的ID，当按钮被点击时，会有一个WM_COMMAND消息发送给窗口，uID为参数。因此，处理标题栏按钮点击的方法和处理普通按钮完全相同。cx和cy定义了按钮的宽度和高度，这个尺寸必须和按钮图片相符。himl则包含了3－5幅图片，表示按钮不同状态下的样子。最后，lpszHint是按钮的tooltip提示文字。</P>
<P><U><STRONG>控制按钮位置</STRONG></U></P>
<P>加入的按钮显示在标题栏的什么地方呢？自动控制按钮的位置似乎是一个可重用的类应该完成的任务。在类的实现中，我尝试自动计算标题栏上的空白区域，让我们添加的标题栏按钮靠窗口右边已有按钮排列。然而，我发现，由于存在许多不同的窗口样式，如是否有最小化按钮，是否有问号按钮，是否窄标题栏(即ToolWindow)，自动计算很容易产生错误。不如让继承类来决定如何排放按钮位置。因此，提供了下面这个函数供继承类重载：</P><PRE> POINT GetButtonPos(int index);
</PRE>
<P>CCaptionButton为这个函数提供了一个默认的实现，但是，这个实现比较简单，只有在窗口为ToolWindow，并且没有任何系统按钮的情况下才能正常显示。通过重载GetButtonPos函数，实际上我们得到了比自动计算强的多的功能，即我们可以在任意位置显示按钮，甚至可以控制按钮水平或者垂直排列，就象例子程序中看到的那样。</P>
<P><U><STRONG>使用方法</STRONG></U></P>
<P>总结一下使用方法</P>
<UL>
<LI>把CCaptionButton作为一个父类继承 
<LI>使用CHAIN_MSG_MAP把消息传递到CCaptionButton类 
<LI>调用AddButton函数添加一个或多个按钮 
<LI>重载GetButtonPos函数提供每个按钮的显示位置 
<LI>处理标题栏按钮产生的Command消息 
<LI>可以调用CheckButton改变按钮的Check状态 
<LI>可以调用EnableButton改变按钮的Enable状态 </LI></UL>
<P><U><STRONG>示例程序</STRONG></U></P>
<P>示例程序中使用了5个标题按钮，并配合使用了<A href="/vibration/archive/2005/09/14/236926.html">CAppBar</A>类，以实现桌面停靠的功能。5个标题按钮的排列使用了普通方式和垂直排列的方式，通过继承GetButtonPos函数实现。其中图钉按钮控制AppBar窗口的自动隐藏设置；其他4个按钮使窗口停靠到桌面的一边；并且把停靠到底部的按钮设置成Disabled，可以看到不同的效果</P>
<P><A href="/Files/vibration/CaptionButton_Demo.zip">下载示例程序</A> </P><img src ="http://www.cnblogs.com/vibration/aggbug/240252.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48001/" target="_blank">上海电信计划2012年80%用户实现100M带宽</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>AppBar的WTL实现</title><link>http://www.cnblogs.com/vibration/archive/2005/09/14/236926.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Wed, 14 Sep 2005 09:05:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2005/09/14/236926.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/236926.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2005/09/14/236926.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/236926.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/236926.html</trackback:ping><description><![CDATA[关于Docking Window的文章有很多，基本都是讲主程序内部的工具栏小窗口的Docking，看看代码，一般都很复杂。关于桌面Docking的文章并不多见。实际上从Windows95开始，Win32 API就提供了一个叫做SHAppBarMessage的函数，用于实现完全等同于Windows Task Bar的功能。即可以停靠在屏幕在任意一边，并把自己排除到桌面空间之外。当其他应用程序窗口最大化的时候，不占据Task Bar的空间。同时，也可以设置成自动隐藏，让出所有的桌面空间。这样的窗口，就称为AppBar。<BR><BR>象QQ这样的程序可以停靠在窗口的一边，也可以自动隐藏，但似乎和AppBar的行为还是有不少差距的。本文提供的是对标准AppBar的一个实现。<BR><BR>利用SHAppBarMessage函数实现一个AppBar并不困难，<A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_int/shell_int_programming/appbars.asp">这篇文章</A>介绍了几乎所有实现细节，但所提供的例子却是SDK风格的代码，基本没有实际使用价值。但是对于SDK文档是一个很好的补充，很多SDK中没有说清楚的问题在文中给出了解释。<BR><BR>另一个问题是，SHAppBarMessage函数并没有提供我想当然认为应该实现的功能。比如对拖动的支持，比如自动隐藏窗口的隐藏和出现功能都必须额外的代码实现。SHAppBarMessage函数所做的主要工作似乎是划分屏幕，使其他窗口不会占用AppBar的空间。当然，能实现这个也足够了，毕竟，没有SHAppBarMessage函数，其他功能肯定都可以实现，而这个划分屏幕的功能我不知道该怎么做。<BR><BR>写一个可重用的AppBar基础类的愿望马上出现在我头脑中。WTL由于其超低的耦合性成为我必然的选择。模板类CAppBar&lt;T&gt;就是工作的结果。这个类不只是对SHAppBarMessage函数的简单封装，同时提供了通过拖动实现停靠或脱离屏幕的功能，并提供自动隐藏的实现。<BR><BR>任何从CWindowImpl直接或间接继承的弹出式窗口类都可以使用CAppBar。使用的方法很简单：<BR>&nbsp;&nbsp;&nbsp; 1、把CAppBar作为一个父类继承<BR>&nbsp;&nbsp;&nbsp;&nbsp;2、使用CHAIN_MSG_MAP把消息传递给CAppBar<BR>&nbsp;&nbsp;&nbsp; 3、在窗口创建时调用InitAppBar函数，参数可选<BR>这样，这个窗口就具备了AppBar的功能了，下面你就可以通过拖动把它停靠在屏幕边上了。<BR>当然，也可以通过调用DockAppBar停靠或脱离；或者调用SetAutoHide改变自动隐藏的设置。<BR>如果在停靠状态改变时需要有特殊操作，可以重载OnDockingChanged函数。<BR><BR>基本就是这样，代码很简单，就象其他WTL类一样。希望下一版的WTL可以收录它<IMG src="http://www.cnblogs.com/Emoticons/emsmilep.gif" align=absMiddle border=0><BR><BR><A href="/Files/vibration/AppBarTest.zip">下载例子程序</A><BR><img src ="http://www.cnblogs.com/vibration/aggbug/236926.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48000/" target="_blank">数万名网友签名抗议星际争霸2取消局域网功能</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>招聘C++和C#开发工程师</title><link>http://www.cnblogs.com/vibration/archive/2005/09/09/233322.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Fri, 09 Sep 2005 07:04:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2005/09/09/233322.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/233322.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2005/09/09/233322.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/233322.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/233322.html</trackback:ping><description><![CDATA[<DIV>招人了，需要比较扎实的C++基础，并能够使用C#开发，C++基础好的话，C#学一下也挺快，所以C#经验不作强制要求。工作地点在上海浦东，靠近科技馆。月薪应该在5k-8k左右。欢迎把简历投递到：<A href="mailto:atahr@ata.net.cn">atahr@ata.net.cn</A> 并抄送给我：<A href="mailto:yaozhifeng@ata.net.cn">yaozhifeng@ata.net.cn</A> &nbsp; <BR>有任何问题可email给我。下面是发布在51job的广告，直接拷贝过来了。 <BR></DIV><BR>
<DIV>
<TABLE style="WIDTH: 604px; HEIGHT: 864px" cellSpacing=0 cellPadding=0 width=604 border=0>
<TBODY>
<TR>
<TD bgColor=#e2e2e2 colSpan=2>&nbsp;<IMG height=15 src="http://images.51job.com/im/space.gif" width=1><B>招聘职位</B> </TD></TR>
<TR align=right>
<TD colSpan=2>
<TABLE cellSpacing=0 cellPadding=0 width="96%" border=0>
<TBODY>
<TR>
<TD><B>系统开发中心</B> </TD></TR>
<TR>
<TD>
<TABLE width="95%" align=right border=0>
<TBODY>
<TR>
<TD>地&nbsp;&nbsp;&nbsp;&nbsp;址：浦东民生路1399号信息大厦首层</TD></TR>
<TR>
<TD>邮政编码：200135</TD></TR>
<TR>
<TD>联&nbsp;系&nbsp;人：杨小姐</TD></TR>
<TR>
<TD>电子邮箱：<A href="http://www.cnblogs.com/vibration/vibration/tr/TrOutSend.php?type=1&amp;url=mailto:atahr@ata.net.cn">atahr@ata.net.cn</A> </TD></TR>
<TR>
<TD></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD>&nbsp;</TD></TR>
<TR>
<TD>
<TABLE width="98%" align=right border=0>
<TBODY>
<TR>
<TD bgColor=#f2f2f2 colSpan=2>&nbsp;&nbsp;<B>高级软件工程师</B> </TD></TR>
<TR>
<TD>
<TABLE width="95%" align=center border=0>
<TBODY>
<TR>
<TD colSpan=2>电子邮箱：<A href="http://www.cnblogs.com/vibration/vibration/tr/TrOutSend.php?type=1&amp;jobid=6998370&amp;url=mailto:atahr@ata.net.cn">atahr@ata.net.cn</A> </TD></TR>
<TR>
<TD colSpan=2 height=4></TD></TR>
<TR>
<TD width="50%">发布日期：2005-09-08</TD>
<TD width="50%">工作地点：上海市</TD></TR>
<TR>
<TD>招聘人数：若干</TD>
<TD>学&nbsp;&nbsp;&nbsp;&nbsp;历：本科</TD></TR>
<TR vAlign=top>
<TD>工作年限：三年以上</TD>
<TD>薪水范围：面议</TD></TR>
<TR vAlign=top>
<TD>外语要求：英语&nbsp;熟练</TD>
<TD>接受简历语言：中文或英文</TD></TR>
<TR>
<TD colSpan=4></TD></TR>
<TR>
<TD colSpan=2 height=4></TD></TR>
<TR>
<TD colSpan=2><B>职位描述：</B> </TD></TR>
<TR>
<TD colSpan=2>职责描述： <BR>1、 熟悉C++语言，三年以上Visual C++开发经验 <BR><BR>2、 熟悉ATL/WTL以及Windows SDK开发 <BR><BR>3、 一年以上的.net项目经验, 精通.net体系应用开发，精通C#桌面应用开发技术 <BR><BR>4、 深入理解面向对象开发思想并具有实际开发经验 <BR><BR>5、 熟悉XML语言，熟练使用DOM模型操作XML文档 <BR><BR>6、 熟悉各种数据结构并能灵活运用，有使用STL的开发经验 <BR><BR>7、 较强的分析、设计能力（有大型项目分析、设计经验者优先） <BR><BR>8、 有综合运用各种技术，并具有创新能力 <BR><BR>9、 能够阅读和查找英文资料 <BR></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></DIV><img src ="http://www.cnblogs.com/vibration/aggbug/233322.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47999/" target="_blank">Silverlight打造杰克逊纪念专题</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>ATL组件中文路径注册问题(转载)</title><link>http://www.cnblogs.com/vibration/archive/2005/09/07/231915.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Wed, 07 Sep 2005 09:11:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2005/09/07/231915.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/231915.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2005/09/07/231915.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/231915.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/231915.html</trackback:ping><description><![CDATA[<P>ATL组件注册的一个很糟糕的BUG，以至于需要通过修改ATL源码来解决。记录在此，方便下次重装机器后使用。</P>
<P>&nbsp; 我曾用ATL写过一个COM组件(MBCS下编译),如果安装在中文路径下的话,注册就会失败.<BR>&nbsp; 为什么会失败?<BR>&nbsp; 打开ATL的源文件statreg.h,可以找到函数BOOL AddString(LPCOLESTR lpsz),他被<BR>组件的UpdateRegistry所调用,他又调用了BOOL AddChar(const TCHAR* pch).问题就<BR>出现在这两个函数中。请看:<BR>&nbsp;&nbsp;BOOL AddString(LPCOLESTR lpsz)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;USES_CONVERSION;<BR>&nbsp;&nbsp;&nbsp;LPCTSTR lpszT = OLE2CT(lpsz);<BR>&nbsp;&nbsp;&nbsp;while (*lpszT)<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;AddChar(lpszT);<BR>&nbsp;&nbsp;&nbsp;&nbsp;lpszT++;&nbsp;<A href="file://%20note/">// note</A>! @1<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;return TRUE;<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;BOOL AddChar(const TCHAR* pch)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;if (nPos == nSize) // realloc&nbsp;@3<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;nSize *= 2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;p = (LPTSTR) CoTaskMemRealloc(p, nSize*sizeof(TCHAR));<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;p[nPos++] = *pch;<BR>#ifndef _UNICODE<BR>&nbsp;&nbsp;&nbsp;if (IsDBCSLeadByte(*pch))<BR>&nbsp;&nbsp;&nbsp;&nbsp;p[nPos++] = *(pch + 1);&nbsp;<A href="file://note/">file://note</A>! @2<BR>#endif<BR>&nbsp;&nbsp;&nbsp;return TRUE;<BR>&nbsp;&nbsp;}<BR>&nbsp;当我们不是使用UNICODE时,如果遇到一个汉字的话,标注@2行识别整个汉字,存入缓冲区.但是pch变量仍然指向<BR>汉字的第一个字节,返回到@1行时,lpszT++后指向了该汉字的第二个字节!以后又把该汉字的第二字节当成一个独立的字<BR>符再次处理一遍.所以就产生了乱码.(致使组件注册的信息有一部分是错误的)<BR>&nbsp;怎么解决?<BR>&nbsp;由上面的分析,很容易得到解决的办法:<BR>&nbsp;&nbsp;BOOL AddString(LPCOLESTR lpsz)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;USES_CONVERSION;<BR>&nbsp;&nbsp;&nbsp;LPCTSTR lpszT = OLE2CT(lpsz);<BR>&nbsp;&nbsp;&nbsp;while (*lpszT)<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;AddChar(lpszT);<BR>&nbsp;&nbsp;&nbsp;&nbsp;lpszT++;&nbsp;<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;return TRUE;<BR>&nbsp;&nbsp;}<BR>/*******************************************************************<BR>&nbsp;* This function cause some error in hanzi.<BR>&nbsp;* &nbsp;Modified by L.C. ,Nov 12th,2001<BR>&nbsp;*******************************************************************/<BR>/********************************************************************<BR>&nbsp;&nbsp;BOOL AddChar(const TCHAR* pch)<BR>&nbsp;********************************************************************/<BR>&nbsp;&nbsp;BOOL AddChar(const TCHAR* &amp;pch)&nbsp;<A href="file://we'll/">file://we'll</A> modify the pch value<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;if (nPos == nSize) // realloc<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;nSize *= 2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;p = (LPTSTR) CoTaskMemRealloc(p, nSize*sizeof(TCHAR));<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;p[nPos++] = *pch;<BR>#ifndef _UNICODE<BR>&nbsp;&nbsp;&nbsp;if (IsDBCSLeadByte(*pch))<BR>/*******************************************************************<BR>&nbsp;&nbsp;&nbsp;&nbsp;p[nPos++] = *(pch + 1);&nbsp;<BR>********************************************************************/<BR>&nbsp;&nbsp;&nbsp;&nbsp;p[nPos++] = *( ++ pch);<BR>#endif<BR>&nbsp;&nbsp;&nbsp;return TRUE;<BR>&nbsp;&nbsp;}<BR>&nbsp;还有什么错误？<BR>&nbsp;请观察@3行，如果阅读一下这个类的源代码（１８０行开始），很明显会有缓冲区溢出的危险：<BR>在非UNICODE情况下，nPos要加两次，而进入这段代码时有可能是nPos=nSize-1.如果是这样，恐怕程序的<BR>会有一些无法预测的行为（虽然几率很小：在 rgs文件中出现大段中文的可能性不多）。修改实际上比较<BR>容易，将if (nPos == nSize) 变为if (nPos == nSize-1)即可。（当然有很多别的方法）<BR>&nbsp;结论<BR>&nbsp;如果你的组件有可能出现在中文路径下的话（使用MBCS），建议你在编译时使用_ATL_STATIC_REGISTRY<BR>编译，并且在编译前修改ATL中相关的代码（或自己写注册函数）。否则现有的ATL.DLL会坏了你的好事.<BR>&nbsp;修改现有的类库是很危险的事情。因为他们的调用关系太复杂了.不过,如果他里面有BUG,这也算是一个<BR>好方法.</P><img src ="http://www.cnblogs.com/vibration/aggbug/231915.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47998/" target="_blank">传诺基亚正在开发Android手机</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>关于C++模板的连接问题</title><link>http://www.cnblogs.com/vibration/archive/2005/06/30/183978.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Thu, 30 Jun 2005 06:27:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2005/06/30/183978.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/183978.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2005/06/30/183978.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/183978.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/183978.html</trackback:ping><description><![CDATA[好久没写模板了，这次做一项目，发现一处非常适合使用模板应用，于是写了个模板类，大概类似于酱紫<IMG src="http://www.cnblogs.com/Emoticons/emsmile.gif" align=absMiddle border=0><BR>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">头文件</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;TElement</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;TTTextT&nbsp;&nbsp;<BR>{<BR></SPAN><SPAN style="COLOR: #0000ff">protected</SPAN><SPAN style="COLOR: #000000">:<BR>&nbsp;&nbsp;&nbsp;&nbsp;vector</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TElement</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;m_chVector;<BR></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">:<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Count();<BR>}<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">CPP文件</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">#include&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">TTText.h</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000"><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;TElement</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;TTTextT</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TElement</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Count()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;m_chVector.size();<BR>}<BR></SPAN></DIV></DIV>当然还有许多其他代码啦，分成头文件和CPP文件，初步编译没什么问题。<BR>可是在使用的时候，却产生了连接问题，说什么unresolved external symbol，函数找不到<IMG src="http://www.cnblogs.com/Emoticons/emsad.gif" align=absMiddle border=0>。忽然想起以前也碰到过类似问题，模板类的声名和实现如果放在两个文件里，就会发生这样的状况。当时没时间多想，把所有实现挪到头文件里就解决了。想看看人家的代码，不管是STL，ATL，WTL，都是所有内容全放头文件的。晕了<IMG src="http://www.cnblogs.com/Emoticons/emrosesad.gif" align=absMiddle border=0>，最后还是把所有代码挪到头文件，就OK了。<BR>可是为什么呢？查MSDN，查google，都没有找到满意的答案<IMG src="http://www.cnblogs.com/Emoticons/hitwall.gif" align=absMiddle border=0>。只看到一篇，说模板编译中不产生实际代码，只有加模板参数使用时才产生代码，因此如果分两个文件，连接时会出错，云云。不是特别明白，结论似乎是使用模板就应该把所有实现放在头文件中。看看STL/ATL/WTL，似乎也是。但问题是：既然这样，为什么允许下面这样的代码呢<IMG src="http://www.cnblogs.com/Emoticons/emrosesad.gif" align=absMiddle border=0><BR><SPAN style="COLOR: #000000">
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;TElement</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;TTTextT</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TElement</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Count()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;m_chVector.size();<BR>}<BR></SPAN></DIV></DIV><BR></SPAN><BR><img src ="http://www.cnblogs.com/vibration/aggbug/183978.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47996/" target="_blank">7月编程语言排行榜</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>用窗口消息解决COM接口的多线程访问问题</title><link>http://www.cnblogs.com/vibration/archive/2005/06/02/166525.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Thu, 02 Jun 2005 02:16:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2005/06/02/166525.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/166525.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2005/06/02/166525.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/166525.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/166525.html</trackback:ping><description><![CDATA[上篇讲了COM接口的多线程访问问题，并用全局接口表的方法解决了。但有时候我们不能直接访问接口指针，而是通过一个封装类间接的访问。比如：<BR>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;SomeClass<BR>{<BR></SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">:<BR>&nbsp;&nbsp;&nbsp;&nbsp;IMyInterface&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">m_pInt;<BR></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">:<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;Method1()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">Init&nbsp;m_pInt</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;Method2()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">call&nbsp;method&nbsp;of&nbsp;m_pInt</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}</SPAN></DIV></DIV>
<P>我们只能访问SomeClass的公共方法，而无法直接访问接口指针，这时就不能使用使用全局接口表的方法。如果需要在不同线程中调用SomeClass的方法，唯一的办法就是把所有的调用放在一个线程中。怎么做到这一点呢？用一个消息窗口来同步是一个简单的方法。<BR>首先定义一个窗口类，把所有对SomeClass的操作定义成窗口消息，如下：<BR></P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">#define</SPAN><SPAN style="COLOR: #000000">&nbsp;WM_METHOD1&nbsp;WM_USER&nbsp;+&nbsp;100</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">#define</SPAN><SPAN style="COLOR: #000000">&nbsp;WM_METHOD2&nbsp;WM_USER&nbsp;+&nbsp;101</SPAN><SPAN style="COLOR: #000000"><BR><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;CThreadWnd&nbsp;:&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;CWindowImpl</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">CThreadWnd</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR></SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">:<BR>&nbsp;&nbsp;&nbsp;&nbsp;SomeClass&nbsp;m_someClass;<BR></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">:<BR>&nbsp;BEGIN_MSG_MAP(CThreadWnd)<BR>&nbsp;&nbsp;MESSAGE_HANDLER(WM_METHOD1,&nbsp;OnMethod1)<BR>&nbsp;&nbsp;MESSAGE_HANDLER(WM_METHOD2,&nbsp;OnMethod2)<BR>&nbsp;END_MSG_MAP()<BR><BR><BR>&nbsp;LRESULT&nbsp;OnMethod1(UINT&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">uMsg</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">,&nbsp;WPARAM&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">wParam</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">,&nbsp;LPARAM&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">lParam</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">,&nbsp;BOOL</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">bHandled</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;LRESULT&nbsp;OnMethod2(UINT&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">uMsg</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">,&nbsp;WPARAM&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">wParam</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">,&nbsp;LPARAM&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">lParam</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">,&nbsp;BOOL</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">bHandled</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">);<BR>}<BR></SPAN></DIV></DIV>
<P><BR>在OnMethod1和OnMethod2中完成对m_someClass的方法调用，如果方法有参数，通过wParam和lParam传递。</P>
<P>然后，我们需要做的是在一个线程中创建这个窗口。并在需要调用SomeClass的方法时，通过向CThreadWnd窗口发送消息间接完成。例如：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">CThreadWnd&nbsp;wndThread;<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">In&nbsp;thread&nbsp;A</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">wndThread.SendMessage(WM_METHOD1);<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">In&nbsp;thread&nbsp;B</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">wndThread.SendMessage(WM_METHOD2);</SPAN></DIV></DIV><BR>至于wndThread，可以保存在任何地方。而创建线程窗口的线程函数代码基本上应该是这样的：<BR><BR>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">UINT&nbsp;WINAPI&nbsp;ThreadProc(LPVOID&nbsp;lpParam)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;::CoInitialize(</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;CThreadWnd&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">pWnd&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(CThreadWnd</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)lpParam;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;CMessageLoop&nbsp;theLoop;<BR>&nbsp;&nbsp;&nbsp;&nbsp;_Module.AddMessageLoop(</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">theLoop);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;pWnd</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">Create(NULL,&nbsp;CRect(</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">),&nbsp;NULL,&nbsp;WS_POPUP);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;theLoop.Run();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;pWnd</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">DestroyWindow();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;_Module.RemoveMessageLoop();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;::CoUninitialize();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}<BR></SPAN></DIV></DIV><BR>创建线程的代码就不贴了，销毁线程则只要向线程窗口发送WM_QUIT消息即可。这个方法在实际应用中个人感觉非常有效。<BR>有一个问题是当方法参数比较多时，很难通过wParam和lParam传递。这就需要另外定义一个结构，存放各种参数，然后通过wParam传递结构的地址。总之人是活的，灵活运用:P<img src ="http://www.cnblogs.com/vibration/aggbug/166525.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47995/" target="_blank">Google Voice 上手</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>用全局接口表实现COM接口在不同线程中的传递</title><link>http://www.cnblogs.com/vibration/archive/2005/05/30/164763.html</link><dc:creator>vibration</dc:creator><author>vibration</author><pubDate>Mon, 30 May 2005 02:13:00 GMT</pubDate><guid>http://www.cnblogs.com/vibration/archive/2005/05/30/164763.html</guid><wfw:comment>http://www.cnblogs.com/vibration/comments/164763.html</wfw:comment><comments>http://www.cnblogs.com/vibration/archive/2005/05/30/164763.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/vibration/comments/commentRss/164763.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/vibration/services/trackbacks/164763.html</trackback:ping><description><![CDATA[<P>在多线程程序中使用COM对象真是件令人头疼的事情。当你能够访问一个接口指针的时候，并不意味着你可以调用接口上的方法。我从来没真正搞懂过所谓COM的几种线程模式。问题是，当我试图在一个线程里调用一个COM接口的方法，而这个COM接口是在另一个线程中创建时，从来没有成功过。更糟的是，连错误提示都没有。<BR>在多个线程中传递接口需要额外的工作，各种书籍上都介绍了所谓Marshal一个接口方法，不过我从来没有使用过。因为有更简单的方法，就是用全局接口表(GlobalInterfaceTable)。<BR>GlobalInterfaceTable允许你在任何地方访问任何线程中创建的COM接口。GlobalInterfaceTable本身是一个COM对象，它实现了IGlobalInterfaceTable接口。这个接口有三个方法，分别用来注册接口，取得接口和注销接口。下面的例子介绍了GlobalInterfaceTable的基本使用方法。<BR>首先当创建一个需要在其他线程使用的COM接口时，把它注册到GlobalInterfaceTable</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">CComPtr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IMyInterface</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;spMyInterface;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top>spMyInterface.CoCreateInstance(<IMG src="http://www.cnblogs.com/images/dot.gif">);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">register&nbsp;interface&nbsp;in&nbsp;global&nbsp;interface&nbsp;table</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">CComPtr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IGlobalInterfaceTable</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;spGIT;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top>spGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(spGIT)<BR><IMG id=Codehighlighter1_225_308_Open_Image onclick="this.style.display='none'; Codehighlighter1_225_308_Open_Text.style.display='none'; Codehighlighter1_225_308_Closed_Image.style.display='inline'; Codehighlighter1_225_308_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_225_308_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_225_308_Closed_Text.style.display='none'; Codehighlighter1_225_308_Open_Image.style.display='inline'; Codehighlighter1_225_308_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_225_308_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_225_308_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;spGIT</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">RegisterInterfaceInGlobal(spMyInterface,&nbsp;IID_IMyInterface,&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">m_dwCookie);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN></DIV></DIV>
<P>注册时会返回一个Cookie，记住这个Cookie，并在任何线程需要使用前面接口时，通过这个Cookie获得接口。</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">CComPtr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IMyInterface</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;spMyInterface;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(m_dwCookie</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">)<BR><IMG id=Codehighlighter1_57_261_Open_Image onclick="this.style.display='none'; Codehighlighter1_57_261_Open_Text.style.display='none'; Codehighlighter1_57_261_Closed_Image.style.display='inline'; Codehighlighter1_57_261_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_57_261_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_57_261_Closed_Text.style.display='none'; Codehighlighter1_57_261_Open_Image.style.display='inline'; Codehighlighter1_57_261_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_57_261_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_57_261_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CComPtr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IGlobalInterfaceTable</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;spGIT;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;spGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(spGIT)<BR><IMG id=Codehighlighter1_167_259_Open_Image onclick="this.style.display='none'; Codehighlighter1_167_259_Open_Text.style.display='none'; Codehighlighter1_167_259_Closed_Image.style.display='inline'; Codehighlighter1_167_259_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_167_259_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_167_259_Closed_Text.style.display='none'; Codehighlighter1_167_259_Open_Image.style.display='inline'; Codehighlighter1_167_259_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_167_259_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_167_259_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spGIT</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">GetInterfaceFromGlobal(m_dwCookie,&nbsp;IID_IMyInterface,&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">**</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">spMyInterface.p);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(spMyInterface)<BR><IMG id=Codehighlighter1_283_305_Open_Image onclick="this.style.display='none'; Codehighlighter1_283_305_Open_Text.style.display='none'; Codehighlighter1_283_305_Closed_Image.style.display='inline'; Codehighlighter1_283_305_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_283_305_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_283_305_Closed_Text.style.display='none'; Codehighlighter1_283_305_Open_Image.style.display='inline'; Codehighlighter1_283_305_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_283_305_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_283_305_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">Call&nbsp;my&nbsp;interface</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></SPAN><SPAN style="COLOR: #000000">}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN></DIV></DIV>
<P>最后，作为一个负责任的程序员，关闭之前一定要注销前面注册的接口。</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(m_dwCookie</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">)<BR><IMG id=Codehighlighter1_19_200_Open_Image onclick="this.style.display='none'; Codehighlighter1_19_200_Open_Text.style.display='none'; Codehighlighter1_19_200_Closed_Image.style.display='inline'; Codehighlighter1_19_200_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_19_200_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_19_200_Closed_Text.style.display='none'; Codehighlighter1_19_200_Open_Image.style.display='inline'; Codehighlighter1_19_200_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_19_200_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_19_200_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CComPtr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IGlobalInterfaceTable</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;spGIT;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;spGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(spGIT)<BR><IMG id=Codehighlighter1_129_198_Open_Image onclick="this.style.display='none'; Codehighlighter1_129_198_Open_Text.style.display='none'; Codehighlighter1_129_198_Closed_Image.style.display='inline'; Codehighlighter1_129_198_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_129_198_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_129_198_Closed_Text.style.display='none'; Codehighlighter1_129_198_Open_Image.style.display='inline'; Codehighlighter1_129_198_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_129_198_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_129_198_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spGIT</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">RevokeInterfaceFromGlobal(m_dwCookie);<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_dwCookie&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN></DIV></DIV>需要注意的时，我们每次都是新创建GlobalInterfaceTable的实例，因为它本身也是COM对象，它的指针不能在不同线程间传递。<img src ="http://www.cnblogs.com/vibration/aggbug/164763.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47994/" target="_blank">Google号召社区力量为互联网加速</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item></channel></rss>