﻿<?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++博客-rdu-cpp</title><link>http://www.cppblog.com/rdu-cpp/</link><description>杨柳不折</description><language>zh-cn</language><lastBuildDate>Tue, 07 Apr 2026 18:48:26 GMT</lastBuildDate><pubDate>Tue, 07 Apr 2026 18:48:26 GMT</pubDate><ttl>60</ttl><item><title>Translating Strings Between Unicode and ANSI</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/04/22/80752.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Wed, 22 Apr 2009 09:00:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/04/22/80752.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/80752.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/04/22/80752.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/80752.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/80752.html</trackback:ping><description><![CDATA[<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"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;DoUKnow.cpp&nbsp;:&nbsp;main&nbsp;project&nbsp;file.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">tchar.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_149_666_Open_Image onclick="this.style.display='none'; Codehighlighter1_149_666_Open_Text.style.display='none'; Codehighlighter1_149_666_Closed_Image.style.display='inline'; Codehighlighter1_149_666_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_149_666_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_149_666_Closed_Text.style.display='none'; Codehighlighter1_149_666_Open_Image.style.display='inline'; Codehighlighter1_149_666_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()</span><span id=Codehighlighter1_149_666_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_149_666_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;the&nbsp;ANSI&nbsp;string&nbsp;to&nbsp;convert&nbsp;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;PCSTR&nbsp;pCStr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">this&nbsp;is&nbsp;an&nbsp;ANSI&nbsp;string</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Step&nbsp;1:&nbsp;Calculate&nbsp;required&nbsp;size</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;MultiByteToWideChar(CP_ACP,&nbsp;NULL,&nbsp;pCStr,&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;NULL,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;size&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(WCHAR);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Step&nbsp;2:&nbsp;Malloc&nbsp;buffer</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;WCHAR&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">szBuffer&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(WCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)malloc(size);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Step&nbsp;3:&nbsp;Do&nbsp;the&nbsp;conversion</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;MultiByteToWideChar(CP_ACP,&nbsp;NULL,&nbsp;pCStr,&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;szBuffer,&nbsp;size);&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Use&nbsp;the&nbsp;converted&nbsp;Unicode&nbsp;string</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;wcout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;szBuffer&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Step&nbsp;4:&nbsp;Free&nbsp;the&nbsp;buffer</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;szBuffer;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&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><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br><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"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;DoUKnow.cpp&nbsp;:&nbsp;main&nbsp;project&nbsp;file.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">tchar.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_149_690_Open_Image onclick="this.style.display='none'; Codehighlighter1_149_690_Open_Text.style.display='none'; Codehighlighter1_149_690_Closed_Image.style.display='inline'; Codehighlighter1_149_690_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_149_690_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_149_690_Closed_Text.style.display='none'; Codehighlighter1_149_690_Open_Image.style.display='inline'; Codehighlighter1_149_690_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()</span><span id=Codehighlighter1_149_690_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_149_690_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;the&nbsp;ANSI&nbsp;string&nbsp;to&nbsp;convert&nbsp;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;PCWSTR&nbsp;pWStr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;L</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">this&nbsp;is&nbsp;an&nbsp;Unicode&nbsp;string</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Step&nbsp;1:&nbsp;Calculate&nbsp;required&nbsp;size</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WideCharToMultiByte(CP_ACP,&nbsp;NULL,&nbsp;pWStr,&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;NULL,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;NULL,&nbsp;NULL);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;size&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(CHAR);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Step&nbsp;2:&nbsp;Malloc&nbsp;buffer</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;CHAR&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">szBuffer&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(CHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)malloc(size);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Step&nbsp;3:&nbsp;Do&nbsp;the&nbsp;conversion</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;WideCharToMultiByte(CP_ACP,&nbsp;NULL,&nbsp;pWStr,&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;szBuffer,&nbsp;size,&nbsp;NULL,&nbsp;NULL);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Use&nbsp;the&nbsp;converted&nbsp;Unicode&nbsp;string</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;szBuffer&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Step&nbsp;4:&nbsp;Free&nbsp;the&nbsp;buffer</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;szBuffer;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&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><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<img src ="http://www.cppblog.com/rdu-cpp/aggbug/80752.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-04-22 17:00 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/04/22/80752.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LoadLibrary 例子</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/04/10/79462.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Fri, 10 Apr 2009 03:18:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/04/10/79462.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/79462.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/04/10/79462.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/79462.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/79462.html</trackback:ping><description><![CDATA[<p>&nbsp;</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"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;CliConsole.cpp&nbsp;:&nbsp;main&nbsp;project&nbsp;file.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;_AFXDLL</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">afx.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">tchar.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;System;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_181_290_Open_Image onclick="this.style.display='none'; Codehighlighter1_181_290_Open_Text.style.display='none'; Codehighlighter1_181_290_Closed_Image.style.display='inline'; Codehighlighter1_181_290_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_181_290_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_181_290_Closed_Text.style.display='none'; Codehighlighter1_181_290_Open_Image.style.display='inline'; Codehighlighter1_181_290_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;PrintWndText(IntPtr&nbsp;hwnd,&nbsp;IntPtr&nbsp;lParam)</span><span id=Codehighlighter1_181_290_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_181_290_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;String&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">wndText&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Helper::GetWndText(hwnd);<br><img id=Codehighlighter1_240_274_Open_Image onclick="this.style.display='none'; Codehighlighter1_240_274_Open_Text.style.display='none'; Codehighlighter1_240_274_Closed_Image.style.display='inline'; Codehighlighter1_240_274_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_240_274_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_240_274_Closed_Text.style.display='none'; Codehighlighter1_240_274_Open_Image.style.display='inline'; Codehighlighter1_240_274_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(wndText)</span><span id=Codehighlighter1_240_274_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_240_274_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;Console::WriteLine(wndText);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">delegate</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;PrintDelegate(String</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">,&nbsp;String</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(array</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">System::String&nbsp;</span><span style="COLOR: #000000">^&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">args)<br><img id=Codehighlighter1_379_1055_Open_Image onclick="this.style.display='none'; Codehighlighter1_379_1055_Open_Text.style.display='none'; Codehighlighter1_379_1055_Closed_Image.style.display='inline'; Codehighlighter1_379_1055_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_379_1055_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_379_1055_Closed_Text.style.display='none'; Codehighlighter1_379_1055_Open_Image.style.display='inline'; Codehighlighter1_379_1055_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_379_1055_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_379_1055_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;CallbackDelegate&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">callback&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;gcnew&nbsp;CallbackDelegate(PrintWndText);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;WindowsEnumerator&nbsp;</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">we&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;gcnew&nbsp;WindowsEnumerator(callback);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;we</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">DoWork();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;HMODULE&nbsp;hLib&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;LoadLibrary(L</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">msvcrt.dll</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img id=Codehighlighter1_578_986_Open_Image onclick="this.style.display='none'; Codehighlighter1_578_986_Open_Text.style.display='none'; Codehighlighter1_578_986_Closed_Image.style.display='inline'; Codehighlighter1_578_986_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_578_986_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_578_986_Closed_Text.style.display='none'; Codehighlighter1_578_986_Open_Image.style.display='inline'; Codehighlighter1_578_986_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(hLib)</span><span id=Codehighlighter1_578_986_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_578_986_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;typedef&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">FUNCPTR)(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">,&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;FARPROC&nbsp;proc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetProcAddress(hLib,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">printf</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;FUNCPTR&nbsp;pFunc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;reinterpret_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">FUNCPTR</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(proc);<br><img id=Codehighlighter1_734_983_Open_Image onclick="this.style.display='none'; Codehighlighter1_734_983_Open_Text.style.display='none'; Codehighlighter1_734_983_Closed_Image.style.display='inline'; Codehighlighter1_734_983_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_734_983_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_734_983_Closed_Text.style.display='none'; Codehighlighter1_734_983_Open_Image.style.display='inline'; Codehighlighter1_734_983_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(pFunc)</span><span id=Codehighlighter1_734_983_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_734_983_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;System::Runtime::InteropServices::Marshal;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;Delegate</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">&nbsp;ptr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Marshal::GetDelegateForFunctionPointer((IntPtr)pFunc,PrintDelegate::typeid);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;PrintDelegate</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">&nbsp;printDelegate&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(PrintDelegate</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">)ptr;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;printDelegate(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%s\r\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,L</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">good&nbsp;man</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;Console::WriteLine(L</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello&nbsp;World</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&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><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<img src ="http://www.cppblog.com/rdu-cpp/aggbug/79462.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-04-10 11:18 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/04/10/79462.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>获取文件的数字签名</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/02/13/73717.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Fri, 13 Feb 2009 06:32:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/02/13/73717.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/73717.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/02/13/73717.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/73717.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/73717.html</trackback:ping><description><![CDATA[<p>假设要查看一个exe的数字签名，那么你可以很容易的右键，查看属性-&gt;数字签名Tab下的内容。可是在程序中如果就没那么容易的了。<br><br>遗憾的是.net没有提供对CryptQueryObject等API作出封装，记下这篇以备用<br><a href="http://support.microsoft.com/default.aspx/kb/323809"><u><font color=#0000ff>http://support.microsoft.com/default.aspx/kb/323809</font></u></a><br><br></p>
<span class=Apple-style-span style="WORD-SPACING: 0px; FONT: 13px Verdana; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0">
<h1 class=title style="FONT-SIZE: 150%; MARGIN: 0px 0px 10px; FONT-FAMILY: Verdana, sans-serif; -webkit-box-sizing: border-box">如何获取信息从 Authenticode 签名可执行文件</h1>
<div class=kb_meta_divider style="BACKGROUND-POSITION: -509px 0px; BACKGROUND-IMAGE: url(http://support.microsoft.com/library/images/support/cn/gsfx_kb_cluster.png); WIDTH: 509px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 10px; -webkit-box-sizing: border-box; -webkit-background-clip: initial; -webkit-background-origin: initial"></div>
<div class=appliesToLink style="MARGIN: 10px 0px; -webkit-box-sizing: border-box"><a style="COLOR: rgb(7,103,154); TEXT-DECORATION: none; -webkit-box-sizing: border-box" href="#appliesto">察看本文应用于的产品</a></div>
<div class=section id=kb_section style="-webkit-box-sizing: border-box">
<div class=expandcollapseall_open id=kb_expandcollapseall style="MARGIN: 10px 0px 10px 10px; COLOR: rgb(17,95,135); -webkit-box-sizing: border-box"><a class=expandalltext style="COLOR: rgb(7,103,154); TEXT-DECORATION: none; -webkit-box-sizing: border-box" href="javascript:void(0);">展开全部</a><span class=Apple-converted-space>&nbsp;</span>|<span class=Apple-converted-space>&nbsp;</span><a class=collapsealltext style="COLOR: rgb(7,103,154); TEXT-DECORATION: none; -webkit-box-sizing: border-box" href="javascript:void(0);">关闭全部</a></div>
<div class=sbody style="MARGIN: 0px 0px 10px 24%; LINE-HEIGHT: 1.5em; -webkit-box-sizing: border-box">可以使用<span class=Apple-converted-space>&nbsp;</span><strong style="-webkit-box-sizing: border-box">WinVerifyTrust()<span class=Apple-converted-space>&nbsp;</span></strong>API 来验证 Authenticode 签名可执行文件。<span class=Apple-converted-space>&nbsp;</span><br style="-webkit-box-sizing: border-box"><br style="-webkit-box-sizing: border-box">虽然验证签名，程序可能还必须执行以下：
<ul style="-webkit-box-sizing: border-box">
    <li style="-webkit-box-sizing: border-box">确定可执行文件的签名的证书的详细信息。</li>
    <li style="-webkit-box-sizing: border-box">确定日期和时间，文件已标记的时间。</li>
    <li style="-webkit-box-sizing: border-box">检索与文件相关联的 URL 链接。</li>
    <li style="-webkit-box-sizing: border-box">检索时间戳的证书。</li>
