﻿<?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>C++博客-章鱼花园</title><link>http://www.cppblog.com/vibration/</link><description>I'd like to be under the sea. In an octopus' garden in the shade ...</description><language>zh-cn</language><lastBuildDate>Sat, 04 Apr 2026 05:38:54 GMT</lastBuildDate><pubDate>Sat, 04 Apr 2026 05:38:54 GMT</pubDate><ttl>60</ttl><item><title>OLE2T在VS2003中转换中文失败的问题及解决方法</title><link>http://www.cppblog.com/vibration/archive/2005/11/10/1034.html</link><dc:creator>章鱼</dc:creator><author>章鱼</author><pubDate>Thu, 10 Nov 2005 01:43:00 GMT</pubDate><guid>http://www.cppblog.com/vibration/archive/2005/11/10/1034.html</guid><wfw:comment>http://www.cppblog.com/vibration/comments/1034.html</wfw:comment><comments>http://www.cppblog.com/vibration/archive/2005/11/10/1034.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/vibration/comments/commentRss/1034.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vibration/services/trackbacks/1034.html</trackback:ping><description><![CDATA[以前VC6的代码，从xml文件中读取属性文字（中文），返回BSTR类型，用OLE2T转换，然后显示，一直工作很正常，用来做本地化，比修改Res文件要方便的多。<BR><BR>同样的代码，在VS2003里面居然不能工作了，调试，发现BSTR返回正常，而通过OLE2T转换居然就全转成“???”了，晕。<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>
<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: #0000ff">#define</SPAN><SPAN style="COLOR: #000000">&nbsp;_CONVERSION_DONT_USE_THREAD_LOCALE</SPAN></DIV><BR><BR>搞定<IMG src="http://www.cnblogs.com/Emoticons/emsmiled.gif" align=absMiddle border=0> <img src ="http://www.cppblog.com/vibration/aggbug/1034.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vibration/" target="_blank">章鱼</a> 2005-11-10 09:43 <a href="http://www.cppblog.com/vibration/archive/2005/11/10/1034.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>标题栏按钮的WTL实现</title><link>http://www.cppblog.com/vibration/archive/2005/09/20/328.html</link><dc:creator>章鱼</dc:creator><author>章鱼</author><pubDate>Tue, 20 Sep 2005 03:07:00 GMT</pubDate><guid>http://www.cppblog.com/vibration/archive/2005/09/20/328.html</guid><wfw:comment>http://www.cppblog.com/vibration/comments/328.html</wfw:comment><comments>http://www.cppblog.com/vibration/archive/2005/09/20/328.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/vibration/comments/commentRss/328.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vibration/services/trackbacks/328.html</trackback:ping><description><![CDATA[<P><U><STRONG>起因</STRONG></U></P>
<P>上次完成了<A href="http://www.cnblogs.com/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="http://www.cnblogs.com/vibration/archive/2005/09/14/236926.html">CAppBar</A>类，以实现桌面停靠的功能。5个标题按钮的排列使用了普通方式和垂直排列的方式，通过继承GetButtonPos函数实现。其中图钉按钮控制AppBar窗口的自动隐藏设置；其他4个按钮使窗口停靠到桌面的一边；并且把停靠到底部的按钮设置成Disabled，可以看到不同的效果</P>
<P><A href="http://www.cnblogs.com/Files/vibration/CaptionButton_Demo.zip">下载示例程序</A> </P><img src ="http://www.cppblog.com/vibration/aggbug/328.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vibration/" target="_blank">章鱼</a> 2005-09-20 11:07 <a href="http://www.cppblog.com/vibration/archive/2005/09/20/328.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppBar的WTL实现</title><link>http://www.cppblog.com/vibration/archive/2005/09/15/275.html</link><dc:creator>章鱼</dc:creator><author>章鱼</author><pubDate>Thu, 15 Sep 2005 01:42:00 GMT</pubDate><guid>http://www.cppblog.com/vibration/archive/2005/09/15/275.html</guid><wfw:comment>http://www.cppblog.com/vibration/comments/275.html</wfw:comment><comments>http://www.cppblog.com/vibration/archive/2005/09/15/275.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/vibration/comments/commentRss/275.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vibration/services/trackbacks/275.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://vibration.cnblogs.com/Emoticons/emsmilep.gif" align=absMiddle border=0><BR><BR><A href="http://vibration.cnblogs.com/Files/vibration/AppBarTest.zip">下载例子程序</A><BR><img src ="http://www.cppblog.com/vibration/aggbug/275.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vibration/" target="_blank">章鱼</a> 2005-09-15 09:42 <a href="http://www.cppblog.com/vibration/archive/2005/09/15/275.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>