</ul>
本文演示如何使<span class=Apple-converted-space>&nbsp;</span><strong style="-webkit-box-sizing: border-box">CryptQueryObject()<span class=Apple-converted-space>&nbsp;</span></strong>API 检索 Authenticode 签名可执行文件的详细的信息。</div>
<h2 class=subTitle id=tocHeadRef style="OVERFLOW-Y: hidden; FONT-SIZE: 140%; OVERFLOW-X: hidden; WIDTH: 100%; CURSOR: pointer; BORDER-BOTTOM: rgb(127,186,226) 2px solid; POSITION: relative; -webkit-box-sizing: border-box"></h2>
<div class=sbody style="MARGIN: 0px 0px 10px 24%; LINE-HEIGHT: 1.5em; -webkit-box-sizing: border-box">Authenticode 签名是 PKCS 7 基于，因此可以使用<span class=Apple-converted-space>&nbsp;</span><strong style="-webkit-box-sizing: border-box">CryptQueryObject<span class=Apple-converted-space>&nbsp;</span></strong>和其他加密 API 函数检索 PKCS 7 签名，并解码 PKCS 7 属性。<br style="-webkit-box-sizing: border-box"><br style="-webkit-box-sizing: border-box">下面的示例 c 代码演示如何使用这些 API。
<div class=kb_codebody style="BORDER-RIGHT: rgb(127,186,226) 1px solid; BORDER-TOP: rgb(127,186,226) 12px solid; OVERFLOW-X: auto; MARGIN-BOTTOM: 10px; BORDER-LEFT: rgb(127,186,226) 1px solid; BORDER-BOTTOM: rgb(127,186,226) 1px solid; POSITION: relative; -webkit-box-sizing: border-box">
<div class=kb_codecontent style="BORDER-RIGHT: rgb(127,186,226) 0px solid; PADDING-RIGHT: 0px; BORDER-TOP: rgb(127,186,226) 0px solid; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; BORDER-LEFT: rgb(127,186,226) 0px solid; WIDTH: 100%; PADDING-TOP: 0px; BORDER-BOTTOM: rgb(127,186,226) 0px solid; BACKGROUND-COLOR: rgb(255,255,255); -webkit-box-sizing: border-box; -webkit-background-clip: initial; -webkit-background-origin: initial"><code style="-webkit-box-sizing: border-box">
<pre class=code style="PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 20px; MARGIN: 0px; WIDTH: 1px; COLOR: rgb(51,51,51); PADDING-TOP: 10px; FONT-FAMILY: Consolas, 'Courier New', Courier, monospace; POSITION: relative; -webkit-box-sizing: border-box">#include &lt;windows.h&gt;
#include &lt;wincrypt.h&gt;
#include &lt;wintrust.h&gt;
#include &lt;stdio.h&gt;
#include &lt;tchar.h&gt;
#pragma comment(lib, "crypt32.lib")
#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
typedef struct {
LPWSTR lpszProgramName;
LPWSTR lpszPublisherLink;
LPWSTR lpszMoreInfoLink;
} SPROG_PUBLISHERINFO, *PSPROG_PUBLISHERINFO;
BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_PUBLISHERINFO Info);
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st);
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext);
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo,
PCMSG_SIGNER_INFO *pCounterSignerInfo);
int _tmain(int argc, TCHAR *argv[])
{
WCHAR szFileName[MAX_PATH];
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
PCCERT_CONTEXT pCertContext = NULL;
BOOL fResult;
DWORD dwEncoding, dwContentType, dwFormatType;
PCMSG_SIGNER_INFO pSignerInfo = NULL;
PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
DWORD dwSignerInfo;
CERT_INFO CertInfo;
SPROG_PUBLISHERINFO ProgPubInfo;
SYSTEMTIME st;
ZeroMemory(&amp;ProgPubInfo, sizeof(ProgPubInfo));
__try
{
if (argc != 2)
{
_tprintf(_T("Usage: SignedFileInfo &lt;filename&gt;\n"));
return 0;
}
#ifdef UNICODE
lstrcpynW(szFileName, argv[1], MAX_PATH);
#else
if (mbstowcs(szFileName, argv[1], MAX_PATH) == -1)
{
printf("Unable to convert to unicode.\n");
__leave;
}
#endif
// Get message handle and store handle from the signed file.
fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
szFileName,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0,
&amp;dwEncoding,
&amp;dwContentType,
&amp;dwFormatType,
&amp;hStore,
&amp;hMsg,
NULL);
if (!fResult)
{
_tprintf(_T("CryptQueryObject failed with %x\n"), GetLastError());
__leave;
}
// Get signer information size.
fResult = CryptMsgGetParam(hMsg,
CMSG_SIGNER_INFO_PARAM,
0,
NULL,
&amp;dwSignerInfo);
if (!fResult)
{
_tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
__leave;
}
// Allocate memory for signer information.
pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
if (!pSignerInfo)
{
_tprintf(_T("Unable to allocate memory for Signer Info.\n"));
__leave;
}
// Get Signer Information.
fResult = CryptMsgGetParam(hMsg,
CMSG_SIGNER_INFO_PARAM,
0,
(PVOID)pSignerInfo,
&amp;dwSignerInfo);
if (!fResult)
{
_tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
__leave;
}
// Get program name and publisher information from
// signer info structure.
if (GetProgAndPublisherInfo(pSignerInfo, &amp;ProgPubInfo))
{
if (ProgPubInfo.lpszProgramName != NULL)
{
wprintf(L"Program Name : %s\n",
ProgPubInfo.lpszProgramName);
}
if (ProgPubInfo.lpszPublisherLink != NULL)
{
wprintf(L"Publisher Link : %s\n",
ProgPubInfo.lpszPublisherLink);
}
if (ProgPubInfo.lpszMoreInfoLink != NULL)
{
wprintf(L"MoreInfo Link : %s\n",
ProgPubInfo.lpszMoreInfoLink);
}
}
_tprintf(_T("\n"));
// Search for the signer certificate in the temporary
// certificate store.
CertInfo.Issuer = pSignerInfo-&gt;Issuer;
CertInfo.SerialNumber = pSignerInfo-&gt;SerialNumber;
pCertContext = CertFindCertificateInStore(hStore,
ENCODING,
0,
CERT_FIND_SUBJECT_CERT,
(PVOID)&amp;CertInfo,
NULL);
if (!pCertContext)
{
_tprintf(_T("CertFindCertificateInStore failed with %x\n"),
GetLastError());
__leave;
}
// Print Signer certificate information.
_tprintf(_T("Signer Certificate:\n\n"));
PrintCertificateInfo(pCertContext);
_tprintf(_T("\n"));
// Get the timestamp certificate signerinfo structure.
if (GetTimeStampSignerInfo(pSignerInfo, &amp;pCounterSignerInfo))
{
// Search for Timestamp certificate in the temporary
// certificate store.
CertInfo.Issuer = pCounterSignerInfo-&gt;Issuer;
CertInfo.SerialNumber = pCounterSignerInfo-&gt;SerialNumber;
pCertContext = CertFindCertificateInStore(hStore,
ENCODING,
0,
CERT_FIND_SUBJECT_CERT,
(PVOID)&amp;CertInfo,
NULL);
if (!pCertContext)
{
_tprintf(_T("CertFindCertificateInStore failed with %x\n"),
GetLastError());
__leave;
}
// Print timestamp certificate information.
_tprintf(_T("TimeStamp Certificate:\n\n"));
PrintCertificateInfo(pCertContext);
_tprintf(_T("\n"));
// Find Date of timestamp.
if (GetDateOfTimeStamp(pCounterSignerInfo, &amp;st))
{
_tprintf(_T("Date of TimeStamp : %02d/%02d/%04d %02d:%02d\n"),
st.wMonth,
st.wDay,
st.wYear,
st.wHour,
st.wMinute);
}
_tprintf(_T("\n"));
}
}
__finally
{
// Clean up.
if (ProgPubInfo.lpszProgramName != NULL)
LocalFree(ProgPubInfo.lpszProgramName);
if (ProgPubInfo.lpszPublisherLink != NULL)
LocalFree(ProgPubInfo.lpszPublisherLink);
if (ProgPubInfo.lpszMoreInfoLink != NULL)
LocalFree(ProgPubInfo.lpszMoreInfoLink);
if (pSignerInfo != NULL) LocalFree(pSignerInfo);
if (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo);
if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
if (hStore != NULL) CertCloseStore(hStore, 0);
if (hMsg != NULL) CryptMsgClose(hMsg);
}
return 0;
}
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext)
{
BOOL fReturn = FALSE;
LPTSTR szName = NULL;
DWORD dwData;
__try
{
// Print Serial Number.
_tprintf(_T("Serial Number: "));
dwData = pCertContext-&gt;pCertInfo-&gt;SerialNumber.cbData;
for (DWORD n = 0; n &lt; dwData; n++)
{
_tprintf(_T("%02x "),
pCertContext-&gt;pCertInfo-&gt;SerialNumber.pbData[dwData - (n + 1)]);
}
_tprintf(_T("\n"));
// Get Issuer name size.
if (!(dwData = CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
NULL,
0)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// Allocate memory for Issuer name.
szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
if (!szName)
{
_tprintf(_T("Unable to allocate memory for issuer name.\n"));
__leave;
}
// Get Issuer name.
if (!(CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
szName,
dwData)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// print Issuer name.
_tprintf(_T("Issuer Name: %s\n"), szName);
LocalFree(szName);
szName = NULL;
// Get Subject name size.
if (!(dwData = CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// Allocate memory for subject name.
szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
if (!szName)
{
_tprintf(_T("Unable to allocate memory for subject name.\n"));
__leave;
}
// Get subject name.
if (!(CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
szName,
dwData)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// Print Subject Name.
_tprintf(_T("Subject Name: %s\n"), szName);
fReturn = TRUE;
}
__finally
{
if (szName != NULL) LocalFree(szName);
}
return fReturn;
}
LPWSTR AllocateAndCopyWideString(LPCWSTR inputString)
{
LPWSTR outputString = NULL;
outputString = (LPWSTR)LocalAlloc(LPTR,
(wcslen(inputString) + 1) * sizeof(WCHAR));
if (outputString != NULL)
{
lstrcpyW(outputString, inputString);
}
return outputString;
}
BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_PUBLISHERINFO Info)
{
BOOL fReturn = FALSE;
PSPC_SP_OPUS_INFO OpusInfo = NULL;
DWORD dwData;
BOOL fResult;
__try
{
// Loop through authenticated attributes and find
// SPC_SP_OPUS_INFO_OBJID OID.
for (DWORD n = 0; n &lt; pSignerInfo-&gt;AuthAttrs.cAttr; n++)
{
if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID,
pSignerInfo-&gt;AuthAttrs.rgAttr[n].pszObjId) == 0)
{
// Get Size of SPC_SP_OPUS_INFO structure.
fResult = CryptDecodeObject(ENCODING,
SPC_SP_OPUS_INFO_OBJID,
pSignerInfo-&gt;AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo-&gt;AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
NULL,
&amp;dwData);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
// Allocate memory for SPC_SP_OPUS_INFO structure.
OpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwData);
if (!OpusInfo)
{
_tprintf(_T("Unable to allocate memory for Publisher Info.\n"));
__leave;
}
// Decode and get SPC_SP_OPUS_INFO structure.
fResult = CryptDecodeObject(ENCODING,
SPC_SP_OPUS_INFO_OBJID,
pSignerInfo-&gt;AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo-&gt;AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
OpusInfo,
&amp;dwData);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
// Fill in Program Name if present.
if (OpusInfo-&gt;pwszProgramName)
{
Info-&gt;lpszProgramName =
AllocateAndCopyWideString(OpusInfo-&gt;pwszProgramName);
}
else
Info-&gt;lpszProgramName = NULL;
// Fill in Publisher Information if present.
if (OpusInfo-&gt;pPublisherInfo)
{
switch (OpusInfo-&gt;pPublisherInfo-&gt;dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
Info-&gt;lpszPublisherLink =
AllocateAndCopyWideString(OpusInfo-&gt;pPublisherInfo-&gt;pwszUrl);
break;
case SPC_FILE_LINK_CHOICE:
Info-&gt;lpszPublisherLink =
AllocateAndCopyWideString(OpusInfo-&gt;pPublisherInfo-&gt;pwszFile);
break;
default:
Info-&gt;lpszPublisherLink = NULL;
break;
}
}
else
{
Info-&gt;lpszPublisherLink = NULL;
}
// Fill in More Info if present.
if (OpusInfo-&gt;pMoreInfo)
{
switch (OpusInfo-&gt;pMoreInfo-&gt;dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
Info-&gt;lpszMoreInfoLink =
AllocateAndCopyWideString(OpusInfo-&gt;pMoreInfo-&gt;pwszUrl);
break;
case SPC_FILE_LINK_CHOICE:
Info-&gt;lpszMoreInfoLink =
AllocateAndCopyWideString(OpusInfo-&gt;pMoreInfo-&gt;pwszFile);
break;
default:
Info-&gt;lpszMoreInfoLink = NULL;
break;
}
}
else
{
Info-&gt;lpszMoreInfoLink = NULL;
}
fReturn = TRUE;
break; // Break from for loop.
} // lstrcmp SPC_SP_OPUS_INFO_OBJID
} // for
}
__finally
{
if (OpusInfo != NULL) LocalFree(OpusInfo);
}
return fReturn;
}
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st)
{
BOOL fResult;
FILETIME lft, ft;
DWORD dwData;
BOOL fReturn = FALSE;
// Loop through authenticated attributes and find
// szOID_RSA_signingTime OID.
for (DWORD n = 0; n &lt; pSignerInfo-&gt;AuthAttrs.cAttr; n++)
{
if (lstrcmpA(szOID_RSA_signingTime,
pSignerInfo-&gt;AuthAttrs.rgAttr[n].pszObjId) == 0)
{
// Decode and get FILETIME structure.
dwData = sizeof(ft);
fResult = CryptDecodeObject(ENCODING,
szOID_RSA_signingTime,
pSignerInfo-&gt;AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo-&gt;AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
(PVOID)&amp;ft,
&amp;dwData);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
break;
}
// Convert to local time.
FileTimeToLocalFileTime(&amp;ft, &amp;lft);
FileTimeToSystemTime(&amp;lft, st);
fReturn = TRUE;
break; // Break from for loop.
} //lstrcmp szOID_RSA_signingTime
} // for
return fReturn;
}
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, PCMSG_SIGNER_INFO *pCounterSignerInfo)
{
PCCERT_CONTEXT pCertContext = NULL;
BOOL fReturn = FALSE;
BOOL fResult;
DWORD dwSize;
__try
{
*pCounterSignerInfo = NULL;
// Loop through unathenticated attributes for
// szOID_RSA_counterSign OID.
for (DWORD n = 0; n &lt; pSignerInfo-&gt;UnauthAttrs.cAttr; n++)
{
if (lstrcmpA(pSignerInfo-&gt;UnauthAttrs.rgAttr[n].pszObjId,
szOID_RSA_counterSign) == 0)
{
// Get size of CMSG_SIGNER_INFO structure.
fResult = CryptDecodeObject(ENCODING,
PKCS7_SIGNER_INFO,
pSignerInfo-&gt;UnauthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo-&gt;UnauthAttrs.rgAttr[n].rgValue[0].cbData,
0,
NULL,
&amp;dwSize);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
// Allocate memory for CMSG_SIGNER_INFO.
*pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize);
if (!*pCounterSignerInfo)
{
_tprintf(_T("Unable to allocate memory for timestamp info.\n"));
__leave;
}
// Decode and get CMSG_SIGNER_INFO structure
// for timestamp certificate.
fResult = CryptDecodeObject(ENCODING,
PKCS7_SIGNER_INFO,
pSignerInfo-&gt;UnauthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo-&gt;UnauthAttrs.rgAttr[n].rgValue[0].cbData,
0,
(PVOID)*pCounterSignerInfo,
&amp;dwSize);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
fReturn = TRUE;
break; // Break from for loop.
}
}
}
__finally
{
// Clean up.
if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
}
return fReturn;
}
</pre>
</code></div>
</div>
</div>
</div>
</span>
<img src ="http://www.cppblog.com/rdu-cpp/aggbug/73717.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-02-13 14:32 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/02/13/73717.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CWnd::FromHandle与CWnd::FromHandlePermanent有什么区别？？</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/02/11/73468.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Wed, 11 Feb 2009 08:16:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/02/11/73468.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/73468.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/02/11/73468.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/73468.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/73468.html</trackback:ping><description><![CDATA[<p><strong><a class=anchor name=r_8761664>6 楼</a>In355Hz（好象一条狗）<input class=star3 title="三星用户 该版得分小于等于50000分，大于30000分" type=button></strong><span>回复于 2003-01-11 18:34:52 得分 <em>20</em></span></p>
<p>你可以参考 &nbsp; MFC &nbsp; 代码中 &nbsp; FromHandle &nbsp; 和 &nbsp; FromHandlePermanent &nbsp; 的实现，这两个函数都是在公共的 &nbsp; CMapHandle &nbsp; 中查找句柄对应的 &nbsp; CWnd &nbsp; 对象（通过一个CBT钩子，CWnd &nbsp; 对象将创建时得到的句柄和自己的指针纪录到 &nbsp; CMapHandle），区别是如果找不到相关的对象，FromHandle &nbsp; 在CMapHandle &nbsp; 的 &nbsp; temporarylist &nbsp; 中创建并返回一个临时对象的指针 &nbsp; ，而 &nbsp; FromHandlePermanent &nbsp; 返回 &nbsp; NULL（此外 &nbsp; FromHandlePermanent &nbsp; 不使用 &nbsp; temporarylist &nbsp; ，所以不查找 &nbsp; temporarylist &nbsp; 下的句柄）。 &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 我想 &nbsp; MFC &nbsp; 引入这个机制的原因是需要从 &nbsp; WindowProc、钩子或 &nbsp; API &nbsp; 返回的 &nbsp; HWND &nbsp; 值中得到&#8220;正确&#8221;的 &nbsp; CWnd &nbsp; 指针，比如 &nbsp; CMainFrame, &nbsp; CView &nbsp; 的指针。因为需要从这些指针调用 &nbsp; CWnd &nbsp; 的虚函数（如PreTranslateMessage），这些虚函数可能被重载过。 &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 大部分情况下，对任意句柄使用 &nbsp; FromHandle &nbsp; 是不错的，因为大多情况下只利用返回的 &nbsp; CWnd &nbsp; 指针调用的非虚函数，返回的即使是一个临时对象，调用也是正确的（MFC &nbsp; 中较少用 &nbsp; FromHandlePermanent，除非确定句柄是由本线程创建的或不需要创建临时对象）。 &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 但是在某些情况下，比如从使用 &nbsp; MFC &nbsp; 的非 &nbsp; Extension &nbsp; DLL &nbsp; 中创建的窗口，这个机制会有问题，因为窗口创建在其他的 &nbsp; MFC &nbsp; 模块之下，在 &nbsp; EXE &nbsp; 中调用 &nbsp; FromHandle，由于该模块的 &nbsp; CMapHandle &nbsp; 对象某有相关的纪录，所以只能得到临时对象，如果使用返回的指针调用 &nbsp; CWnd &nbsp; 的虚函数如 &nbsp; PreTranslateMessage，得到调用的是 &nbsp; CWnd::PreTranslateMessage，而不是 &nbsp; DLL &nbsp; 中的 &nbsp; CWnd &nbsp; 派生类重载过的 &nbsp; CWnd::PreTranslateMessage。我觉得 &nbsp; &#8220;FromHandle &nbsp; 有可能失效&#8221;这种情况是 &nbsp; MFC &nbsp; 中 &nbsp; Bug &nbsp; 的主要来源。 &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 关于 &nbsp; CMapHandle &nbsp; 的描述可以参考 &nbsp; MFC &nbsp; 代码中的以下函数和结构： &nbsp; <br>&nbsp; _AFX_MODULE_THREAD_STATE，CThreadLocal &nbsp; <br>&nbsp; CHandleMap* &nbsp; PASCAL &nbsp; afxMapHWND(BOOL &nbsp; bCreate) &nbsp; <br>&nbsp; LRESULT &nbsp; CALLBACK &nbsp; _AfxCbtFilterHook(int &nbsp; code, &nbsp; WPARAM &nbsp; wParam, &nbsp; LPARAM &nbsp; lParam) &nbsp; <br>&nbsp; BOOL &nbsp; CWinThread::PreTranslateMessage(MSG* &nbsp; pMsg) &nbsp; <br>&nbsp; BOOL &nbsp; PASCAL &nbsp; CWnd::WalkPreTranslateTree(HWND &nbsp; hWndStop, &nbsp; MSG* &nbsp; pMsg)<a href="http://topic.csdn.net/t/20030109/23/1344394.html#">Top</a></p>
<h4><strong>相关问题</strong></h4>
<div class=relation>
<ul>
    <li><a href="http://topic.csdn.net/t/20001113/14/39972.html" target=_blank rel=external>CWND和HWND的区别？</a>
    <li><a href="http://topic.csdn.net/t/20050620/14/4094072.html" target=_blank rel=external>问！CWnd和HWND的区别!</a>
    <li><a href="http://topic.csdn.net/t/20020426/20/679746.html" target=_blank rel=external>请教：Attach和FromHandle的区别</a>
    <li><a href="http://topic.csdn.net/t/20020509/14/708501.html" target=_blank rel=external>HWND 和CWnd*有什么区别</a>
    <li><a href="http://topic.csdn.net/t/20021203/11/1225969.html" target=_blank rel=external>CWnd和HWND有什么区别？</a>
    <li><a href="http://topic.csdn.net/t/20050602/12/4053718.html" target=_blank rel=external>CWindow和Cwnd有什么区别？</a>
    <li><a href="http://topic.csdn.net/t/20060123/17/4532316.html" target=_blank rel=external>CWnd和CFrameWnd有什么区别啊？</a>
    <li><a href="http://topic.csdn.net/t/20010831/10/264839.html" target=_blank rel=external>在MFC中CWindow和CWnd有什么区别！！！来者有分！！</a>
    <li><a href="http://topic.csdn.net/t/20020630/19/839625.html" target=_blank rel=external>HWND 与 CWnd对象的指针有什么区别？</a>
    <li><a href="http://topic.csdn.net/t/20050428/16/3973992.html" target=_blank rel=external>CWnd CDC hCdc 得具体区别在哪里</a> </li>
</ul>
</div>
<img src ="http://www.cppblog.com/rdu-cpp/aggbug/73468.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-02-11 16:16 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/02/11/73468.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Win32 MFC的关系收藏</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/02/11/73459.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Wed, 11 Feb 2009 06:46:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/02/11/73459.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/73459.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/02/11/73459.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/73459.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/73459.html</trackback:ping><description><![CDATA[<a href="http://blog.csdn.net/xtting_8984313/archive/2008/10/31/3191362.aspx"><u><font color=#0000ff>http://blog.csdn.net/xtting_8984313/archive/2008/10/31/3191362.aspx</font></u></a><br><br><span class=Apple-style-span style="WORD-SPACING: 0px; FONT: 12px/18px verdana; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; TEXT-ALIGN: left; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0"><a style="COLOR: rgb(51,102,153); TEXT-DECORATION: none" href="http://www.vckbase.com/document/viewdoc/?id=487"><strong>系统理解Win32 API和MFC(上)</strong></a><br><a style="COLOR: rgb(51,102,153); TEXT-DECORATION: none" href="http://www.vckbase.com/document/viewdoc/?id=488"><strong>系统理解Win32 API和MFC(下)</strong></a><br><a style="COLOR: rgb(51,102,153); TEXT-DECORATION: none" href="http://www.cnblogs.com/henryzc/articles/302023.html">MFC和Win32</a></span><img src ="http://www.cppblog.com/rdu-cpp/aggbug/73459.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-02-11 14:46 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/02/11/73459.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UNICODE编程资料(转贴)</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/02/10/73396.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Tue, 10 Feb 2009 08:59:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/02/10/73396.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/73396.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/02/10/73396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/73396.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/73396.html</trackback:ping><description><![CDATA[<a href="http://yangwei.blogbus.com/tag/Windows/"><u><font color=#0000ff>http://yangwei.blogbus.com/tag/Windows/</font></u></a><br><br><span class=Apple-style-span style="WORD-SPACING: 0px; FONT: 12px/21px Verdana; TEXT-TRANSFORM: none; COLOR: rgb(102,102,102); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; TEXT-ALIGN: left; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0">&nbsp;<span style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><font style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 12px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">1. 如何取得一个既包含单字节字符又包含双字节字符的字符串的字符个数？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">可以调用Microsoft Visual C++的运行期库包含函数_mbslen来操作多字节（既包括单字节也包括双字节）字符串。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">调用strlen函数，无法真正了解字符串中究竟有多少字符，它只能告诉你到达结尾的0之前有多少个字节。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">2. 如何对DBCS（双字节字符集）字符串进行操作？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">函数 描述<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">PTSTR CharNext （ LPCTSTR ）; 返回字符串中下一个字符的地址<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">PTSTR CharPrev （ LPCTSTR, LPCTSTR ）； 返回字符串中上一个字符的地址<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">BOOL IsDBCSLeadByte( BYTE )； 如果该字节是DBCS字符的第一个字节，则返回非0值<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">3. 为什么要使用Unicode？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">（1） 可以很容易地在不同语言之间进行数据交换。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">（2） 使你能够分配支持所有语言的单个二进制.exe文件或DLL文件。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">（3） 提高应用程序的运行效率。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">Windows 2000是使用Unicode从头进行开发的，如果调用任何一个Windows函数并给它传递一个ANSI字符串，那么系统首先要将字符串转换成 Unicode，然后将Unicode字符串传递给操作系统。如果希望函数返回ANSI字符串，系统就会首先将Unicode字符串转换成ANSI字符串，然后将结果返回给你的应用程序。进行这些字符串的转换需要占用系统的时间和内存。通过从头开始用Unicode来开发应用程序，就能够使你的应用程序更加有效地运行。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">Windows CE 本身就是使用Unicode的一种操作系统，完全不支持ANSI Windows函数<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">Windows 98 只支持ANSI，只能为ANSI开发应用程序。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">Microsoft公司将COM从16位Windows转换成Win32时，公司决定需要字符串的所有COM接口方法都只能接受Unicode字符串。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">4. 如何编写Unicode源代码？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">Microsoft 公司为Unicode设计了WindowsAPI，这样，可以尽量减少代码的影响。实际上，可以编写单个源代码文件，以便使用或者不使用Unicode来对它进行编译。只需要定义两个宏（UNICODE和_UNICODE），就可以修改然后重新编译该源文件。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">_UNICODE宏用于C运行期头文件，而UNICODE宏则用于Windows头文件。当编译源代码模块时，通常必须同时定义这两个宏。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">5. Windows定义的Unicode数据类型有哪些？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">数据类型 说明<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">WCHAR Unicode字符<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">PWSTR 指向Unicode字符串的指针<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">PCWSTR 指向一个恒定的Unicode字符串的指针<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">对应的ANSI数据类型为CHAR，LPSTR和LPCSTR。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">ANSI/Unicode通用数据类型为TCHAR，PTSTR,LPCTSTR。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">6. 如何对Unicode进行操作？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">字符集 特性 实例<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">ANSI 操作函数以str开头 strcpy<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">Unicode 操作函数以wcs开头 wcscpy<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">MBCS 操作函数以_mbs开头 _mbscpy<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">ANSI/Unicode 操作函数以_tcs开头 _tcscpy（C运行期库）<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">ANSI/Unicode 操作函数以lstr开头 lstrcpy（Windows函数）<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">所有新的和未过时的函数在Windows2000中都同时拥有ANSI和Unicode两个版本。ANSI版本函数结尾以A表示；Unicode版本函数结尾以W表示。Windows会如下定义：<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">#ifdef UNICODE<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">#define CreateWindowEx CreateWindowExW<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">#else<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">#define CreateWindowEx CreateWindowExA<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">#endif // !UNICODE<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">7. 如何表示Unicode字符串常量？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">字符集 实例<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">ANSI "string"<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">Unicode L"string"<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">ANSI/Unicode T("string")或_TEXT("string")if( szError[0] == _TEXT(&#8216;J') ){ }<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">8. 为什么应当尽量使用操作系统函数？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">这将有助于稍稍提高应用程序的运行性能，因为操作系统字符串函数常常被大型应用程序比如操作系统的外壳进程Explorer.exe所使用。由于这些函数使用得很多，因此，在应用程序运行时，它们可能已经被装入RAM。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">如：StrCat，StrChr，StrCmp和StrCpy等。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">9. 如何编写符合ANSI和Unicode的应用程序？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">（1） 将文本串视为字符数组，而不是chars数组或字节数组。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">（2） 将通用数据类型（如TCHAR和PTSTR）用于文本字符和字符串。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">（3） 将显式数据类型（如BYTE和PBYTE）用于字节、字节指针和数据缓存。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">（4） 将TEXT宏用于原义字符和字符串。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">（5） 执行全局性替换（例如用PTSTR替换PSTR）。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">（6）修改字符串运算问题。例如函数通常希望在字符中传递一个缓存的大小，而不是字节。这意味着不应该传递sizeof(szBuffer),而应该传递（sizeof(szBuffer)/sizeof(TCHAR)。另外，如果需要为字符串分配一个内存块，并且拥有该字符串中的字符数目，那么请记住要按字节来分配内存。这就是说，应该调用<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">malloc(nCharacters *sizeof(TCHAR)),而不是调用malloc(nCharacters)。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">10. 如何对字符串进行有选择的比较？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">通过调用CompareString来实现。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">标志 含义<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">NORM_IGNORECASE 忽略字母的大小写<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">NORM_IGNOREKANATYPE 不区分平假名与片假名字符<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">NORM_IGNORENONSPACE 忽略无间隔字符<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">NORM_IGNORESYMBOLS 忽略符号<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">NORM_IGNOREWIDTH 不区分单字节字符与作为双字节字符的同一个字符<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">SORT_STRINGSORT 将标点符号作为普通符号来处理<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">11. 如何判断一个文本文件是ANSI还是Unicode？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">判断如果文本文件的开头两个字节是0xFF和0xFE，那么就是Unicode，否则是ANSI。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">12. 如何判断一段字符串是ANSI还是Unicode？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">用IsTextUnicode进行判断。IsTextUnicode使用一系列统计方法和定性方法，以便猜测缓存的内容。由于这不是一种确切的科学方法，因此 IsTextUnicode有可能返回不正确的结果。<br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><strong style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">13. 如何在Unicode与ANSI之间转换字符串？</strong><br style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">Windows函数MultiByteToWideChar用于将多字节字符串转换成宽字符串；函数WideCharToMultiByte将宽字符串转换成等价的多字节字符串。</font></span></span>
<img src ="http://www.cppblog.com/rdu-cpp/aggbug/73396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-02-10 16:59 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/02/10/73396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++字符串完全指引之一 —— Win32 字符编码[转贴]</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/02/10/73395.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Tue, 10 Feb 2009 08:57:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/02/10/73395.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/73395.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/02/10/73395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/73395.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/73395.html</trackback:ping><description><![CDATA[<span class=Apple-style-span style="WORD-SPACING: 0px; FONT: 16px simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0">
<table style="FONT-SIZE: 14px; LINE-HEIGHT: 18pt; FONT-FAMILY: Tahoma; LETTER-SPACING: 1px" cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td width=40 height=74>　</td>
            <td vAlign=top width=* height=74>
            <form name=form2 action=/SYS/script/find.asp method=post>
                <table style="FONT-SIZE: 14px; LINE-HEIGHT: 18pt; FONT-FAMILY: Tahoma; LETTER-SPACING: 1px" cellSpacing=0 cellPadding=0 width="100%" border=0>
                    <tbody>
                        <tr>
                            <td><span id=docinfo>[<span class=Apple-converted-space>&nbsp;</span><font color=#009900>翻译文档</font><span class=Apple-converted-space>&nbsp;</span>本文适合中级读者 已阅读62026次 ]</span></td>
                            <td align=right><input class=rect style="BORDER-RIGHT: rgb(102,102,102) 1px solid; BORDER-TOP: rgb(102,102,102) 1px solid; FONT: 9pt 宋体; BORDER-LEFT: rgb(102,102,102) 1px solid; COLOR: rgb(0,0,0); BORDER-BOTTOM: rgb(102,102,102) 1px solid" maxLength=20 size=10 name=keyword><span class=Apple-converted-space>&nbsp;</span><select class=rect style="BORDER-RIGHT: rgb(102,102,102) 1px solid; BORDER-TOP: rgb(102,102,102) 1px solid; FONT: 9pt 宋体; BORDER-LEFT: rgb(102,102,102) 1px solid; COLOR: rgb(0,0,0); BORDER-BOTTOM: rgb(102,102,102) 1px solid" name=gclsid>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
                            <option value=100 selected>文档</option>
                            &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
                            <option value=200>代码</option>
                            &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
                            <option value=400>工具</option>
                            &nbsp; &nbsp; &nbsp;</select><span class=Apple-converted-space>&nbsp;</span><input type=image height=15 width=21 src="http://www.cppblog.com/rdu-cpp/image/go.gif" align=absMiddle border=0 name=imageField></td>
                        </tr>
                    </tbody>
                </table>
            </form>
            <table style="FONT-SIZE: 14px; LINE-HEIGHT: 18pt; FONT-FAMILY: Tahoma; LETTER-SPACING: 1px" cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td>
                        <p align=center><strong>C++字符串完全指引之一 —— Win32 字符编码<br><br></strong><br>原著：Michael Dunn<br><br>翻译：<a style="FONT-SIZE: 14px; COLOR: rgb(0,0,136); FONT-FAMILY: 宋体; TEXT-DECORATION: none" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#99;&#106;&#115;&#117;&#110;&#64;&#105;&#110;&#115;&#117;&#110;&#46;&#104;&#105;&#116;&#46;&#101;&#100;&#117;&#46;&#99;&#110;">Chengjie Sun</a></p>
                        <p><br><br>原文出处：<font size=2><a style="FONT-SIZE: 14px; COLOR: rgb(0,0,136); FONT-FAMILY: 宋体; TEXT-DECORATION: none" href="http://www.codeproject.com/string/cppstringguide1.asp" target=_blank>CodeProject：The Complete Guide to C++ Strings, Part I</a></font><br><br><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><span class=Apple-converted-space>&nbsp;</span><strong>引言</strong><br><br>　　毫无疑问，我们都看到过像 TCHAR, std::string, BSTR 等各种各样的字符串类型，还有那些以 _tcs 开头的奇怪的宏。你也许正在盯着显示器发愁。本指引将总结引进各种字符类型的目的，展示一些简单的用法，并告诉您在必要时，如何实现各种字符串类型之间的转换。<br>　　在第一部分，我们将介绍3种字符编码类型。了解各种编码模式的工作方式是很重要的事情。即使你已经知道一个字符串是一个字符数组，你也应该阅读本部分。一旦你了解了这些，你将对各种字符串类型之间的关系有一个清楚地了解。<br>　　在第二部分，我们将单独讲述string类，怎样使用它及实现他们相互之间的转换。<br><br><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><span class=Apple-converted-space>&nbsp;</span><strong>字符基础 -- ASCII, DBCS, Unicode</strong><br><br>　　所有的 string 类都是以C-style字符串为基础的。C-style 字符串是字符数组。所以我们先介绍字符类型。这里有3种编码模式对应3种字符类型。第一种编码类型是单子节字符集（single-byte character set or SBCS）。在这种编码模式下，所有的字符都只用一个字节表示。ASCII是SBCS。一个字节表示的0用来标志SBCS字符串的结束。<br>　　第二种编码模式是多字节字符集（multi-byte character set or MBCS）。一个MBCS编码包含一些一个字节长的字符，而另一些字符大于一个字节的长度。用在Windows里的MBCS包含两种字符类型，单字节字符（single-byte characters）和双字节字符（double-byte characters）。由于Windows里使用的多字节字符绝大部分是两个字节长，所以MBCS常被用DBCS代替。<br>　　在DBCS编码模式中，一些特定的值被保留用来表明他们是双字节字符的一部分。例如，在Shift-JIS编码中（一个常用的日文编码模式），0x81-0x9f之间和 0xe0-oxfc之间的值表示"这是一个双字节字符，下一个子节是这个字符的一部分。"这样的值被称作"leading bytes",他们都大于0x7f。跟随在一个leading byte子节后面的字节被称作"trail byte"。在DBCS中，trail byte可以是任意非0值。像SBCS一样，DBCS字符串的结束标志也是一个单字节表示的0。<br>　　第三种编码模式是Unicode。Unicode是一种所有的字符都使用两个字节编码的编码模式。Unicode字符有时也被称作宽字符，因为它比单子节字符宽（使用了更多的存储空间）。注意，Unicode不能被看作MBCS。MBCS的独特之处在于它的字符使用不同长度的字节编码。Unicode字符串使用两个字节表示的0作为它的结束标志。<br>　　单字节字符包含拉丁文字母表，accented characters及ASCII标准和DOS操作系统定义的图形字符。双字节字符被用来表示东亚及中东的语言。Unicode被用在COM及Windows NT操作系统内部。<br>　　你一定已经很熟悉单字节字符。当你使用char时，你处理的是单字节字符。双字节字符也用char类型来进行操作（这是我们将会看到的关于双子节字符的很多奇怪的地方之一）。Unicode字符用wchar_t来表示。Unicode字符和字符串常量用前缀L来表示。例如：</p>
                        <pre>wchar_t wch = L''1''; // 2 bytes, 0x0031
                        wchar_t* wsz = L"Hello"; // 12 bytes, 6 wide characters</pre>
                        <p><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><span class=Apple-converted-space>&nbsp;</span><strong>字符在内存中是怎样存储的</strong><br><br>　　单字节字符串：每个字符占一个字节按顺序依次存储，最后以单字节表示的0结束。例如。"Bob"的存贮形式如下：</p>
                        <table id=AutoNumber1 style="FONT-SIZE: 14px; LINE-HEIGHT: 18pt; FONT-FAMILY: Tahoma; LETTER-SPACING: 1px; BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=0 cellPadding=0 width="26%" border=1>
                            <tbody>
                                <tr>
                                    <td align=middle width="25%">42</td>
                                    <td align=middle width="25%"><font color=#990000>6F</font></td>
                                    <td align=middle width="25%">62</td>
                                    <td align=middle width="25%">00</td>
                                </tr>
                                <tr>
                                    <td align=middle width="25%"><font color=#990000>B</font></td>
                                    <td align=middle width="25%"><font color=#990000>o</font></td>
                                    <td align=middle width="25%"><font color=#990000>b</font></td>
                                    <td align=middle width="25%"><font color=#990000>BOS</font></td>
                                </tr>
                            </tbody>
                        </table>
                        <p>Unicode的存储形式，L"Bob"</p>
                        <table id=AutoNumber2 style="FONT-SIZE: 14px; LINE-HEIGHT: 18pt; FONT-FAMILY: Tahoma; LETTER-SPACING: 1px; BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=0 cellPadding=0 width="42%" border=1>
                            <tbody>
                                <tr>
                                    <td align=middle width="25%">42 00</td>
                                    <td align=middle width="25%"><font color=#990000>6F</font><span class=Apple-converted-space>&nbsp;</span>00</td>
                                    <td align=middle width="25%">62 00</td>
                                    <td align=middle width="25%">00 00</td>
                                </tr>
                                <tr>
                                    <td align=middle width="25%"><font color=#990000>B</font></td>
                                    <td align=middle width="25%"><font color=#990000>o</font></td>
                                    <td align=middle width="25%"><font color=#990000>b</font></td>
                                    <td align=middle width="25%"><font color=#990000>BOS</font></td>
                                </tr>
                            </tbody>
                        </table>
                        <p>使用两个字节表示的0来做结束标志。<br><br>　　一眼看上去，DBCS 字符串很像 SBCS 字符串，但是我们一会儿将看到 DBCS 字符串的微妙之处，它使得使用字符串操作函数和永字符指针遍历一个字符串时会产生预料之外的结果。字符串" " ("nihongo")在内存中的存储形式如下（LB和TB分别用来表示 leading byte 和 trail byte）</p>
                        <table id=AutoNumber3 style="FONT-SIZE: 14px; LINE-HEIGHT: 18pt; FONT-FAMILY: Tahoma; LETTER-SPACING: 1px; BORDER-COLLAPSE: collapse" borderColor=#111111 height=52 cellSpacing=0 cellPadding=0 width="62%" border=1>
                            <tbody>
                                <tr>
                                    <td align=middle width="25%" height=20>93<span class=Apple-converted-space>&nbsp;</span><font color=#990000>FA</font></td>
                                    <td align=middle width="25%" height=20>96<span class=Apple-converted-space>&nbsp;</span><font color=#990000>7B</font></td>
                                    <td align=middle width="25%" height=20><font color=#990000>8C EA</font></td>
                                    <td align=middle width="25%" height=20>00</td>
                                </tr>
                                <tr>
                                    <td align=middle width="25%" height=20><font color=#990000>LB TB</font></td>
                                    <td align=middle width="25%" height=20><font color=#990000>LB TB</font></td>
                                    <td align=middle width="25%" height=20><font color=#990000>LB TB</font></td>
                                    <td align=middle width="25%" height=20><font color=#990000>EOS</font></td>
                                </tr>
                                <tr>
                                    <td align=middle width="25%" height=20><img height=13 src="http://www.cppblog.com/document/journal/vckbase30/images/ri.gif" width=10 border=0></td>
                                    <td align=middle width="25%" height=20><img height=13 src="http://www.cppblog.com/document/journal/vckbase30/images/ben.gif" width=13 border=0></td>
                                    <td align=middle width="25%" height=20><img height=13 src="http://www.cppblog.com/document/journal/vckbase30/images/yu.gif" width=13 border=0></td>
                                    <td align=middle width="25%" height=20><font color=#990000>EOS</font></td>
                                </tr>
                            </tbody>
                        </table>
                        <p>值得注意的是，"ni"的值不能被解释成WORD型值0xfa93，而应该看作两个值93和fa以这种顺序被作为"ni"的编码。<br><br><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><span class=Apple-converted-space>&nbsp;</span><strong>使用字符串处理函数</strong><br><br>　　我们都已经见过C语言中的字符串函数，strcpy(), sprintf(), atoll()等。这些字符串只应该用来处理单字节字符字符串。标准库也提供了仅适用于Unicode类型字符串的函数，比如wcscpy(), swprintf(), wtol()等。<br>　　微软还在它的CRT(C runtime library)中增加了操作DBCS字符串的版本。Str***()函数都有对应名字的DBCS版本_mbs***()。如果你料到可能会遇到DBCS字符串（如果你的软件会被安装在使用DBCS编码的国家，如中国，日本等，你就可能会），你应该使用_mbs***()函数，因为他们也可以处理SBCS字符串。（一个DBCS字符串也可能含有单字节字符，这就是为什么_mbs***()函数也能处理SBCS字符串的原因）<br>　　让我们来看一个典型的字符串来阐明为什么需要不同版本的字符串处理函数。我们还是使用前面的Unicode字符串 L"Bob"：</p>
                        <table id=AutoNumber4 style="FONT-SIZE: 14px; LINE-HEIGHT: 18pt; FONT-FAMILY: Tahoma; LETTER-SPACING: 1px; BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=0 cellPadding=0 width="42%" border=1>
                            <tbody>
                                <tr>
                                    <td align=middle width="25%">42 00</td>
                                    <td align=middle width="25%"><font color=#990000>6F</font><span class=Apple-converted-space>&nbsp;</span>00</td>
                                    <td align=middle width="25%">62 00</td>
                                    <td align=middle width="25%">00 00</td>
                                </tr>
                                <tr>
                                    <td align=middle width="25%"><font color=#990000>B</font></td>
                                    <td align=middle width="25%"><font color=#990000>o</font></td>
                                    <td align=middle width="25%"><font color=#990000>b</font></td>
                                    <td align=middle width="25%"><font color=#990000>BOS</font></td>
                                </tr>
                            </tbody>
                        </table>
                        <p>　　因为x86CPU是little-endian，值0x0042在内存中的存储形式是42 00。你能看出如果这个字符串被传给strlen()函数会出现什么问题吗？它将先看到第一个字节42，然后是00，而00是字符串结束的标志，于是strlen()将会返回1。如果把"Bob"传给wcslen()，将会得出更坏的结果。wcslen()将会先看到0x6f42，然后是0x0062，然后一直读到你的缓冲区的末尾，直到发现00 00结束标志或者引起了GPF。<br>　　到目前为止，我们已经讨论了str***()和wcs***()的用法及它们之间的区别。Str***()和_mbs**()之间的有区别区别呢？明白他们之间的区别，对于采用正确的方法来遍历DBCS字符串是很重要的。下面，我们将先介绍字符串的遍历，然后回到str***()与_mbs***()之间的区别这个问题上来。<br><br><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><span class=Apple-converted-space>&nbsp;</span><strong>正确的遍历和索引字符串</strong><br><br>　　因为我们中大多数人都是用着SBCS字符串成长的，所以我们在遍历字符串时，常常使用指针的++-和-操作。我们也使用数组下标的表示形式来操作字符串中的字符。这两种方式是用于SBCS和Unicode字符串，因为它们中的字符有着相同的宽度，编译器能正确的返回我们需要的字符。<br>　　然而，当碰到DBCS字符串时，我们必须抛弃这些习惯。这里有使用指针遍历DBCS字符串时的两条规则。违背了这两条规则，你的程序就会存在DBCS有关的bugs。</p>
                        <dir>
                        <li>1．在前向遍历时，不要使用++操作，除非你每次都检查lead byte；</li>
                        <li>2．永远不要使用-操作进行后向遍历。</li>
                        </dir>
                        <p>　　我们先来阐述规则2，因为找到一个违背它的真实的实例代码是很容易的。假设你有一个程序在你自己的目录里保存了一个设置文件，你把安装目录保存在注册表中。在运行时，你从注册表中读取安装目录，然后合成配置文件名，接着读取该文件。假设，你的安装目录是C:\Program Files\MyCoolApp，那么你合成的文件名应该是C:\Program Files\MyCoolApp\config.bin。当你进行测试时，你发现程序运行正常。<br>　　现在，想象你合成文件名的代码可能是这样的：</p>
                        <pre>bool GetConfigFileName ( char* pszName, size_t nBuffSize )
                        {
                        char szConfigFilename[MAX_PATH];
                        // Read install dir from registry... we''ll assume it succeeds.
                        // Add on a backslash if it wasn''t present in the registry value.
                        // First, get a pointer to the terminating zero.
                        char* pLastChar = strchr ( szConfigFilename, ''\0'' );
                        // Now move it back one character.
                        pLastChar--;
                        if ( *pLastChar != ''\\'' )
                        strcat ( szConfigFilename, "\\" );
                        // Add on the name of the config file.
                        strcat ( szConfigFilename, "config.bin" );
                        // If the caller''s buffer is big enough, return the filename.
                        if ( strlen ( szConfigFilename ) &gt;= nBuffSize )
                        return false;
                        else
                        {
                        strcpy ( pszName, szConfigFilename );
                        return true;
                        }
                        }      </pre>
                        　　这是一段很健壮的代码，然而在遇到 DBCS 字符时它将会出错。让我们来看看为什么。假设一个日本用户使用了你的程序，把它安装在 C:\<img height=13 src="http://www.cppblog.com/document/journal/vckbase30/images/youkoso.gif" width=35 border=0>。下面是这个名字在内存中的存储形式：<br>　
                        <table id=AutoNumber5 style="FONT-SIZE: 14px; LINE-HEIGHT: 18pt; FONT-FAMILY: Tahoma; LETTER-SPACING: 1px; BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=0 cellPadding=0 width="55%" border=1>
                            <tbody>
                                <tr>
                                    <td align=middle width="12%">43</td>
                                    <td align=middle width="12%"><font color=#990000>3A</font></td>
                                    <td align=middle width="12%"><font color=#0000ff>5C</font></td>
                                    <td align=middle width="12%">83 88</td>
                                    <td align=middle width="13%">83 45</td>
                                    <td align=middle width="13%">83 52</td>
                                    <td align=middle width="13%">83<span class=Apple-converted-space>&nbsp;</span><font color=#0000ff>5C</font></td>
                                    <td align=middle width="13%">00</td>
                                </tr>
                                <tr>
                                    <td align=middle width="12%">　</td>
                                    <td align=middle width="12%">　</td>
                                    <td align=middle width="12%">　</td>
                                    <td align=middle width="12%"><font color=#990000>LB TB</font></td>
                                    <td align=middle width="13%"><font color=#990000>LB TB</font></td>
                                    <td align=middle width="13%"><font color=#990000>LB TB</font></td>
                                    <td align=middle width="13%"><font color=#990000>LB TB</font></td>
                                    <td align=middle width="13%">　</td>
                                </tr>
                                <tr>
                                    <td align=middle width="12%">C</td>
                                    <td align=middle width="12%">:</td>
                                    <td align=middle width="12%">\</td>
                                    <td align=middle width="12%"><img height=11 src="http://www.cppblog.com/document/journal/vckbase30/images/yo.gif" width=9 border=0></td>
                                    <td align=middle width="13%"><img height=13 src="http://www.cppblog.com/document/journal/vckbase30/images/u.gif" width=10 border=0></td>
                                    <td align=middle width="13%"><img height=11 src="http://www.cppblog.com/document/journal/vckbase30/images/ko.gif" width=9 border=0></td>
                                    <td align=middle width="13%"><img height=12 src="http://www.cppblog.com/document/journal/vckbase30/images/so.gif" width=10 border=0></td>
                                    <td align=middle width="13%"><span lang=EN-US style="FONT-SIZE: 12pt; COLOR: rgb(153,0,0); FONT-FAMILY: 'Courier New'">EOS</span></td>
                                </tr>
                            </tbody>
                        </table>
                        <p>　　当使用 GetConfigFileName() 检查尾部的''\\''时，它寻找安装目录名中最后的非0字节，看它是等于''\\''的，所以没有重新增加一个''\\''。结果是代码返回了错误的文件名。<br>　　哪里出错了呢？看看上面两个被用蓝色高量显示的字节。斜杠''\\''的值是0x5c。'' ''的值是83 5c。上面的代码错误的读取了一个 trail byte，把它当作了一个字符。<br>　　正确的后向遍历方法是使用能够识别DBCS字符的函数，使指针移动正确的字节数。下面是正确的代码。（指针移动的地方用红色标明）</p>
                        <pre>bool FixedGetConfigFileName ( char* pszName, size_t nBuffSize )
                        {
                        char szConfigFilename[MAX_PATH];
                        // Read install dir from registry... we''ll assume it succeeds.
                        // Add on a backslash if it wasn''t present in the registry value.
                        // First, get a pointer to the terminating zero.
                        char* pLastChar = _mbschr ( szConfigFilename, ''\0'' );
                        // Now move it back one double-byte character.
                        <font color=#ff0000>  pLastChar = CharPrev ( szConfigFilename, pLastChar );</font>
                        if ( *pLastChar != ''\\'' )
                        _mbscat ( szConfigFilename, "\\" );
                        // Add on the name of the config file.
                        _mbscat ( szConfigFilename, "config.bin" );
                        // If the caller''s buffer is big enough, return the filename.
                        if ( _mbslen ( szInstallDir ) &gt;= nBuffSize )
                        return false;
                        else
                        {
                        _mbscpy ( pszName, szConfigFilename );
                        return true;
                        }
                        }
                        </pre>
                        　　上面的函数使用CharPrev() API使pLastChar向后移动一个字符，这个字符可能是两个字节长。在这个版本里，if条件正常工作，因为lead byte永远不会等于0x5c。<br>　　让我们来想象一个违背规则1的场合。例如，你可能要检测一个用户输入的文件名是否多次出现了'':''。如果，你使用++操作来遍历字符串，而不是使用CharNext()，你可能会发出不正确的错误警告如果恰巧有一个trail byte它的值的等于'':''的值。<br>与规则2相关的关于字符串索引的规则：
                        <pre>2a. 永远不要使用减法去得到一个字符串的索引。</pre>
                        <p>违背这条规则的代码和违背规则2的代码很相似。例如，</p>
                        <pre>char* pLastChar = &amp;szConfigFilename [strlen(szConfigFilename) - 1];</pre>
                        <p>这和向后移动一个指针是同样的效果。<br><br><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><strong><span class=Apple-converted-space>&nbsp;</span>回到关于str***()和_mbs***()的区别</strong><br><br>　　现在，我们应该很清楚为什么_mbs***()函数是必需的。Str***()函数根本不考虑DBCS字符，而_mbs***()考虑。如果，你调用strrchr("C:\\ ", ''\\'')，返回结果可能是错误的，然而_mbsrchr()将会认出最后的双字节字符，返回一个指向真的''\\''的指针。<br>　　关于字符串函数的最后一点：str***()和_mbs***()函数认为字符串的长度都是以char来计算的。所以，如果一个字符串包含3个双字节字符，_mbslen()将会返回6。Unicode函数返回的长度是按wchar_t来计算的。例如，wcslen(L"Bob")返回3。<br><br><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><strong><span class=Apple-converted-space>&nbsp;</span>Win32 API中的MBCS和Unicode</strong><br><br>两组 APIs：<span class=Apple-converted-space>&nbsp;</span><br>　　尽管你也许从来没有注意过，Win32中的每个与字符串相关的API和message都有两个版本。一个版本接受MBCS字符串，另一个接受Unicode字符串。例如，根本没有SetWindowText()这个API，相反，有SetWindowTextA()和SetWindowTextW()。后缀A表明这是MBCS函数，后缀W表示这是Unicode版本的函数。<br>　　当你 build 一个 Windows 程序，你可以选择是用 MBCS 或者 Unicode APIs。如果，你曾经用过VC向导并且没有改过预处理的设置，那表明你用的是MBCS版本。那么，既然没有 SetWindowText() API，我们为什么可以使用它呢？winuser.h头文件包含了一些宏，例如：</p>
                        <pre>BOOL WINAPI SetWindowTextA ( HWND hWnd, LPCSTR lpString );
                        BOOL WINAPI SetWindowTextW ( HWND hWnd, LPCWSTR lpString );
                        #ifdef UNICODE
                        #define SetWindowText  SetWindowTextW
                        #else
                        #define SetWindowText  SetWindowTextA
                        #endif      </pre>
                        当使用MBCS APIs来build程序时，UNICODE没有被定义，所以预处理器看到：
                        <pre>#define SetWindowText SetWindowTextA</pre>
                        <p>　　这个宏定义把所有对SetWindowText的调用都转换成真正的API函数SetWindowTextA。（当然，你可以直接调用SetWindowTextA() 或者 SetWindowTextW()，虽然你不必那么做。）<br>　　所以，如果你想把默认使用的API函数变成Unicode版的，你可以在预处理器设置中，把_MBCS从预定义的宏列表中删除，然后添加UNICODE和_UNICODE。(你需要两个都定义，因为不同的头文件可能使用不同的宏。) 然而，如果你用char来定义你的字符串，你将会陷入一个尴尬的境地。考虑下面的代码：</p>
                        <pre>HWND hwnd = GetSomeWindowHandle();
                        char szNewText[] = "we love Bob!";
                        SetWindowText ( hwnd, szNewText );</pre>
                        <p>在预处理器把SetWindowText用SetWindowTextW来替换后，代码变成：</p>
                        <pre>HWND hwnd = GetSomeWindowHandle();
                        char szNewText[] = "we love Bob!";
                        SetWindowTextW ( hwnd, szNewText );</pre>
                        <p>　　看到问题了吗？我们把单字节字符串传给了一个以Unicode字符串做参数的函数。解决这个问题的第一个方案是使用 #ifdef 来包含字符串变量的定义：</p>
                        <pre>HWND hwnd = GetSomeWindowHandle();
                        #ifdef UNICODE
                        wchar_t szNewText[] = L"we love Bob!";
                        #else
                        char szNewText[] = "we love Bob!";
                        #endif
                        SetWindowText ( hwnd, szNewText );</pre>
                        <p>你可能已经感受到了这样做将会使你多么的头疼。完美的解决方案是使用TCHAR.<br><br><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><strong><span class=Apple-converted-space>&nbsp;</span>使用TCHAR</strong><br><br>　　TCHAR是一种字符串类型，它让你在以MBCS和UNNICODE来build程序时可以使用同样的代码，不需要使用繁琐的宏定义来包含你的代码。TCHAR的定义如下：</p>
                        <pre>#ifdef UNICODE
                        typedef wchar_t TCHAR;
                        #else
                        typedef char TCHAR;
                        #endif</pre>
                        <p>所以用MBCS来build时，TCHAR是char，使用UNICODE时，TCHAR是wchar_t。还有一个宏来处理定义Unicode字符串常量时所需的L前缀。</p>
                        <pre>#ifdef UNICODE
                        #define _T(x) L##x
                        #else
                        #define _T(x) x
                        #endif</pre>
                        <p>　　##是一个预处理操作符，它可以把两个参数连在一起。如果你的代码中需要字符串常量，在它前面加上_T宏。如果你使用Unicode来build，它会在字符串常量前加上L前缀。</p>
                        <pre>TCHAR szNewText[] = _T("we love Bob!");</pre>
                        <p>　　像是用宏来隐藏SetWindowTextA/W的细节一样，还有很多可以供你使用的宏来实现str***()和_mbs***()等字符串函数。例如，你可以使用_tcsrchr宏来替换strrchr()、_mbsrchr()和wcsrchr()。_tcsrchr根据你预定义的宏是_MBCS还是UNICODE来扩展成正确的函数，就像SetWindowText所作的一样。<br>　　不仅str***()函数有TCHAR宏。其他的函数如， _stprintf（代替sprinft()和swprintf()）,_tfopen（代替fopen()和_wfopen()）。 MSDN中"Generic-Text Routine Mappings."标题下有完整的宏列表。<br><br><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><strong><span class=Apple-converted-space>&nbsp;</span>字符串和TCHAR typedefs</strong><br><br>　　由于Win32 API文档的函数列表使用函数的常用名字（例如，"SetWindowText"），所有的字符串都是用TCHAR来定义的。（除了XP中引入的只适用于Unicode的API）。下面列出一些常用的typedefs，你可以在msdn中看到他们。</p>
                        <table id=AutoNumber6 style="FONT-SIZE: 14px; LINE-HEIGHT: 18pt; FONT-FAMILY: Tahoma; LETTER-SPACING: 1px; BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=4 cellPadding=4 width="98%" border=1>
                            <tbody>
                                <tr>
                                    <td align=middle width="16%"><strong>type</strong></td>
                                    <td align=middle width="42%"><strong>Meaning in MBCS builds</strong></td>
                                    <td align=middle width="42%"><strong>Meaning in Unicode builds</strong></td>
                                </tr>
                                <tr>
                                    <td width="16%">WCHAR</td>
                                    <td width="42%">wchar_t</td>
                                    <td width="42%">wchar_t</td>
                                </tr>
                                <tr>
                                    <td width="16%">LPSTR</td>
                                    <td width="42%">zero-terminated string of char (char*)</td>
                                    <td width="42%">zero-terminated string of char (char*)</td>
                                </tr>
                                <tr>
                                    <td width="16%">LPCSTR</td>
                                    <td width="42%">constant zero-terminated string of char (const char*)</td>
                                    <td width="42%">constant zero-terminated string of char (const char*)</td>
                                </tr>
                                <tr>
                                    <td width="16%">LPWSTR</td>
                                    <td width="42%">zero-terminated Unicode string (wchar_t*)</td>
                                    <td width="42%">zero-terminated Unicode string (wchar_t*)</td>
                                </tr>
                                <tr>
                                    <td width="16%">LPCWSTR</td>
                                    <td width="42%">constant zero-terminated Unicode string (const wchar_t*)</td>
                                    <td width="42%">constant zero-terminated Unicode string (const wchar_t*)</td>
                                </tr>
                                <tr>
                                    <td width="16%"><xxxxime xime="7">TCHAR</xxxxime></td>
                                    <td width="42%"><xxxxime xime="7">char</xxxxime></td>
                                    <td width="42%"><xxxxime xime="7">wchar_t</xxxxime></td>
                                </tr>
                                <tr>
                                    <td width="16%">LPTSTR</td>
                                    <td width="42%">zero-terminated string of TCHAR (TCHAR*)</td>
                                    <td width="42%">zero-terminated string of TCHAR (TCHAR*)</td>
                                </tr>
                                <tr>
                                    <td width="16%">LPCTSTR</td>
                                    <td width="42%">constant zero-terminated string of TCHAR (const TCHAR*)</td>
                                    <td width="42%">constant zero-terminated string of TCHAR (const TCHAR*)</td>
                                </tr>
                            </tbody>
                        </table>
                        <p><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><strong><span class=Apple-converted-space>&nbsp;</span>何时使用 TCHAR 和 Unicode</strong><br><br>　　到现在，你可能会问，我们为什么要使用Unicode。我已经用了很多年的char。下列3种情况下，使用Unicode将会使你受益：</p>
                        <dir>
                        <li>1．你的程序只运行在Windows NT系统中。</li>
                        <li>2． 你的程序需要处理超过MAX_PATH个字符长的文件名。</li>
                        <li>3． 你的程序需要使用XP中引入的只有Unicode版本的API.</li>
                        </dir>
                        <p>　　Windows 9x 中大多数的 API 没有实现 Unicode 版本。所以，如果你的程序要在windows 9x中运行，你必须使用MBCS APIs。然而，由于NT系统内部都使用Unicode，所以使用Unicode APIs将会加快你的程序的运行速度。每次，你传递一个字符串调用MBCS API，操作系统会把这个字符串转换成Unicode字符串，然后调用对应的Unicode API。如果一个字符串被返回，操作系统还要把它转变回去。尽管这个转换过程被高度优化了，但它对速度造成的损失是无法避免的。<br>　　只要你使用Unicode API，NT系统允许使用非常长的文件名（突破了MAX_PATH的限制，MAX_PATH=260）。使用Unicode API的另一个优点是你的程序会自动处理用户输入的各种语言。所以一个用户可以输入英文，中文或者日文，而你不需要额外编写代码去处理它们。<br>　　最后，随着windows 9x产品的淡出，微软似乎正在抛弃MBCS APIs。例如，包含两个字符串参数的SetWindowTheme() API只有Unicode版本的。使用Unicode来build你的程序将会简化字符串的处理，你不必在MBCS和Unicdoe之间相互转换。<br>　　即使你现在不使用Unicode来build你的程序，你也应该使用TCHAR及其相关的宏。这样做不仅可以的代码可以很好地处理DBCS，而且如果将来你想用Unicode来build你的程序，你只需要改变一下预处理器中的设置就可以实现了。<br><br></p>
                        <p>&#160;</p>
                        <p>&#160;</p>
                        <p>&#160;</p>
                        </td>
                    </tr>
                    <tr>
                        <td><img src="http://www.cppblog.com/rdu-cpp/image/paragraph.gif"><strong><span class=Apple-converted-space>&nbsp;</span>作者简介</strong><br>　　Michael Dunn：居住在阳光城市洛杉矶。他是如此的喜欢这里的天气以致于想一生都住在这里。他在4年级时开始编程，那时用的电脑是Apple //e。1995年，在 UCLA 获得数学学士学位，随后在Symantec 公司做 QA 工程师，在 Norton AntiVirus 组工作。他自学了 Windows 和 MFC 编程。1999-2000年，他设计并实现了 Norton AntiVirus 的新界面。　<br>　　Michael 现在在 Napster（一个提供在线订阅音乐服务的公司）做开发工作，他还开发了UltraBar，一个IE工具栏插件，它可以使网络搜索更加容易，给了 googlebar 以沉重打击；他还开发了 CodeProject SearchBar；与人共同创建了 Zabersoft 公司，该公司在洛杉矶和丹麦的 Odense 都设有办事处。<br>　　他喜欢玩游戏。爱玩的游戏有 pinball, bike riding，偶尔还玩 PS, Dreamcasth 和 MAME 游戏。他因忘了自己曾经学过的语言：法语、汉语、日语而感到悲哀。</td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
</span><img src ="http://www.cppblog.com/rdu-cpp/aggbug/73395.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-02-10 16:57 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/02/10/73395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>string.format in c++</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/01/22/72467.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Thu, 22 Jan 2009 08:14:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/01/22/72467.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/72467.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/01/22/72467.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/72467.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/72467.html</trackback:ping><description><![CDATA[C#里面的string.Format用着很爽，可是在C++里面拼字符串好像就不那么便捷了。<br>对一般内置类型来说，sprintf当能满足大部分需求。而对于自定义类型而言，可以利用stringstream来曲线救国：<br><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"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sstream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;foo()<br><img id=Codehighlighter1_32_115_Open_Image onclick="this.style.display='none'; Codehighlighter1_32_115_Open_Text.style.display='none'; Codehighlighter1_32_115_Closed_Image.style.display='inline'; Codehighlighter1_32_115_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_32_115_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_32_115_Closed_Text.style.display='none'; Codehighlighter1_32_115_Open_Image.style.display='inline'; Codehighlighter1_32_115_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_32_115_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_32_115_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;stringstream&nbsp;ss;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ss&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">x:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;_x&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\ty:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;_y;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;ss.str();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>当然了，这里_x,_y的类型均需实现了<br>friend&nbsp;ostream&amp;&nbsp; operator &lt;&lt; (ostream&amp;&nbsp; s, ObjClass&amp; m)<br><br>----------------华丽的分割线--------------<br>
<p><strong>Input/output string stream class</strong></p>
<p>
<table class=hierarchy>
    <tbody>
        <tr>
            <td>
            <div><strong><a href="http://www.cplusplus.com/ios_base"><font color=#0000ff><u>ios_base</u></font></a></strong></div>
            </td>
            <td><font color=#0000ff><u><img src="http://www.cplusplus.com/img/arrow.gif"></u></font></td>
            <td>
            <div><strong><a href="http://www.cplusplus.com/ios"><font color=#0000ff><u>ios</u></font></a></strong></div>
            </td>
            <td><font color=#0000ff><u><img src="http://www.cplusplus.com/img/arrow.gif"></u></font></td>
            <td>
            <div><strong><a href="http://www.cplusplus.com/istream"><font color=#0000ff><u>istream</u></font></a></strong></div>
            </td>
            <td><font color=#0000ff><u><img src="http://www.cplusplus.com/img/arrow.gif"></u></font></td>
            <td>
            <div><strong><a href="http://www.cplusplus.com/iostream"><u><font color=#0000ff>iostream</font></u></a></strong></div>
            </td>
            <td><u><font color=#0000ff><img src="http://www.cplusplus.com/img/arrow.gif"></font></u></td>
            <td>
            <div><strong>stringstream</strong></div>
            </td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td><img src="http://www.cplusplus.com/img/arrow.gif"></td>
            <td>
            <div><strong><a href="http://www.cplusplus.com/ostream"><u><font color=#0000ff>ostream</font></u></a></strong></div>
            </td>
            <td><u><font color=#0000ff><img src="http://www.cplusplus.com/img/arrow.gif"></font></u></td>
            <td><u><font color=#0000ff></font></u></td>
            <td><u><font color=#0000ff></font></u></td>
            <td><u><font color=#0000ff></font></u></td>
        </tr>
    </tbody>
</table>
<p><tt>stringstream</tt> provides an interface to manipulate strings as if they were input/output streams.</p>
<a title="ref of stringstream from cplusplus.com" href="http://www.cplusplus.com/reference/iostream/stringstream/">ref of stringstream from cplusplus.com</a><br>
<img src ="http://www.cppblog.com/rdu-cpp/aggbug/72467.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-01-22 16:14 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/01/22/72467.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>cout &lt;&lt; 标准输出流的输出顺序</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/01/22/cout_stream_order.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Thu, 22 Jan 2009 04:50:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/01/22/cout_stream_order.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/72455.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/01/22/cout_stream_order.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/72455.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/72455.html</trackback:ping><description><![CDATA[看下面的代码：<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: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;increment(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">i)<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img id=Codehighlighter1_64_98_Open_Image onclick="this.style.display='none'; Codehighlighter1_64_98_Open_Text.style.display='none'; Codehighlighter1_64_98_Closed_Image.style.display='inline'; Codehighlighter1_64_98_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_64_98_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_64_98_Closed_Text.style.display='none'; Codehighlighter1_64_98_Open_Image.style.display='inline'; Codehighlighter1_64_98_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_64_98_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_64_98_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">i)&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">i;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img id=Codehighlighter1_112_231_Open_Image onclick="this.style.display='none'; Codehighlighter1_112_231_Open_Text.style.display='none'; Codehighlighter1_112_231_Closed_Image.style.display='inline'; Codehighlighter1_112_231_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_112_231_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_112_231_Closed_Text.style.display='none'; Codehighlighter1_112_231_Open_Image.style.display='inline'; Codehighlighter1_112_231_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_112_231_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_112_231_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a(</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;increment(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">a)&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&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">;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>输出是什么？<br>答案是： 不确定。<br><br>因为C++标准并没有对cout顺序作出规定，所以这段代码的输出取决于你的编译器。<br>在VS2005中，输出为：11&nbsp;&nbsp;&nbsp; 11&nbsp;&nbsp; 10<br>而在dev c++ 4.9.9.2中，输出为： 11&nbsp;&nbsp;&nbsp; 11&nbsp;&nbsp;&nbsp; 11<br><br>CSDN上有人讨论过这个问题： <a href="http://topic.csdn.net/u/20081120/20/2c57cb9c-0ed6-41b2-9b65-ea182ecf606d.html">http://topic.csdn.net/u/20081120/20/2c57cb9c-0ed6-41b2-9b65-ea182ecf606d.html</a>&nbsp;<br>上面有人解释道：<br>
<table class="item reply" cellSpacing=1 csdnid="reply_53716867">
    <tbody>
        <tr>
            <td class=info>
            <p class=icon>&nbsp;</p>
            </td>
            <td class=main>
            <table style="HEIGHT: 100%" cellSpacing=0>
                <tbody>
                    <tr>
                        <td class=floor><span>发表于：<var csdnid="replyDate">2008-11-20 21:04:54</var></span><var csdnid="replyLayer">6</var>楼&nbsp;得分:<var csdnid="replyPoint">0</var></td>
                    </tr>
                    <tr>
                        <td class=content id=reply53716867_body csdnid="replyBody" name="reply_body">
                        <dl class=code>
                        <dt>C/C++ code
                        <dd>
                        <pre>
                        <div><!--
                        Code highlighting produced by Actipro CodeHighlighter (freeware)
                        http://www.CodeHighlighter.com/
                        --><span style="COLOR: #000000">
                        cout的输出是先从右往左读入缓冲区，再从左往右输出；
                        假设a </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #800080">1</span><span style="COLOR: #000000">; b </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #800080">2</span><span style="COLOR: #000000">; c </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #800080">3</span><span style="COLOR: #000000">;
                        cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">b</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">c</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;
                        缓冲区：</span><span style="COLOR: #000000">|</span><span style="COLOR: #800080">3</span><span style="COLOR: #000000">|</span><span style="COLOR: #800080">2</span><span style="COLOR: #000000">|</span><span style="COLOR: #800080">1</span><span style="COLOR: #000000">|&lt;-</span><span style="COLOR: #000000">   (把&#8220;</span><span style="COLOR: #000000">&lt;-</span><span style="COLOR: #000000">&#8221;看作是指针)
                        输出：</span><span style="COLOR: #000000">|</span><span style="COLOR: #800080">3</span><span style="COLOR: #000000">|</span><span style="COLOR: #800080">2</span><span style="COLOR: #000000">|&lt;-</span><span style="COLOR: #000000">     (输出 </span><span style="COLOR: #800080">1</span><span style="COLOR: #000000">)
                        </span><span style="COLOR: #000000">|</span><span style="COLOR: #800080">3</span><span style="COLOR: #000000">|&lt;-</span><span style="COLOR: #000000">       (输出 </span><span style="COLOR: #800080">2</span><span style="COLOR: #000000">)
                        </span><span style="COLOR: #000000">|&lt;-</span><span style="COLOR: #000000">         (输出 </span><span style="COLOR: #800080">3</span><span style="COLOR: #000000">)
                        你的f(a)是直接进入缓冲区的：</span><span style="COLOR: #000000">|</span><span style="COLOR: #800080">7</span><span style="COLOR: #000000">|</span><span style="COLOR: #800080">8</span><span style="COLOR: #000000">|</span><span style="COLOR: #800080">9</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">
                        输出</span><span style="COLOR: #000000">&lt;-</span><span style="COLOR: #000000">
                        缓冲区相当于堆栈的效果。。。
                        </span></div>
                        </pre>
                        </dd></dl></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
貌似正确，实属误导!<br><br>
<img src ="http://www.cppblog.com/rdu-cpp/aggbug/72455.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-01-22 12:50 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/01/22/cout_stream_order.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dangerous c-styled func: gets</title><link>http://www.cppblog.com/rdu-cpp/archive/2009/01/21/72422.html</link><dc:creator>rdu</dc:creator><author>rdu</author><pubDate>Wed, 21 Jan 2009 07:37:00 GMT</pubDate><guid>http://www.cppblog.com/rdu-cpp/archive/2009/01/21/72422.html</guid><wfw:comment>http://www.cppblog.com/rdu-cpp/comments/72422.html</wfw:comment><comments>http://www.cppblog.com/rdu-cpp/archive/2009/01/21/72422.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/rdu-cpp/comments/commentRss/72422.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/rdu-cpp/services/trackbacks/72422.html</trackback:ping><description><![CDATA[<font size=2>如果您使用cin來取得使用者的輸入字串，則您會發現輸入字串時中間不能包括空白，如果您想要在輸入字串時包括空白，您必須使用gets()函式，例如： <br></font>
<div style="MARGIN-LEFT: 40px"><small><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">char str[80]; </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">cout &lt;&lt; "輸入字串："; </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">gets(str); </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">cout &lt;&lt; "輸入的字串：" &lt;&lt; str &lt;&lt; endl;</span><br></small></div>
<small><br>使用gets()函式時有一點必須注意，就是它並不會檢查使用者的輸入是否超出字元陣列的長度，使用時必須小心，有的編譯器會提示警告訊息。 <br></small>
<div style="MARGIN-LEFT: 40px"><small><span style="FONT-WEIGHT: bold; COLOR: rgb(255,0,0); FONT-FAMILY: Courier New,Courier,monospace">: the `gets' function is dangerous and should not be used.</span><br></small></div>
<small><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: #008080">1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br></span><span style="COLOR: #008080">2</span><span style="COLOR: #000000"><img id=Codehighlighter1_11_88_Open_Image onclick="this.style.display='none'; Codehighlighter1_11_88_Open_Text.style.display='none'; Codehighlighter1_11_88_Closed_Image.style.display='inline'; Codehighlighter1_11_88_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_11_88_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_11_88_Closed_Text.style.display='none'; Codehighlighter1_11_88_Open_Image.style.display='inline'; Codehighlighter1_11_88_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_11_88_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.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_11_88_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;str[</span><span style="COLOR: #000000">9</span><span style="COLOR: #000000">];<br></span><span style="COLOR: #008080">4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;puts(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">input&nbsp;a&nbsp;string:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;gets(str);<br></span><span style="COLOR: #008080">6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;puts(str);<br></span><span style="COLOR: #008080">7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&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></span><span style="COLOR: #008080">8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>在VS 2005中，如果输入了一个长度大于8（9-1）的字符串，VS 2005在编译期不给出上述警告，但是在执行完毕后会跳出对话框提示：<br>Run-Time Check Failure #2 - Stack around the variable 'str' was corrupted.</small> 
<img src ="http://www.cppblog.com/rdu-cpp/aggbug/72422.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/rdu-cpp/" target="_blank">rdu</a> 2009-01-21 15:37 <a href="http://www.cppblog.com/rdu-cpp/archive/2009/01/21/72422.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>