﻿<?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++博客-Jiang's C++ Space-随笔分类-Windows Programming</title><link>http://www.cppblog.com/guogangj/category/10228.html</link><description>创作，也是一种学习的过程。</description><language>zh-cn</language><lastBuildDate>Mon, 08 Aug 2011 06:40:29 GMT</lastBuildDate><pubDate>Mon, 08 Aug 2011 06:40:29 GMT</pubDate><ttl>60</ttl><item><title>从C++到C#的一些注意事项</title><link>http://www.cppblog.com/guogangj/archive/2011/08/08/152776.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Mon, 08 Aug 2011 05:03:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2011/08/08/152776.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/152776.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2011/08/08/152776.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/152776.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/152776.html</trackback:ping><description><![CDATA[<div>C++毫无疑问是软件开发工具中的工业标准，但要说做Windows开发，现在恐怕看起来还是用.net比较划算，使用.net的C++叫&#8220;Managed C++&#8221;，我看了之后只想说这句话：这货不是C++。这里顺带提起一次面试经历，是我面试别人，我告诉来面试的人：&#8220;我们目前的软件项目使用C++开发，没用.net。&#8221;他一脸诧异地问道：&#8220;你现在用的是VC6？&#8221;我说：&#8220;不是，我用的是VS2008。&#8221;他说：&#8220;那你用的就是.net，从VS2003开始都是.net。&#8221;我解释道：&#8220;我在做本地开发，没使用.net。&#8221;而这位哥们继续坚持说我就是用.net开发，我很郁闷，也许我们说的是不同的话，互相之间无法理解得了。总而言之，Managed C++的用户是极少的，从某种意义上说，C#为.net而生，而.net也为C#而生，用C++做.net开发可是半点优势都没有。这是题外话，OK，进入正题。<br /><br /><strong>1，最最最要注意的就是：垃圾回收机制<br /></strong><br />C#没有delete，其托管资源不需要delete，也不能显式delete，完全由.net的垃圾回收器来管理。<br /><br />稍微有点麻烦的是非托管资源，比如打开的文件句柄，创建的位图句柄等，这些是非托管资源，如果一直不显式回收，那有可能会越来越多，那怎么办？这方面的问题在绝大多数的C#的书籍上都有讲述，有时候看得人晕头转向的，其实我们只要遵循这么一种规范，就可以应对不说100%，也有99%的情况了：<br /><br />类中没有非托管资源的情况下，啥都不用管，也不用实现析构函数。<br />如果类中有非托管资源，则应该实现析构函数，并且在析构函数中释放资源。<br />如果类中有非托管资源，并且想让类使用者提前释放掉这些非托管资源的话，那就实现一个Dispose的方法来释放非托管资源，再加上这么一行代码GC.SuppressFinalize(this);以此来告诉.net的垃圾回收器，不需要再调用一次析构函数来释放非托管资源了。<br /><br /><strong>2，值/引用，struct/class</strong><br /><br />C#的struct和class差别很大，不像C++那样几乎没什么差别，struct适用于创建小的结构，它使用的是值传递，而用class的对象使用的是引用传递。<br /><br />值，存在于栈区，而引用，则存在于堆区。<br /><br />struct：存在于栈区，可用new初始化（也可以不用），没有默认构造函数（但可以添加构造函数，也可以不添加），没析构函数，不能被继承。<br />class：存在于堆区，必须用new初始化，有默认构造函数，有析构函数，当然能被继承啦。<br /><br /><strong>3，注意装箱和拆箱</strong><br /><br />值和引用有时候得互相转换，比如当一个函数需要引用参数，而你却把值传了过去，那么就存在这么一个隐式转换的过程了，这个过程会有额外的性能开销，所以要尽量避免。值转为引用叫&#8220;装箱&#8221;，反过来引用转为值叫&#8220;拆箱&#8221;。装箱可以是隐式的，但拆箱一定是显式的，如：<br /><br />int i = 123;<br />object o = i; //装箱（隐式）<br />int j = (int) o; //拆箱（显式）<br /><br /><strong>4，其它一些语法差别<br /></strong><br />4.1 虚方法必须带上override修饰，否则会有warning。<br />4.2 没有了C++构造函数中的&#8220;初始化列表&#8221;。<br />4.3 布尔和整型是两种不同类型。<br />4.4 switch语句的行为和C++的略有不同。<br /><br /></div><img src ="http://www.cppblog.com/guogangj/aggbug/152776.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2011-08-08 13:03 <a href="http://www.cppblog.com/guogangj/archive/2011/08/08/152776.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用VC++访问文本文件</title><link>http://www.cppblog.com/guogangj/archive/2011/06/08/148257.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Wed, 08 Jun 2011 04:26:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2011/06/08/148257.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/148257.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2011/06/08/148257.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/148257.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/148257.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 初一看这个标题，稍微做过C++编程的人都不认为这是什么困难的事情，但细细想起来还是有些需要注意的。其中我想最主要的就是文本文件的格式了，我们目前常见的有下面这四种，也就是Windows的记事本所能保存的那四种格式了：1，ANSI，也是我们最最常见的文本文件格式，在中文操作系统中，使用默认的GBK编码，而港台用的繁体中文操作系统则默认使用Big5码，简体中文操作系统打开Big5码的文本文件，会显...&nbsp;&nbsp;<a href='http://www.cppblog.com/guogangj/archive/2011/06/08/148257.html'>阅读全文</a><img src ="http://www.cppblog.com/guogangj/aggbug/148257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2011-06-08 12:26 <a href="http://www.cppblog.com/guogangj/archive/2011/06/08/148257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WM_SIZE在WM_CREATE之前？</title><link>http://www.cppblog.com/guogangj/archive/2010/10/21/130733.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Thu, 21 Oct 2010 05:01:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2010/10/21/130733.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/130733.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2010/10/21/130733.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/130733.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/130733.html</trackback:ping><description><![CDATA[我一直认为创建一个窗口的时候，窗口处理过程处理WM_CREATE是在处理WM_SIZE之前的，所以很多初始化的东西都放在WM_CREATE处来做，但最近弄一个程序发现到了WM_SIZE处出错，原因是空指针，而这个指针应该是在WM_CREATE的时候被赋值的，奇怪了，难道WM_SIZE会在WM_CREATE之前？于是设两个断点，不看不知道，一看还真的如此，如下图：<br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/size_before_create_1.png" width=684 height=291><br>程序每次总是先触到WM_SIZE的这个断点，难道我理解一直有误？于是我创建了一个hello world程序，调试了半天，又发觉没有这个问题，WM_CREATE总是在WM_SIZE之前，我尝试在别处重现问题，无果&#8230;&#8230;现在，你再仔细看一下上图，你发现问题了么？<br><br>我想经过我这么提示，你应该知道了：原因就是WM_CREATE这个断点前一行的SetWindowLong这个调用，这个调用会引起一个WM_SIZE事件，所以这就制造了WM_SIZE在WM_CREATE之前这个假象。处理这个问题很简单，把SetWindowLong这行拿掉，然后把WS_NONAVDONEBUTTON这个属性交给CreateWindow，如下图：<br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/size_before_create_2.png" width=835 height=140><br>这样就好了，我想顺便提个问题，我在设计一个程序的时候，也碰到了&#8220;布局&#8221;和&#8220;加载&#8221;的先后问题，因为布局可能需要重新调整加载的资源，而加载资源又需要参考布局的尺寸，由于功能上的原因，我必须把两者分开，所以存在我前面说的这个先鸡先蛋的难题。最后我是这么弄的，做一个&#8220;资源是否已经加载&#8221;的标志，然后总是先&#8220;布局&#8221;，布局的时候检查这个标志，如果没有资源的加载，那就只更改尺寸参数而不调整资源，这样看起来就没什么问题了，从逻辑上来说我的设计确实是WM_SIZE优先于WM_CREATE&#8230;&#8230;<br><br>欢迎对这些方面的设计问题留言讨论。
<img src ="http://www.cppblog.com/guogangj/aggbug/130733.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2010-10-21 13:01 <a href="http://www.cppblog.com/guogangj/archive/2010/10/21/130733.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>控制台(Console)程序和Windows程序到底有什么差别？</title><link>http://www.cppblog.com/guogangj/archive/2010/09/15/126631.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Wed, 15 Sep 2010 02:01:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2010/09/15/126631.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/126631.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2010/09/15/126631.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/126631.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/126631.html</trackback:ping><description><![CDATA[<p>这是我在《Programming Microsoft Windows with C#》（此书作者是大名鼎鼎的Charles Petzold）一书中找到的描述：<br><br>This compiler switch doesn't do anything very profound. It really only sets a flag in the executable file that indicates how the program is to be loaded an run. If an executable is flagged as a Console Application and is started from Windows, the Windows operating system creates a Command Prompt window that launches the program and displays any console output from the program. If the console application is started from within the Command Prompt window, the MS-DOS promptdoesn't return until the program terminateds. If the executable is flagged as a Windows Application, no Command Prompt window is created. Any console output from the program goes into the bit bucket. If you start such a program from the Command Prompt window, the MS-DOS prompt appears again right after the program is launched. The point is this: nothing bad happens if you compile a Windows Forms application as a console application!<br><br>作者之前提到的编译选项是/target:exe和/target:winexe，前者生成控制台程序，后者生成Windows程序，这是C#的编译器，而VC++的连接器的选项却有些不同，看这张图：<br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/compiler_option_console.png" width=747 height=578><br>如果你在应用程序向导里指定的是一个Windows程序，而你后来却在这个连接器选项里选择Console，那会怎么样呢？——会连接失败！因为VC++连接器认为Console程序和Windows程序的入口函数是不同，这样简单的一改它会找不到入口函数，所以连接失败。<br><br>但不管这样，通过Charles Petzold的这段描述，我们对Console程序和Windows程序的认识应该是没什么问题了，两者其实并没有什么根本不同，只是Windows根据PE文件中的标识，用稍微不同的方法来运行这两种程序而已。<br><br>BTW：Windows程序可以创建自己的控制台（参考AllocConsole等API），控制台程序也可以创建窗口。</p>
<img src ="http://www.cppblog.com/guogangj/aggbug/126631.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2010-09-15 10:01 <a href="http://www.cppblog.com/guogangj/archive/2010/09/15/126631.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows异常处理简介</title><link>http://www.cppblog.com/guogangj/archive/2010/08/11/123071.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Wed, 11 Aug 2010 07:30:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2010/08/11/123071.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/123071.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2010/08/11/123071.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/123071.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/123071.html</trackback:ping><description><![CDATA[以前有这么个问题，如果代码不小心发生了一个异常，比如除零异常，但我不想让代码就此弹框结束，我想让代码忽略掉这个异常继续运行，那应该怎么办？<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"><br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;c</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">b;<br>}<br></span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(<img src="http://www.cppblog.com/Images/dot.gif">)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Ignore&nbsp;that&nbsp;error&nbsp;and&nbsp;continue&nbsp;to&nbsp;work!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>}</span></div>
这段代码并不奏效，因为除零错误是一个系统异常，而不是一个C++类型异常，所以catch不到的，这种异常类型也就没法通过这种方式来处理了。必须用Windows特有的异常处理方式：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">__try<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;c</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">b;<br>}<br>__except(EXCEPTION_EXECUTE_HANDLER)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Ignore&nbsp;that&nbsp;error&nbsp;and&nbsp;continue&nbsp;to&nbsp;work!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>}</span></div>
这样就没有问题了，而且我们可以在__except中调用GetExceptionCode来获得异常代码，比如这个例子的异常代码是0xC0000094，表示&#8220;整型除零异常&#8221;。试图访问一个非法地址导致的异常也同样可以通过这种方式来捕捉到。例如：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">__try<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">;<br>}<br>__except(EXCEPTION_EXECUTE_HANDLER)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Exception[%0X]&nbsp;occured!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;GetExceptionCode());<br>}</span></div>
异常代码0xC0000005，这个我们见得太多了，也就是非法地址访问异常。<br>这种方式的异常处理还有个妙用，那就是用来取代goto语句。大致这样：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">__try<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;rtn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Foo1();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">rtn)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__leave;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;rtn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Foo2();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">rtn)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__leave;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Blah&nbsp;Blah&nbsp;Blah<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">}<br>__finally<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Do&nbsp;some&nbsp;job&nbsp;to&nbsp;release&nbsp;the&nbsp;resources.</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">}</span></div>
进一步信息请查看MSDN，查找&#8220;__try&#8221;等关键字就可以了。<br>值得注意的是，这种方式的异常处理不能和C++风格的异常处理同时使用，否则会编译通不过。
<img src ="http://www.cppblog.com/guogangj/aggbug/123071.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2010-08-11 15:30 <a href="http://www.cppblog.com/guogangj/archive/2010/08/11/123071.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用安全字符串函数</title><link>http://www.cppblog.com/guogangj/archive/2010/08/10/122923.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Tue, 10 Aug 2010 05:12:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2010/08/10/122923.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/122923.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2010/08/10/122923.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/122923.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/122923.html</trackback:ping><description><![CDATA[先看看可能有问题或者有歧义的代码：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">TCHAR&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ABC中文</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>INT&nbsp;iLen&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;lstrlen(p);</span></div>
lstrlen返回的到底是字符串的字符数目，还是字符串所占据的字节数呢？再看：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">TCHAR&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">more&nbsp;than&nbsp;10&nbsp;characters.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>TCHAR&nbsp;szBuff[</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">];<br>lstrcpy(szBuff,&nbsp;p);</span></div>
明显要复制到szBuff的字符串比szBuff本身要长，那会导致什么问题呢？如果要复制的字符串的长度正好就是10，那szBuff会不会在末尾加上一个字符串结束标志'\0'呢？<br><br>使用新的安全字符串函数之后，上面的都不是问题了，关于安全字符串函数，技术细节还是很多的，但我们不用管那么多，我们只需要关心我们用得最多的几个就可以了。<br><br>
<table style="WIDTH: 320px; BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 cellPadding=3>
    <tbody>
        <tr>
            <td>旧函数</td>
            <td>新函数（字符）</td>
            <td>新函数（字节）</td>
        </tr>
        <tr>
            <td>lstrlen</td>
            <td>StringCchLength</td>
            <td>StringCbLength</td>
        </tr>
        <tr>
            <td>lstrcpy</td>
            <td>StringCchCopy</td>
            <td>StringCbCopy</td>
        </tr>
        <tr>
            <td>lstrcat</td>
            <td>StringCchCat</td>
            <td>StringCbCat</td>
        </tr>
        <tr>
            <td>wsprintf</td>
            <td>StringCchPrintf</td>
            <td>StringCbPrintf</td>
        </tr>
    </tbody>
</table>
<br>你会发现，一个旧的函数对应了两个新的函数，理解这个并不难，因为新的函数大多需要你指定一个&#8220;最长长度&#8221;，那这个长度究竟指的是字符数目还是字节长度呢？如果指的是字符数目的话，那就用Cch系列的，否则就用Cb系列的。好我们改一下上面的代码：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">TCHAR&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ABC中文</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>size_t&nbsp;iLen;<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">We&nbsp;want&nbsp;to&nbsp;get&nbsp;the&nbsp;character&nbsp;number</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">StringCchLength(p,&nbsp;STRSAFE_MAX_CCH,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">iLen);</span></div>
这样就比较好地避免了歧义。<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;BUFFER_SIZE&nbsp;10</span><span style="COLOR: #000000"><br>TCHAR&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">more&nbsp;than&nbsp;10&nbsp;characters.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>TCHAR&nbsp;szBuff[BUFFER_SIZE];<br>StringCchCopy(szBuff,&nbsp;BUFFER_SIZE,&nbsp;p);<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">szBuff&nbsp;is&nbsp;"more&nbsp;than"&nbsp;now,&nbsp;it&nbsp;always&nbsp;ends&nbsp;with&nbsp;a&nbsp;'\0'</span></div>
这样的字符拷贝也就不存在越界的问题了，并且能保证字符串总是能以'\0'结束。其它的嘛，读者就举一反三自己看看了，基本用用还是没问题的，如果有兴趣还可以直接看看这些字符串函数的代码，不简单的哦。<br><br>最后，别忘了使用的时候包含strsafe.h头文件。
<img src ="http://www.cppblog.com/guogangj/aggbug/122923.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2010-08-10 13:12 <a href="http://www.cppblog.com/guogangj/archive/2010/08/10/122923.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让TinyXML保存文件为UTF-8格式</title><link>http://www.cppblog.com/guogangj/archive/2010/07/05/119351.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Mon, 05 Jul 2010 07:31:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2010/07/05/119351.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/119351.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2010/07/05/119351.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/119351.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/119351.html</trackback:ping><description><![CDATA[<p style="FONT-FAMILY: 宋体">TinyXML是个好东西，这个不用我多说了，我用它做过好几个项目，但这几个项目都只是从xml文件中获取信息，没有涉及到写文件，最近需要生成xml的配置文件，才注意到这个问题，那就是TinyXML似乎不能保存文件为UTF-8格式。</p>
<p style="FONT-FAMILY: 宋体">我用UltraEdit打开生成的xml文件，UltraEdit把它识别为ASCII格式的文本文件，而通过二进制查看，也确实如此，我看了下帮助文档，也没具体提及到这个问题。但后来我仔细整理了一下思路后，发觉这个其实不算什么问题，分析如下。</p>
<p style="FONT-FAMILY: 宋体">文档上就说明了，TinyXML是完全支持UTF-8的，可以尝试load一个UTF-8格式的xml文件，完全没有问题，那现在问题是load了一个UTF-8文件后，文件中的字符串，在TiXmlDocument对象中，到底是什么格式？TinyXML在load它之后会不会直接把UTF-8格式转为Unicode格式？——不会，为什么？因为TinyXML在编写的时候是把自己定位为一个比较单纯的C++ Lib，它没有使用任何Windows相关的API，包括很重要的两个编码转换函数WideCharToMultiByte和MultiByteToWideChar，它都没用，对不同平台，编码转换函数可能是不同的，因此TinyXML不会画蛇添足地提供这个转换，也就是说，如果你的xml文件（UTF-8格式）中如果有中文的话，用TinyXML加载进来之后，依旧是UTF-8的，不经过转换直接print出来的话，就是乱码了，所以要经过一个UTF-8到Unicode的转换，转换代码我这里就不写了。再说一下，TinyXML声称对UTF-8的支持表示它认识UTF-8的xml文件，但并不表示它自动对UTF-8的文本进行转换。</p>
<p style="FONT-FAMILY: 宋体">好，再回到保存的问题上，其实你差不多想到了，应该怎么做，因为整个TinyXML其实并不计较内存中的文本究竟是什么内容，它都可以把文本当做是UTF-8（当然了，实际上把文本转为UTF-8然后交给TinyXML的工作是我们的程序去完成），那我们可不可以说保存的xml文件其实就已经是UTF-8格式的？——答案是肯定的。而UTF-8的格式标志其实就是文件头的三个字节：0xEF，0xBB，0xBF。有了这个头，用UltraEdit打开这个xml，UltraEdit就把它认为是一个UTF-8的文本文件了。<br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/tinyxml_utf_8.PNG" width=720 height=115></p>
<p style="FONT-FAMILY: 宋体">这个改动非常简单，稍微浏览下TinyXML的代码就知道怎么改了，我下载的TinyXML是2.6.1版本的（我没记错的话），在tinyxml.cpp文件中搜索&#8220;useMicrosoftBOM&#8221;，把&#8220;useMicrosoftBOM = false;&#8221;这个语句改为&#8220;useMicrosoftBOM = true;&#8221;就可以了，好像一共才三处地方，十分简单，代码一看就懂，不多说了。</p>
<img src ="http://www.cppblog.com/guogangj/aggbug/119351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2010-07-05 15:31 <a href="http://www.cppblog.com/guogangj/archive/2010/07/05/119351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>非MFC程序使用TRACE</title><link>http://www.cppblog.com/guogangj/archive/2010/06/09/117453.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Wed, 09 Jun 2010 03:19:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2010/06/09/117453.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/117453.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2010/06/09/117453.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/117453.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/117453.html</trackback:ping><description><![CDATA[<p>我们都知道MFC有个很有用的宏，叫TRACE，它用起来跟printf一样简单，能直接在VC++的output窗口中输出调试信息，但非MFC的project却没有这个宏，只能用OutputDebugString这个API输出，而OutputDebugString这个API却不支持类似printf这样的输出格式，而且不能在Release版本中自动关闭，于是我自己写了一个，其实实现起来还是蛮简单的，上代码：</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#ifdef&nbsp;_DEBUG<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;MYTRACE&nbsp;&nbsp;DbgStrOut</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#else</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;MYTRACE</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;My&nbsp;debug&nbsp;output&nbsp;function</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;DbgStrOut(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;TCHAR&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">fmt,&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">);</span></div>
把这个定义写在预编译头中（默认是stdafx.h），就能很方便在别处调用了。这个MYTRACE的作用就相当于TRACE。下面是写在cpp文件中的代码。<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;DbgStrOut(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;TCHAR&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">fmt,&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;TCHAR&nbsp;szOutStr[</span><span style="COLOR: #000000">512</span><span style="COLOR: #000000">];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;va_list&nbsp;ap;<br>&nbsp;&nbsp;&nbsp;&nbsp;va_start(ap,&nbsp;fmt);<br>&nbsp;&nbsp;&nbsp;&nbsp;vswprintf(szOutStr,&nbsp;fmt,&nbsp;ap);<br>&nbsp;&nbsp;&nbsp;&nbsp;va_end(ap);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;OutputDebugString(szOutStr);<br>}</span></div>
这样就可以了，我尝试了Windows Mobile的项目，也是可以通过的，而且支持TCHAR字符串，也就是说可以用Unicode。:)
<img src ="http://www.cppblog.com/guogangj/aggbug/117453.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2010-06-09 11:19 <a href="http://www.cppblog.com/guogangj/archive/2010/06/09/117453.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>把内存数据转变为流</title><link>http://www.cppblog.com/guogangj/archive/2010/04/02/111421.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Fri, 02 Apr 2010 05:11:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2010/04/02/111421.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/111421.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2010/04/02/111421.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/111421.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/111421.html</trackback:ping><description><![CDATA[<span style="FONT-FAMILY: 宋体">如题，用这种方法即可：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">strstream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></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><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">假设pData指向了内存中你想要转变为流的数据<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">iLen是数据长度</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">strstreambuf&nbsp;buff(pData,&nbsp;iLen);<br>istream&nbsp;xmlStream(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">buff);<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">xmlStream也就是你要的流了</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">xmlStream</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">xmldoc;</span></div>
你并不用担心strstreambuf会额外占用什么空间，它只是把它其中的一个成员指向了内存中的数据的地址而已。<br></span>
<img src ="http://www.cppblog.com/guogangj/aggbug/111421.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2010-04-02 13:11 <a href="http://www.cppblog.com/guogangj/archive/2010/04/02/111421.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最简易对称加密</title><link>http://www.cppblog.com/guogangj/archive/2009/09/29/97523.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Tue, 29 Sep 2009 02:34:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2009/09/29/97523.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/97523.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2009/09/29/97523.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/97523.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/97523.html</trackback:ping><description><![CDATA[<p>我们日常工作中经常要对一些东西进行加密，可选的加密方法当然很多了，Windows都自带了加密库，但密码学方面的东西实在令我头大，可能因为我从小学开始数学一直没学好的缘故，而我仔细考虑之后发觉：我们对信息加密，不一定是出自于什么&#8220;top security&#8221;的原因，大多可能仅仅是不想让用户看到具体的文件的结构或保护一些个人隐私信息，也就是说对安全的要求一般，没必要引入太过重量级的东西，最好是非常快捷、高效和轻量的。那本文提供了一种方法，能让你的信息看起来被很好地加过密了，并且你根本不需要去研究什么密码学，也不需要引入什么庞大的Lib，因为代码就那么几行。</p>
<p>写这个程序的时候其实我是想要这么一种加密方法：假如明文只有一个字节，那加密出来的密文应该也只有一个字节。而实际上别人实现好的AES算法加密出来的密文通常都要带上一串随机数，不太符合我的要求。</p>
<p>没有什么include，没有什么LIB，更没有什么DLL，代码再简单不过，但我保证它很有效，OK，不多说了，看代码：</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">String.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">加密和解密，其实这两个函数完全相同的，简单起见嘛，另外我居然允许密码为空，也是简单起见</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;JiangEncode(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pBuff,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iBuffLen,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pKey</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">NULL,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iKeyLen</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;JiangDecode(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pBuff,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iBuffLen,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pKey</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">NULL,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iKeyLen</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">这个main函数是用来测试的</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;TEST_LEN&nbsp;100</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;totest[TEST_LEN];<br>&nbsp;memcpy(totest,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">012345678901234567890123456789012345678901234567890123456789\</span><span style="COLOR: #000000"><br></span><span style="COLOR: #000000">0123456789012345678901234567890123456789</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;100);</span><span style="COLOR: #000000"><br></span><span style="COLOR: #000000"><br>&nbsp;JiangEncode(totest,&nbsp;TEST_LEN,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">J~xye</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">);<br><br>&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i;<br>&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">TEST_LEN;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br>&nbsp;{<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((i</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;totest[i]);<br>&nbsp;}<br><br>&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><br>&nbsp;JiangDecode(totest,&nbsp;TEST_LEN,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">J~xye</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">);<br><br>&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">TEST_LEN;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br>&nbsp;{<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((i</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;totest[i]);<br>&nbsp;}<br><br>&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">交换两个BYTE</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Swap2Byte(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;v1,&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;v2)<br>{<br>&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">v1&nbsp;</span><span style="COLOR: #000000">^=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">v2;<br>&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">v2&nbsp;</span><span style="COLOR: #000000">^=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">v1;<br>&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">v1&nbsp;</span><span style="COLOR: #000000">^=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">v2;<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;GetMyCypher(</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;pKey,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iKeyLen,&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pMyCypher)<br>{<br>&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">原始加密索引</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;cypherOrg[</span><span style="COLOR: #000000">256</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"><br>&nbsp;{<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">15</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">17</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">51</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">85</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">255</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">26</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">46</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">114</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">150</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">161</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">248</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">19</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">53</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">95</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">225</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">56</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">72</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">216</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">115</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">149</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">164</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">247</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">30</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">34</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">102</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">170</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">229</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">52</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">92</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">228</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">55</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">89</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">235</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">38</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">106</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">190</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">217</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">112</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">144</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">171</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">230</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">49</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">83</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">245</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">12</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">60</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">68</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">204</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">79</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">209</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">104</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">184</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">211</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">110</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">178</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">205</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">76</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">212</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">103</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">169</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">224</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">59</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">77</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">215</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">98</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">166</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">241</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">24</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">40</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">120</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">136</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">131</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">158</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">185</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">208</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">107</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">189</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">220</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">127</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">129</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">152</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">179</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">206</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">73</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">219</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">118</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">154</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">181</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">196</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">87</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">249</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">16</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">48</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">80</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">240</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">11</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">29</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">39</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">105</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">187</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">214</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">97</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">163</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">254</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">25</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">43</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">125</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">135</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">146</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">173</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">236</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">47</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">113</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">147</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">174</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">233</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">32</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">96</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">160</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">251</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">22</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">58</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">78</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">210</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">109</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">183</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">194</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">93</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">231</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">50</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">86</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">250</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">21</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">63</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">65</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">195</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">94</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">226</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">61</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">71</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">201</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">64</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">192</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">91</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">237</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">44</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">116</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">156</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">191</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">218</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">117</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">159</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">186</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">213</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">172</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">239</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">42</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">126</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">130</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">157</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">188</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">223</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">122</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">142</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">137</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">128</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">155</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">182</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">193</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">88</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">232</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">35</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">101</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">175</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">234</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">37</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">111</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">177</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">67</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">197</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">84</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">252</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">31</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">33</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">99</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">165</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">244</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">7</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">9</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">27</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">45</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">119</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">153</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">176</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">203</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">70</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">202</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">69</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">207</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">74</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">222</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">121</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">139</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">134</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">145</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">168</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">227</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">62</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">66</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">198</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">81</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">243</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">14</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">18</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">54</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">90</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">238</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">41</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">123</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">141</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">140</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">143</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">138</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">133</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">148</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">167</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">242</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">13</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">23</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">57</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">75</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">221</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">124</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">132</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">151</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">162</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">253</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">28</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">36</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">108</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">180</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">199</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">82</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">246</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"><br>&nbsp;};<br><br>&nbsp;memcpy(pMyCypher,&nbsp;cypherOrg,&nbsp;</span><span style="COLOR: #000000">256</span><span style="COLOR: #000000">);<br><br>&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">根据密码调整加密索引</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i,&nbsp;j;<br>&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iKeyLen;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br>&nbsp;{<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(j</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;j</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">256</span><span style="COLOR: #000000">;&nbsp;j</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iSwitchIndex&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(pMyCypher[j]&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pKey[i])</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">255</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(iSwitchIndex</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">j)<br>&nbsp;&nbsp;&nbsp;&nbsp;Swap2Byte(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(pMyCypher[j]),&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">(pMyCypher[iSwitchIndex]));<br>&nbsp;&nbsp;}<br>&nbsp;}<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;JiangCode(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pBuff,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iBuffLen,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pKey,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iKeyLen)<br>{<br>&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;cypher[</span><span style="COLOR: #000000">256</span><span style="COLOR: #000000">];<br>&nbsp;GetMyCypher(pKey,&nbsp;iKeyLen,&nbsp;cypher);<br>&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iIndex</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(iIndex</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iBuffLen)<br>&nbsp;{<br>&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">其实&#8230;&#8230;也就一个异或操作，所以加密和解密的过程完全一样</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;pBuff[iIndex]&nbsp;</span><span style="COLOR: #000000">^=</span><span style="COLOR: #000000">&nbsp;cypher[iIndex</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">256</span><span style="COLOR: #000000">];<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">iIndex;<br>&nbsp;}<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;JiangEncode(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pBuff,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iBuffLen,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pKey,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iKeyLen)<br>{<br>&nbsp;JiangCode(pBuff,&nbsp;iBuffLen,&nbsp;pKey,&nbsp;iKeyLen);<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;JiangDecode(unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pBuff,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iBuffLen,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pKey,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iKeyLen)<br>{<br>&nbsp;JiangCode(pBuff,&nbsp;iBuffLen,&nbsp;pKey,&nbsp;iKeyLen);<br>}</span></div>
<p>写完了，运行结果是如下：</p>
<p>241 206 235 249 4 160 190 73 253 196<br>160 238 105 243 18 190 10 97 26 66<br>182 218 99 73 40 204 208 123 196 46<br>76 208 117 159 38 66 234 117 142 52<br>66 63 135 193 60 49 228 15 12 58<br>131 252 1 171 96 72 254 198 171 201<br>110 242 27 189 199 108 136 12 177 215<br>88 66 156 183 221 142 27 45 61 221<br>122 158 39 174 123 112 156 241 77 227<br>112 148 57 67 225 30 47 49 83 94</p>
<p>48 49 50 51 52 53 54 55 56 57<br>48 49 50 51 52 53 54 55 56 57<br>48 49 50 51 52 53 54 55 56 57<br>48 49 50 51 52 53 54 55 56 57<br>48 49 50 51 52 53 54 55 56 57<br>48 49 50 51 52 53 54 55 56 57<br>48 49 50 51 52 53 54 55 56 57<br>48 49 50 51 52 53 54 55 56 57<br>48 49 50 51 52 53 54 55 56 57<br>48 49 50 51 52 53 54 55 56 57 Press any key to continue</p>
<p>上面这段是密文，看起来是不是完全没有原文的样子了？你试试看把TEST_LEN改为1，只加密一个字节看，这也是允许的，代码纯C，移植性很好，拿去别处用也方便。但对安全性要求高的应用可能不能使用这种方法了，至于怎么样才算安全，我也不知道，密码学方面的东西我最害怕了。<br></p>
<img src ="http://www.cppblog.com/guogangj/aggbug/97523.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2009-09-29 10:34 <a href="http://www.cppblog.com/guogangj/archive/2009/09/29/97523.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【CSDN】Winsock原理</title><link>http://www.cppblog.com/guogangj/archive/2009/09/28/97443.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Mon, 28 Sep 2009 03:09:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2009/09/28/97443.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/97443.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2009/09/28/97443.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/97443.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/97443.html</trackback:ping><description><![CDATA[<p><span style="COLOR: red">【20060407发表于blog.csdn.net，20090928重编辑】</span><br><span style="COLOR: #0000ff"><br>（博主：此为转载文章，出处已经记不清，内容有些泛泛而谈，仅供参考）<br></span><br><strong><span style="FONT-SIZE: 18pt">一、客户机/服务器模式</span></strong></p>
<p>在TCP/IP网络中两个进程间的相互作用的主机模式是客户机/服务器模式(Client/Server model)。该模式的建立基于以下两点：<br>1、非对等作用；<br>2、通信完全是异步的。<br>客户机/服务器模式在操作过程中采取的是主动请示方式。</p>
<p>服务器方要先启动，并根据请示提供相应服务，过程如下：<br>1、打开一通信通道并告知本地主机，它愿意在某一个公认地址上接收客户请求。<br>2、等待客户请求到达该端口。<br>3、接收到重复服务请求，处理该请求并发送应答信号。<br>4、返回第二步，等待另一客户请求<br>5、关闭服务器。</p>
<p>然后死客户方：<br>1、打开一通信通道，并连接到服务器所在主机的特定端口。<br>2、向服务器发送服务请求报文，等待并接收应答；继续提出请求&#8230;&#8230;<br>3、请求结束后关闭通信通道并终止。</p>
<p><strong style="FONT-SIZE: 18pt">二、基本套接字</strong></p>
<p>为了更好说明套接字编程原理，给出几个基本的套接字，在以后的篇幅中会给出更详细的使用说明。</p>
<p><strong>1、创建套接字——socket()</strong><br>功能：使用前创建一个新的套接字<br>格式：SOCKET PASCAL FAR socket(int af,int type,int procotol);<br>af: 通信发生的区域<br>type: 要建立的套接字类型<br>procotol: 使用的特定协议 </p>
<p><strong>2、指定本地地址——bind()</strong><br>功能：将套接字地址与所创建的套接字号联系起来。<br>格式：int PASCAL FAR bind(SOCKET s,const struct sockaddr FAR * name,int namelen);<br>s: 是由socket()调用返回的并且未作连接的套接字描述符（套接字号）。<br>其它：没有错误，bind()返回0，否则SOCKET_ERROR</p>
<p>地址结构说明：</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;sockaddr_in<br>{<br>&nbsp;</span><span style="COLOR: #0000ff">short</span><span style="COLOR: #000000">&nbsp;sin_family;&nbsp;　　　　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">AF_INET</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;u_short&nbsp;sin_port;&nbsp;　　　　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">16位端口号，网络字节顺序</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;in_addr&nbsp;sin_addr;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">32位IP地址，网络字节顺序</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;sin_zero[</span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">];&nbsp;　　　　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">保留</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">}</span></div>
<p><strong>3、建立套接字连接——connect()和accept()</strong><br>功能：共同完成连接工作<br>格式：int PASCAL FAR connect(SOCKET s,const struct sockaddr FAR * name,int namelen);<br>格式：SOCKET PASCAL FAR accept(SOCKET s,struct sockaddr FAR * name,int FAR * addrlen);<br>(参数同上)</p>
<p><strong>4、监听连接——listen()</strong><br>功能：用于面向连接服务器，表明它愿意接收连接。<br>格式：int PASCAL FAR listen(SOCKET s, int backlog);</p>
<p><strong>5、数据传输——send()与recv()</strong><br>功能：数据的发送与接收<br>格式：int PASCAL FAR send(SOCKET s,const char FAR * buf,int len,int flags);<br>格式：int PASCAL FAR recv(SOCKET s,const char FAR * buf,int len,int flags);<br>buf:指向存有传输数据的缓冲区的指针。 </p>
<p><strong>6、多路复用——select()</strong><br>功能：用来检测一个或多个套接字状态。<br>格式：int PASCAL FAR select(int nfds,fd_set FAR * readfds,fd_set FAR * writefds, <br>&nbsp;fd_set FAR * exceptfds,const struct timeval FAR * timeout);<br>readfds:指向要做读检测的指针<br>writefds:指向要做写检测的指针<br>exceptfds:指向要检测是否出错的指针<br>timeout:最大等待时间</p>
<p><strong>7、关闭套接字——closesocket()</strong><br>功能：关闭套接字s<br>格式：BOOL PASCAL FAR closesocket(SOCKET s);<br><br><strong><span style="FONT-SIZE: 18pt">三、典型过程图</span></strong></p>
<p><strong>2.1 面向连接的套接字的系统调用时序图</strong></p>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/winsock_principle_1.jpg" width=435 height=566></p>
<p><strong>2.2 无连接协议的套接字调用时序图</strong></p>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/winsock_principle_2.jpg" width=417 height=279></p>
<p><strong>2.3 面向连接的应用程序流程图</strong><br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/winsock_principle_3.jpg" width=414 height=339></p>
<p style="FONT-SIZE: 18pt"><strong>四、WinSock简介</strong></p>
<p>Windows Sockets 是从 Berkeley Sockets 扩展而来的，其在继承 Berkeley Sockets 的基础上，又进行了新的扩充。这些扩充主要是提供了一些异步函数，并增加了符合WINDOWS消息驱动特性的网络事件异步选择机制。</p>
<p>Windows Sockets由两部分组成：开发组件和运行组件。<br>开发组件：Windows Sockets 实现文档、应用程序接口(API)引入库和一些头文件。<br>运行组件：Windows Sockets 应用程序接口的动态链接库(WINSOCK.DLL)。 <br><br><span style="FONT-SIZE: 18pt"><strong>五、WinSock主要扩充说明</strong></span> </p>
<p><strong>1、异步选择机制</strong><br>Windows Sockets 的异步选择函数提供了消息机制的网络事件选择，当使用它登记网络事件发生时，应用程序相应窗口函数将收到一个消息，消息中指示了发生的网络事件，以及与事件相关的一些信息。Windows Sockets 提供了一个异步选择函数 WSAAsyncSelect()，用它来注册应用程序感兴趣的网络事件，当这些事件发生时，应用程序相应的窗口函数将收到一个消息。</p>
<p>函数结构如下：<br>int PASCAL FAR WSAAsyncSelect(SOCKET s,HWND hWnd,unsigned int wMsg,long lEvent); <br>hWnd：窗口句柄<br>wMsg：需要发送的消息<br>lEvent：事件（以下为事件的内容）</p>
<p>事件值含义：<br>FD_READ 期望在套接字上收到数据（即读准备好）时接到通知<br>FD_WRITE 期望在套接字上可发送数据（即写准备好）时接到通知<br>FD_OOB 期望在套接字上有带外数据到达时接到通知<br>FD_ACCEPT 期望在套接字上有外来连接时接到通知<br>FD_CONNECT 期望在套接字连接建立完成时接到通知<br>FD_CLOSE 期望在套接字关闭时接到通知</p>
<p>例如：我们要在套接字读准备好或写准备好时接到通知，语句如下： <br>rc=WSAAsyncSelect(s,hWnd,wMsg,FD_READ|FD_WRITE);<br>如果我们需要注销对套接字网络事件的消息发送，只要将 lEvent 设置为0 </p>
<p><strong>2、异步请求函数</strong><br>在 Berkeley Sockets 中请求服务是阻塞的，WINDOWS SICKETS 除了支持这一类函数外，还增加了相应的异步请求函数——WSAAsyncGetXByY。 </p>
<p><strong>3、阻塞处理方法</strong><br>Windows Sockets 为了实现当一个应用程序的套接字调用处于阻塞时，能够放弃CPU让其它应用程序运行，它在调用处于阻塞时便进入一个叫&#8220;HOOK&#8221;的例程，此例程负责接收和分配WINDOWS消息，使得其它应用程序仍然能够接收到自己的消息并取得控制权。</p>
<p>WINDOWS 是非抢先的多任务环境，即若一个程序不主动放弃其控制权，别的程序就不能执行。因此在设计Windows Sockets 程序时，尽管系统支持阻塞操作，但还是反对程序员使用该操作。但由于 SUN 公司下的 Berkeley Sockets 的套接字默认操作是阻塞的，WINDOWS 作为移植的 SOCKETS 也不可避免对这个操作支持。</p>
<p>在Windows Sockets 实现中，对于不能立即完成的阻塞操作做如下处理：DLL初始化&#8594;循环操作。在循环中，它发送任何 WINDOWS 消息，并检查这个 Windows Sockets 调用是否完成，在必要时，它可以放弃CPU让其它应用程序执行（当然使用超线程的CPU就不会有这个麻烦了^_^）。我们可以调用 WSACancelBlockingCall() 函数取消此阻塞操作。</p>
<p>在 Windows Sockets 中，有一个默认的阻塞处理例程 BlockingHook() 简单地获取并发送 WINDOWS 消息。如果要对复杂程序进行处理，Windows Sockets 中还有 WSASetBlockingHook() 提供用户安装自己的阻塞处理例程能力；与该函数相对应的则是 WSAUnhookBlockingHook()，它用于删除先前安装的任何阻塞处理例程，并重新安装默认的处理例程。请注意，设计自己的阻塞处理例程时，除了函数 WSACancelBlockingHook() 之外，它不能使用其它的 Windows Sockets API 函数。在处理例程中调用 WSACancelBlockingHook()函数将取消处于阻塞的操作，它将结束阻塞循环。</p>
<p><strong>4、出错处理</strong></p>
<p>Windows Sockets 为了和以后多线程环境（WINDOWS/UNIX）兼容，它提供了两个出错处理函数来获取和设置当前线程的最近错误号。（WSAGetLastEror()和WSASetLastError()）</p>
<p><strong>5、启动与终止</strong></p>
<p>使用函数 WSAStartup() 和 WSACleanup() 启动和终止套接字。</p>
<p><strong><span style="FONT-SIZE: 18pt">六、Windows Sockets网络程序设计核心</span></strong> </p>
<p>我们终于可以开始真正的 Windows Sockets 网络程序设计了。不过我们还是先看一看每个 Windows Sockets 网络程序都要涉及的内容。让我们一步步慢慢走。</p>
<p><strong>1、启动与终止</strong></p>
<p>在所有Windows Sockets函数中，只有启动函数WSAStartup()和终止函数WSACleanup()是必须使用的。启动函数必须是第一个使用的函数，而且它允许指定 Windows Sockets API 的版本，并获得 SOCKETS的特定的一些技术细节。本结构如下：</p>
<p>int PASCAL FAR WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData); </p>
<p>其中 wVersionRequested 保证 SOCKETS 可正常运行的 DLL 版本，如果不支持，则返回错误信息。我们看一下下面这段代码，看一下如何进行 WSAStartup() 的调用：</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">WORD&nbsp;wVersionRequested;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;定义版本信息变量</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">WSADATA&nbsp;wsaData;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">定义数据信息变量</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;err;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">定义错误号变量</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">wVersionRequested&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;MAKEWORD(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">给版本信息赋值</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">err&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WSAStartup(wVersionRequested,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">wsaData);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">给错误信息赋值</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(err</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>{<br>　　</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">告诉用户找不到合适的版本</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">}<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">确认&nbsp;Windows&nbsp;Sockets&nbsp;DLL&nbsp;支持&nbsp;1.1&nbsp;版本<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">DLL&nbsp;版本可以高于&nbsp;1.1<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">系统返回的版本号始终是最低要求的&nbsp;1.1，即应用程序与DLL&nbsp;中可支持的最低版本号</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(LOBYTE(wsaData.wVersion)</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;HIBYTE(wsaData.wVersion)</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br>{<br>　　WSACleanup();</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">告诉用户找不到合适的版本</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">　　</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br>}<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Windows&nbsp;Sockets&nbsp;DLL&nbsp;被进程接受，可以进入下一步操作</span></div>
<p>关闭函数使用时，任何打开并已连接的 SOCK_STREAM 套接字被复位，但那些已由 closesocket() 函数关闭的但仍有未发送数据的套接字不受影响，未发送的数据仍将被发送。程序运行时可能会多次调用 WSAStartuo() 函数，但必须保证每次调用时的 wVersionRequested 的值是相同的。</p>
<p><strong>2、异步请求服务</strong></p>
<p>Windows Sockets 除支持 Berkeley Sockets 中同步请求，还增加了了一类异步请求服务函数 WSAAsyncGerXByY()。该函数是阻塞请求函数的异步版本。应用程序调用它时，由 Windows Sockets DLL 初始化这一操作并返回调用者，此函数返回一个异步句柄，用来标识这个操作。当结果存储在调用者提供的缓冲区，并且发送一个消息到应用程序相应窗口。常用结构如下：</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">HANDLE&nbsp;taskHnd;<br></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;hostname</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">rs6000</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>taskHnd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WSAAsyncBetHostByName(hWnd,wMsg,hostname,buf,buflen);&nbsp;&nbsp;</span></div>
<p>需要注意的是，由于 Windows 的内存对像可以设置为可移动和可丢弃，因此在操作内存对象是，必须保证 WIindows Sockets DLL 对象是可用的。 </p>
<p><strong>3、异步数据传输</strong></p>
<p>使用 send() 或 sendto() 函数来发送数据，使用 recv() 或recvfrom() 来接收数据。Windows Sockets 不鼓励用户使用阻塞方式传输数据，因为那样可能会阻塞整个 Windows 环境。下面我们看一个异步数据传输实例。</p>
<p>假设套接字 s 在连接建立后，已经使用了函数 WSAAsyncSelect() 在其上注册了网络事件 FD_READ 和 FD_WRITE，并且 wMsg 值为 UM_SOCK，那么我们可以在 Windows 消息循环中增加如下的分支语句：</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;UM_SOCK:<br>　　</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">(lParam)<br>　　{<br>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;FD_READ:<br>　　　　len&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;recv(wParam,lpBuffer,length,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br>　　　　</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;FD_WRITE:<br>　　　　</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(send(wParam,lpBuffer,len,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">SOCKET_ERROR)<br>　　　　</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>　　}<br></span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;&nbsp;</span></div>
<p><strong>4、出错处理</strong></p>
<p>Windows 提供了一个函数来获取最近的错误码 WSAGetLastError()，推荐的编写方式如下： </p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">len&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;send&nbsp;(s,lpBuffer,len,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((len</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">SOCKET_ERROR)</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">(WSAGetLastError()</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">WSAWOULDBLOCK)){<img src="http://www.cppblog.com/Images/dot.gif">}</span></div>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/guogangj/aggbug/97443.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2009-09-28 11:09 <a href="http://www.cppblog.com/guogangj/archive/2009/09/28/97443.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DLL快速入门</title><link>http://www.cppblog.com/guogangj/archive/2009/09/24/97136.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Thu, 24 Sep 2009 08:35:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2009/09/24/97136.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/97136.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2009/09/24/97136.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/97136.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/97136.html</trackback:ping><description><![CDATA[<p>三年多前我在blog.csdn.net上半转载过一篇文章，关于DLL入门的，不过内容有些凌乱，加上非原创，我打算重新写一下，更突出&#8220;快速&#8221;，内容嘛，就比较精简了，虽然精简，看完后写写DLL肯定是没问题的，相信我。</p>
<p><strong>一，快速生成一个DLL</strong></p>
<p>哦，对了，讲解还是用VC++ 6.0（简称VC6）来讲解。在VC6下new一个&#8220;Win32 Dynamic-Link Library&#8221;的Project，就叫&#8220;dllTest&#8221;吧，注意不要选择&#8220;MFC AppWizard(dll)&#8221;，因为&#8230;&#8230;这不属于本文的内容，其实最重要的是：我不太懂（^_^），然后呢，选择&#8220;An empty DLL project&#8221;即可。</p>
<p>接下来就是创建以这两个文件，并添加到Project中去：</p>
<p>lib.h</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#ifndef&nbsp;LIB_H<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;LIB_H</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;__declspec(dllexport)&nbsp;add(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;y);<br></span><span style="COLOR: #0000ff">#endif</span></div>
<p>lib.cpp</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">lib.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;add(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;y)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;x&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;y;<br>}</span></div>
<p>Build！（这么简单的程序不会通不过吧？）你就能看到你的生成目录下有个文件，叫&#8220;dllTest.dll&#8221;，这就是我们第一个dll，没几行代码，简单吧，但麻雀虽小五脏俱全，我们使用Visual Studio提供的工具&#8220;Depends&#8221;打开这个文件看看，如图所示，你能看到我们导出的这个函数，add。</p>
<p>这个超微型的dll和普通程序的不同在于add函数的声明，多了一个__declspec(dllexport)，这个是关键，这个修饰符告诉VC6，这个函数需要导出，而前面的extern "C"的意思是这个函数是以C语言的标准来调用的，如果不加extern "C"的话，会怎么样呢？自己试试看吧，Build后再用Depends看看生成的dll。<br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/fast_dll_1.png" width=500 height=386><br></p>
<p><strong>二、使用这个DLL</strong></p>
<p>用VC6的向导创建一个&#8220;Win32 Console Application&#8221;的Project，叫&#8220;CallDllTest&#8221;，然后选择&#8220;"A Hello, Word!"Application&#8221;，为什么用Console？简单呗。</p>
<p>把CallDllTest.cpp的内容换成以下：<br>CallDllTest.cpp</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#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>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br>typedef&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;(&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;lpAddFun)(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">);<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE&nbsp;hDll;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">DLL&nbsp;handle&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;lpAddFun&nbsp;addFun;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Function&nbsp;pointer</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;hDll&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;LoadLibrary(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">dllTest.dll</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(hDll&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;addFun&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(lpAddFun)GetProcAddress(hDll,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">add</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(addFun</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">NULL)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;&nbsp;addFun(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,result);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;FreeLibrary(hDll);<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
<p>Build，然后&lt;Ctrl&gt;+&lt;F5&gt;运行，就能看到结果了，打印了一个&#8220;5&#8221;出来，说明正常了，有点需要说明的是你得把前面生产的那个DLL和这次生成的EXE放在同一目录下方可。代码很简单，思路就是定义函数指针类型，加载DLL，获取要调用的函数的指针，然后调用，这么一个过程。</p>
<p><strong>三、静态链接</strong></p>
<p>刚才使用LoadLibrary这个API加载DLL的方式叫动态链接，现在来介绍静态链接，其实静态链接用得还更多，只不过你不一定注意到而已，不信的话现在查看一下你刚创建的CallDllTest这个Project的Project Settings，如图：<br></p>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/fast_dll_2.PNG" width=567 height=385><br>注意我画红线的这个地方，Kernel32.lib，user32.lib和gdi32.lib等，这些lib叫做&#8220;导入库&#8221;，并不包含真正有效的代码，真正有效的代码是存放在DLL中的，刚才我们所使用的LoadLibrary这个API，其实就是通过Kernel32.lib链接到Kernel32.dll中去的，也就是说LoadLibrary的实现存在于Kernel32.dll中，而我们是通过Kernel32.lib来找到它的，如果还有兴趣的话，可以用Depends看看Kernel32.dll，看看里面是否有LoadLibrary，里面函数很多，别看花眼了哦，这可是Windows的核心库之一，但可能你并没有找到LoadLibrary，而是找到了，LoadLibraryA和LoadLibraryW，这很正常，因为很多需要使用到字符串的API，都有两个版本，一个是窄字符版，一个是宽字符版，在程序编译链接的时候，编译器会根据你的选项来跟你选择其中一个，这里暂时不展开了。</p>
<p>那如何静态使用前面生成的那个dllTest.dll呢？回到刚才dllTest.dll的那个生成目录，你会发现一个叫dllTest.lib的文件，这就是我前面提到&#8220;导入库&#8221;，现在改一下CallDllTest.cpp。<br>CallDllTest.cpp</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#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><br>#pragma&nbsp;comment(lib,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">dllTest.lib</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br><br></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;__declspec(dllimport)&nbsp;add(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;y);<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;&nbsp;add(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,result);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
<p>dllTest.lib这个文件得复制到CallDllTest这个Project的目录下，否则会报找不到文件，执行结果如何？跟刚才是一样的，这种方式就叫静态链接，区别是什么？不需要在运行时调用LoadLibrary了，我个人觉得静态链接用得更多一些。</p>
<p>注意看代码：</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;__declspec(dllimport)&nbsp;add(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;y);</span></div>
<p>这句话很关键，__declspec(dllimport)对应了DllTest中的__declspec(dllexport)，表示该函数将从dll中导入，那你也许要问了：&#8220;我怎么知道这个dll中有这个函数？并且还知道这个函数的参数类型和返回值类型？该不会也是用Depends去看吧？&#8221;呃&#8230;&#8230;这怎么说呢？如果这个dll是你写的，你当然知道啦，但如果这个Dll不是你写的话，它的作者往往会提供一个头文件，就好像你要使用LoadLibrary，你得包含&#8220;windows.h&#8221;这个头文件一样，否则就出现符号未定义的编译错误，那么我们改一下lib.h这个头文件。</p>
<p>lib.h</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#ifndef&nbsp;LIB_H<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;LIB_H</span><span style="COLOR: #000000"><br>#ifdef&nbsp;DLLTEST_EXPORTS<br></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;__declspec(dllexport)&nbsp;add(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;y);<br></span><span style="COLOR: #0000ff">#else</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;__declspec(dllimport)&nbsp;add(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;y);<br></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#endif</span></div>
<p>在DllTest这个Project中，DLLTEST_EXPORTS是被定义了的，如图：<br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/fast_dll_3.png" width=652 height=300><br></p>
<p>所以使用dllexport，而在别的Project中，则使用dllimport。在CallDllTest中include这个lib.h，就可以了，当然你也可以写得更好，我这里仅仅是demo。</p>
<p><strong>四、DLL中的main函数</strong></p>
<p>大家都知道C语言的程序是从main开始的，到了Windows环境下，则换成了WinMain，但也差不多，那DLL有没有类似的入口呢？答案是肯定的，我们来改一下DllTest的lib.cpp。</p>
<p>lib.cpp</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">lib.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br>BOOL&nbsp;APIENTRY&nbsp;DllMain(&nbsp;HANDLE&nbsp;hModule,&nbsp;DWORD&nbsp;&nbsp;ul_reason_for_call,&nbsp;LPVOID&nbsp;lpReserved)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">&nbsp;(ul_reason_for_call)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_PROCESS_ATTACH:<br>&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\nprocess&nbsp;attach&nbsp;of&nbsp;DLL</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_THREAD_ATTACH:<br>&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\nthread&nbsp;attach&nbsp;of&nbsp;DLL</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_THREAD_DETACH:<br>&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\nthread&nbsp;detach&nbsp;of&nbsp;DLL</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_PROCESS_DETACH:<br>&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\nprocess&nbsp;detach&nbsp;of&nbsp;DLL</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;TRUE;<br>}<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;add(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;y)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;x&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;y;<br>}</span></div>
<p>你能看到一个叫&#8220;DllMain&#8221;的函数，它就是dll的入口，oh，当然了，我这篇文章所讲的都是针对Windows操作系统的，Linux的可不一样哦，甚至一般来说，Linux的DLL都不叫&#8220;DLL&#8221;。</p>
<p>好了，你再按照前面的方法去调用下这个DLL，（记得拷贝这个dll到相应目录去）这时候你就能看到执行结果中多了&#8220;process attach of DLL&#8221;和&#8220;process detach of DLL&#8221;，这是很显而易见的，一个进程连接和断开连接到这个dll的时候，DllMain就会被调用，且传递的ul_reason_for_call参数分别是DLL_PROCESS_ATTACH和DLL_PROCESS_DETACH，那什么时候会有&#8220;DLL_THREAD_ATTACH&#8221;和&#8220;DLL_THREAD_DETACH&#8221;？当库已经加载，创建新的线程和销毁线程的时候，会分别使用THREAD_ATTACH和THREAD_DETACH参数来调DllMain。</p>
<p><strong>五、调用方式</strong></p>
<p>前面我们导入，导出函数的时候都加了一个&#8220;extern "C"&#8221;，那不加会怎么样呢？如果再涉及到这几个修饰符：__stdcall，__cdecl和__fastcall，那又会怎样呢？我画了两个表，大家可以比较下，体会下。</p>
<p>这是三种不同调用方式的比较：<br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/fast_dll_4.png" width=483 height=119><br></p>
<p>这是命名修饰在不同方式下的比较：<br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/fast_dll_5.png" width=574 height=165><br></p>
<p>如果dll和exe的命名理解不一致，就有可能出错。通常来说，我是习惯于用&#8220;extern "C"&#8221;和&#8220;__cdecl&#8221;的组合。</p>
<p><strong>六、导出变量</strong></p>
<p>前面只说了如何导出函数，那如何导出一个变量呢？方法类似，甚至可以说几乎一样，看代码：</p>
<p>lib.cpp</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">lib.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iExportInt;<br><br>BOOL&nbsp;APIENTRY&nbsp;DllMain(&nbsp;HANDLE&nbsp;hModule,&nbsp;DWORD&nbsp;&nbsp;ul_reason_for_call,&nbsp;LPVOID&nbsp;lpReserved)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">&nbsp;(ul_reason_for_call)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_PROCESS_ATTACH:<br>&nbsp;&nbsp;iExportInt&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">112</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;TRUE;<br>}</span></div>
<p>lib.h</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#ifndef&nbsp;LIB_H<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;LIB_H</span><span style="COLOR: #000000"><br>#ifdef&nbsp;DLLTEST_EXPORTS<br></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;__declspec(dllexport)&nbsp;iExportInt;<br></span><span style="COLOR: #0000ff">#else</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;__declspec(dllimport)&nbsp;iExportInt;<br></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#endif</span></div>
<p>这样，就可以了，和导出函数是没什么差别吧？同样，你也可以用Depends观察生成的DLL，你会发现iExportInt这个导出符号，也就是我们导出的这个变量了。现在看CallDllTest的代码：</p>
<p>CallDllTest.cpp</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#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>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">lib.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br>#pragma&nbsp;comment(lib,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">dllTest.lib</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;iExportInt);<br>&nbsp;iExportInt</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;<br>&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;iExportInt);<br>&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></div>
<p>输出是什么？112和113，说明成功了。不知道你这个时候有没有想到一个问题，那就是如果两个进程同时调用dllTest.dll，而且同时修改和读取iExportInt，那会不会乱掉呢？要不要做一个互斥锁呢？答案是：不会，不需要。这得益于Windows内存管理的一个底层实现技术，叫Copy-on-write，在调用执行&#8220;iExportInt++&#8221;的时候，其实并非真正修改了DLL中的值，而是做了一份拷贝，通过内存映射机制，使得程序访问的那个&#8220;iExportInt&#8221;其实是那份拷贝，而另一进程使用的也是自己的拷贝，互不干涉。</p>
<p><strong>七、共享内存</strong></p>
<p>紧接着前面这个问题，那如果我企图通过DLL来让不同进程共享一段内存，而不是让系统执行默认的Copy-on-write操作，那怎么办呢？有办法！这是Microsoft提供的一个方法，个人觉得是个不错的进程间通信的方法，比如两个进程需要交换一大块数据，而且这一大块数据变化比较频繁，通过数据库啊，文件啊，就显得有点慢，如果通过socket啊，管道啊，就显得有些不直接，还是直接使用共享内存来得直接，但很多人并不知道这个功能，我这里跟大家分享下。</p>
<p>lib.h</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#ifndef&nbsp;LIB_H<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;LIB_H</span><span style="COLOR: #000000"><br>#ifdef&nbsp;DLLTEST_EXPORTS<br></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;__declspec(dllexport)&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;dataChunk[</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">];<br></span><span style="COLOR: #0000ff">#else</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;__declspec(dllimport)&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;dataChunk[</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">];<br></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">#endif</span></div>
<p>lib.cpp</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">lib.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br>#pragma&nbsp;data_seg(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">shared</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br>unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;dataChunk[</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">{</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">};<br>#pragma&nbsp;data_seg()<br><br>#pragma&nbsp;comment(linker,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/SECTION:shared,RWS</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)</span></div>
<p>Build一下，然后用Depends看看输出情况。现在来改CallDllText.cpp。这里有非常要注意的两个地方，一是&#8220;={0}&#8221;这个初始化，这是必须的，否则共享将不起作用，Microsoft规定了共享段一定需要先初始化，哪怕只是给第一个元素赋个随便什么值都好，如这个例子，我只是给第一个元素赋值了个0；另一处要注意的是&#8220;/SECTION:shared,RWS"这个字符串，中间可别要有空格，否则你同样会发现共享不起作用，我当时调试就很郁闷，因为我习惯在英文逗号后加个空格。</p>
<p>CallDllText.cpp<br></p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#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>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">lib.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br>#pragma&nbsp;comment(lib,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">dllTest.lib</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;dataChunk[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">);<br>&nbsp;Sleep(</span><span style="COLOR: #000000">10000</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
<p>Sleep(10000)会让程序堵塞10秒钟，这样就可以运行多个程序的副本，来观察共享的效果。</p>
<p><strong>八、结束</strong></p>
<p>DLL涵盖的知识面相当广，本文只是篇入门级的文章，介绍了一些比较实用的内容而已，如果要进一步学习，需要看看《Windows核心编程》这种经典著作，关于DLL的很多内容我都没有提及到，比如DLL的导出方法其实有好几种，我介绍的只是其中一种，但我认为我介绍的方法是最好用而且是最简单的。我们写程序，是为了实现某些应用，而不是为了炫耀某些技术，所以我是偏向于使用成熟，可靠和易行的方法。<br></p>
<img src ="http://www.cppblog.com/guogangj/aggbug/97136.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2009-09-24 16:35 <a href="http://www.cppblog.com/guogangj/archive/2009/09/24/97136.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最简易的坐标刻度校正算法</title><link>http://www.cppblog.com/guogangj/archive/2009/08/26/94451.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Wed, 26 Aug 2009 05:30:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2009/08/26/94451.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/94451.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2009/08/26/94451.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/94451.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/94451.html</trackback:ping><description><![CDATA[blog好一些时间没更新了，一方面是自己有些懒散了，另一方面是觉得难找到一个自己很满意的blog空间，看来看去综合上来说还是cppblog.com最好，虽然也有许多不尽人意之处。今天浮上来写篇小文，希望自己重新恢复勤快，也藉此纪念今天这个特别的&#8220;中国情人节&#8221;——七夕。<br><br>作为工程师，经常需要画些图表曲线，那刻度就成了个问题，下面我举两个例子说说这个问题：<br>数字系列1：1.12，2.4，2.3，1.16，2.5，8.9，11，32，4.6<br>画成曲线，用Excel，很简单，你很快就弄好了，如图：<br><img height=393 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/excel1.png" width=505 border=0><br>数字系列2：1234321.1，1234331.1，1234343.1，1234123.1，1234356.1，1234567.1，1234399.1，1234300.1<br>同样，用Excel画成曲线，如下图：<br><img height=350 alt="" src="http://www.cppblog.com/images/cppblog_com/guogangj/excel2.png" width=498 border=0><br><br>注意纵坐标的刻度，我说的就是这个问题，如果是你，如何来标这个刻度？<br><br>一般来说，我们日常生活中看到的刻度都是以2，2.5，5，10为间隔的，如果给出了一个最小值4.55，一个最大值5.13，要求画出大约5个刻度，那应该怎么画？如果是我，大概就画出这几个：4.4，4.6，4.8，5.0，5.2。<br><br>那这样行不行呢？(5.13-4.55)/5=0.116，于是画出这几个刻度：4.55，4.666，4.782，4.898，5.014，5.13。当然也可以，但这个算法未免太简单，画出来的刻度不好看。<br><br>那我们如何来描述我上面提到的以2，2.5，5，10为间隔的划分算法呢？我一直感觉很困难，直到今天动手去写，并且把它写出来了，才发现也就那么几行代码，我把我的代码贴出来与大家分享，我相信我这个算法经过稍微的修改就能适应所有的坐标刻度划分。<br><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">math.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><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;RegulateAll(</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dMin,&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dMax,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iMaxAxisNum);<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">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_114_400_Open_Image onclick="this.style.display='none'; Codehighlighter1_114_400_Open_Text.style.display='none'; Codehighlighter1_114_400_Closed_Image.style.display='inline'; Codehighlighter1_114_400_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_114_400_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_114_400_Closed_Text.style.display='none'; Codehighlighter1_114_400_Open_Image.style.display='inline'; Codehighlighter1_114_400_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_114_400_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_114_400_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RegulateAll(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">45</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">7</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RegulateAll(</span><span style="COLOR: #000000">0.12</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">0.43</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RegulateAll(</span><span style="COLOR: #000000">10001</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">10002</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RegulateAll(</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">12.65</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">56.3</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RegulateAll(</span><span style="COLOR: #000000">5243217834.12</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">5378234435.12</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RegulateAll(</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">0.043</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">0.099</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RegulateAll(</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">123431</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">67325</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RegulateAll(</span><span style="COLOR: #000000">0.0</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">0.0</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">5</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><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">void</span><span style="COLOR: #000000">&nbsp;RegulateAll(</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dMin,&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dMax,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iMaxAxisNum)<br><img id=Codehighlighter1_463_1331_Open_Image onclick="this.style.display='none'; Codehighlighter1_463_1331_Open_Text.style.display='none'; Codehighlighter1_463_1331_Closed_Image.style.display='inline'; Codehighlighter1_463_1331_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_463_1331_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_463_1331_Closed_Text.style.display='none'; Codehighlighter1_463_1331_Open_Image.style.display='inline'; Codehighlighter1_463_1331_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_463_1331_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_463_1331_Open_Text><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">if</span><span style="COLOR: #000000">(iMaxAxisNum</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;dMax</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">dMin)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</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: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dDelta&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dMax&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;dMin;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(dDelta</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">1.0</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Modify&nbsp;this&nbsp;by&nbsp;your&nbsp;requirement.</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_590_645_Open_Image onclick="this.style.display='none'; Codehighlighter1_590_645_Open_Text.style.display='none'; Codehighlighter1_590_645_Closed_Image.style.display='inline'; Codehighlighter1_590_645_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_590_645_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_590_645_Closed_Text.style.display='none'; Codehighlighter1_590_645_Open_Image.style.display='inline'; Codehighlighter1_590_645_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_590_645_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_590_645_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dMax</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1.0</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">dDelta)</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2.0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dMin</span><span style="COLOR: #000000">-=</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1.0</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">dDelta)</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2.0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;dDelta&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dMax&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;dMin;<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: #0000ff">int</span><span style="COLOR: #000000">&nbsp;iExp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">)(log(dDelta)</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">log(</span><span style="COLOR: #000000">10.0</span><span style="COLOR: #000000">))</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">2</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">double</span><span style="COLOR: #000000">&nbsp;dMultiplier&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;pow(</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,&nbsp;iExp);<br><img id=Codehighlighter1_781_830_Open_Image onclick="this.style.display='none'; Codehighlighter1_781_830_Open_Text.style.display='none'; Codehighlighter1_781_830_Closed_Image.style.display='inline'; Codehighlighter1_781_830_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_781_830_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_781_830_Closed_Text.style.display='none'; Codehighlighter1_781_830_Open_Image.style.display='inline'; Codehighlighter1_781_830_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dSolutions[]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_781_830_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_781_830_Open_Text><span style="COLOR: #000000">{</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">2.5</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">25</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">50</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">250</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">500</span><span style="COLOR: #000000">}</span></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;i;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(dSolutions)</span><span style="COLOR: #000000">/</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">);&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_894_1014_Open_Image onclick="this.style.display='none'; Codehighlighter1_894_1014_Open_Text.style.display='none'; Codehighlighter1_894_1014_Closed_Image.style.display='inline'; Codehighlighter1_894_1014_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_894_1014_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_894_1014_Closed_Text.style.display='none'; Codehighlighter1_894_1014_Open_Image.style.display='inline'; Codehighlighter1_894_1014_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_894_1014_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_894_1014_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dMultiCal&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dMultiplier&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;dSolutions[i];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(((</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">)(dDelta</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">dMultiCal)&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&lt;=</span><span style="COLOR: #000000">iMaxAxisNum)<br><img id=Codehighlighter1_997_1011_Open_Image onclick="this.style.display='none'; Codehighlighter1_997_1011_Open_Text.style.display='none'; Codehighlighter1_997_1011_Closed_Image.style.display='inline'; Codehighlighter1_997_1011_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_997_1011_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_997_1011_Closed_Text.style.display='none'; Codehighlighter1_997_1011_Open_Image.style.display='inline'; Codehighlighter1_997_1011_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_997_1011_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_997_1011_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dInterval&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dMultiplier&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;dSolutions[i];<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: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dStartPoint&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;((</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">)ceil(dMin</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">dInterval)&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;dInterval;<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;iAxisIndex;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(iAxisIndex</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;&nbsp;iAxisIndex</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_1188_1312_Open_Image onclick="this.style.display='none'; Codehighlighter1_1188_1312_Open_Text.style.display='none'; Codehighlighter1_1188_1312_Closed_Image.style.display='inline'; Codehighlighter1_1188_1312_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1188_1312_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1188_1312_Closed_Text.style.display='none'; Codehighlighter1_1188_1312_Open_Image.style.display='inline'; Codehighlighter1_1188_1312_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1188_1312_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_1188_1312_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%f</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;dStartPoint</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">dInterval</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">iAxisIndex);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(dStartPoint</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">dInterval</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">iAxisIndex</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">dMax)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;|&nbsp;</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;&nbsp;&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;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</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></span></div>
<p>除开打印和前面的条件判断外，真的没几行，而且只用了一个非常有限的迭代，效率自然是很高的。</p>
<img src ="http://www.cppblog.com/guogangj/aggbug/94451.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2009-08-26 13:30 <a href="http://www.cppblog.com/guogangj/archive/2009/08/26/94451.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【CSDN】关于“预编译”</title><link>http://www.cppblog.com/guogangj/archive/2009/04/23/80806.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Thu, 23 Apr 2009 02:01:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2009/04/23/80806.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/80806.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2009/04/23/80806.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/80806.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/80806.html</trackback:ping><description><![CDATA[<p style="FONT-FAMILY: 宋体"><span style="COLOR: red">【20060307发表于blog.csdn.net，20090423重编辑】</span><br><br><span style="FONT-SIZE: 18pt">一、预编译头文件说明</span><br><br>所谓头文件预编译，就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译，以后该工程编译时，不再编译这部分头文件，仅仅使用预编译的结果。这样可以加快编译速度，节省时间。<br><br>预编译头文件通过编译stdafx.cpp生成，以工程名命名，由于预编译的头文件的后缀是&#8220;pch&#8221;，所以编译结果文件是projectname.pch。<br><br>编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h这个头文件名是可以在project的编译设置里指定的。编译器认为，所有在指令#include "stdafx.h"前的代码都是预编译的，它跳过#include "stdafx. h"指令，使用projectname.pch编译这条指令之后的所有代码。<br><br>因此，所有的CPP实现文件第一条语句都是：#include "stdafx.h"。<br><br>另外，每一个实现文件CPP都包含了如下语句：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">#ifdef&nbsp;_DEBUG<br></span><span style="COLOR: #0000ff">#undef</span><span style="COLOR: #000000">&nbsp;THIS_FILE</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;THIS_FILE[]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;__FILE__;<br></span><span style="COLOR: #0000ff">#endif</span></div>
<p style="FONT-FAMILY: 宋体" align=left>这是表示，如果生成调试版本，要指示当前文件的名称。__FILE__是一个宏，在编译器编译过程中给它赋值为当前正在编译的文件名称。<br><br>vc.net默认情况下使用预编译头(/Yu)，不明白的在加入新.h文件后编译时总出现fatal error C1010: 在查找预编译头指令时遇到意外的文件结尾的错误。解决方法是在在include头文件的地方加上#include "stdafx.h",或者打项目属性，找到&#8220;C/C++&#8221;文件夹，单击&#8220;预编译头&#8221;属性页。修改&#8220;创建/使用预编译头&#8221;属性为&#8220;不使用预编译头&#8221;。<br><br><span style="FONT-SIZE: 18pt">二、C/C++头文件一览</span><br><br>C、传统 C++<br>#include &lt;assert.h&gt;　　　　//设定插入点<br>#include &lt;ctype.h&gt;　　　　 //字符处理<br>#include &lt;errno.h&gt;　　　　 //定义错误码<br>#include &lt;float.h&gt;　　　　 //浮点数处理<br>#include &lt;fstream.h&gt;　　　 //文件输入／输出<br>#include &lt;iomanip.h&gt;　　　 //参数化输入／输出<br>#include &lt;iostream.h&gt;　　　//数据流输入／输出<br>#include &lt;limits.h&gt;　　　　//定义各种数据类型最值常量<br>#include &lt;locale.h&gt;　　　　//定义本地化函数<br>#include &lt;math.h&gt;　　　　　//定义数学函数<br>#include &lt;stdio.h&gt;　　　　 //定义输入／输出函数<br>#include &lt;stdlib.h&gt;　　　　//定义杂项函数及内存分配函数<br>#include &lt;string.h&gt;　　　　//字符串处理<br>#include &lt;strstrea.h&gt;　　　//基于数组的输入／输出<br>#include &lt;time.h&gt;　　　　　//定义关于时间的函数<br>#include &lt;wchar.h&gt;　　　　 //宽字符处理及输入／输出<br>#include &lt;wctype.h&gt;　　　　//宽字符分类<br><br>标准 C++　（同上的不再注释）<br>#include &lt;algorithm&gt;　　　 //STL 通用算法<br>#include &lt;bitset&gt;　　　　　//STL 位集容器<br>#include &lt;cctype&gt;<br>#include &lt;cerrno&gt;<br>#include &lt;clocale&gt;<br>#include &lt;cmath&gt;<br>#include &lt;complex&gt;　　　　 //复数类<br>#include &lt;cstdio&gt;<br>#include &lt;cstdlib&gt;<br>#include &lt;cstring&gt;<br>#include &lt;ctime&gt;<br>#include &lt;deque&gt;　　　　　 //STL 双端队列容器<br>#include &lt;exception&gt;　　　 //异常处理类<br>#include &lt;fstream&gt;<br>#include &lt;functional&gt;　　　//STL 定义运算函数（代替运算符）<br>#include &lt;limits&gt;<br>#include &lt;list&gt;　　　　　　//STL 线性列表容器<br>#include &lt;map&gt;　　　　　　 //STL 映射容器<br>#include &lt;iomanip&gt;<br>#include &lt;ios&gt;　　　　　　 //基本输入／输出支持<br>#include &lt;iosfwd&gt;　　　　　//输入／输出系统使用的前置声明<br>#include &lt;iostream&gt;<br>#include &lt;istream&gt;　　　　 //基本输入流<br>#include &lt;ostream&gt;　　　　 //基本输出流<br>#include &lt;queue&gt;　　　　　 //STL 队列容器<br>#include &lt;set&gt;　　　　　　 //STL 集合容器<br>#include &lt;sstream&gt;　　　　 //基于字符串的流<br>#include &lt;stack&gt;　　　　　 //STL 堆栈容器　　　　<br>#include &lt;stdexcept&gt;　　　 //标准异常类<br>#include &lt;streambuf&gt;　　　 //底层输入／输出支持<br>#include &lt;string&gt;　　　　　//字符串类<br>#include &lt;utility&gt;　　　　 //STL 通用模板类<br>#include &lt;vector&gt;　　　　　//STL 动态数组容器<br>#include &lt;cwchar&gt;<br>#include &lt;cwctype&gt;<br><br>using namespace std;<br><br>C99 增加<br>#include &lt;complex.h&gt;　　 //复数处理<br>#include &lt;fenv.h&gt;　　　　//浮点环境<br>#include &lt;inttypes.h&gt;　　//整数格式转换<br>#include &lt;stdbool.h&gt;　　 //布尔环境<br>#include &lt;stdint.h&gt;　　　//整型环境<br>#include &lt;tgmath.h&gt;　　　//通用类型数学宏<br><br><span style="FONT-SIZE: 18pt">三、预处理的由来</span><br><br>在C++的历史发展中，有很多的语言特征（特别是语言的晦涩之处）来自于C语言，预处理就是其中的一个。C++从C语言那里把C语言预处理器继承过来，C语言预处理器，被Bjarne博士(C++之父)简称为Cpp，不知道是不是C Program Preprocessor的简称。<br><br><span style="FONT-SIZE: 18pt">四、常见的预处理功能</span><br><br>预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换，最常见的预处理有：文件包含，条件编译、布局控制和宏替换4种。<br><br>1，文件包含：#include 是一种最为常见的预处理，主要是做为文件的引用组合源程序正文。<br>2，条件编译：#if,#ifndef,#ifdef,#endif,#undef等也是比较常见的预处理，主要是进行编译时进行有选择的挑选，注释掉一些指定的代码，以达到版本控制、防止对文件重复包含的功能。<br>3，布局控制：#pragma，这也是我们应用预处理的一个重要方面，主要功能是为编译程序提供非常规的控制流信息。<br>4，宏替换：#define，这是最常见的用法，它可以定义符号常量、函数功能、重新命名、字符串的拼接等各种功能。<br><br><span style="FONT-SIZE: 18pt">五、预处理指令</span><br><br>预处理指令的格式如下：<br><br>#directive tokens<br><br>#符号应该是这一行的第一个非空字符，一般我们把它放在起始位置。如果指令一行放不下，可以通过&#8220;\&#8221;进行控制，例如：<br><br>#define Error if(error) exit(1)<br><br>等价于<br><br>#define Error \<br>if(error) exit(1)<br><br>下面我们看一下常见的预处理指令：<br>#define 宏定义<br>#undef 未定义宏<br>#include 文本包含<br>#ifdef 如果宏被定义就进行编译<br>#ifndef 如果宏未被定义就进行编译<br>#endif 结束编译块的控制<br>#if 表达式非零就对代码进行编译<br>#else 作为其他预处理的剩余选项进行编译<br>#elif 这是一种#else和#if的组合选项<br>#line 改变当前的行数和文件名称<br>#error 输出一个错误信息<br>#pragma 为编译程序提供非常规的控制流信息<br><br>下面我们对这些预处理进行一一的说明，考虑到宏的重要性和繁琐性，我们把它放到最后讲。<br><br><span style="FONT-SIZE: 18pt">六、文件包含指令<br></span><br>这种预处理使用方式是最为常见的，平时我们编写程序都会用到，最常见的用法是：<br>#include &lt;iostream&gt; //标准库头文件<br>#include &lt;iostream.h&gt; //旧式的标准库头文件<br>#include "IO.h" //用户自定义的头文件<br>#include "../file.h" //UNIX下的父目录下的头文件<br>#include "/usr/local/file.h" //UNIX下的完整路径<br>#include "..\file.h" //Dos下的父目录下的头文件<br>#include "\usr\local\file.h" //Dos下的完整路径<br><br>（其实DOS/Windows的目录分隔也可以用斜杠，为了和Unix兼容，就统一用斜杠吧）<br><br>这里面有2个地方要注意：<br><br>1、我们用&lt;iostream&gt;还是&lt;iostream.h&gt;?<br><br>我们主张使用&lt;iostream&gt;，而不是&lt;iostream.h&gt;,为什么呢？我想你可能还记得我曾经给出过几点理由，这里我大致的说一下：<br><br>首先，h格式的头文件早在98年9月份就被标准委员会抛弃了，我们应该紧跟标准，以适合时代的发展。其次，iostream.h只支持窄字符集，iostream则支持窄/宽字符集。还有，标准对iostream作了很多的改动，接口和实现都有了变化。最后，iostream组件全部放入namespace std中，防止了名字污染。<br><br>2、&lt;io.h&gt;和"io.h"的区别？<br><br>其实他们唯一的区别就是搜索路径不同：对于#include &lt;io.h&gt; ，编译器从标准库路径开始搜索对于#include "io.h" ，编译器从用户的工作路径开始搜索。<br><br><span style="FONT-SIZE: 18pt">七、编译控制指令</span><br><br>这些指令的主要目的是进行编译时进行有选择的挑选，注释掉一些指定的代码，以达到版本控制、防止对文件重复包含的功能。使用格式，如下：<br><br><strong>1、#ifdef identifier</strong><br><br>如果identifier为一个定义了的符号，your code就会被编译，否则剔除。<br>#ifdef identifier<br>your code<br>#endif<br><br><strong>2、#ifndef identifier<br></strong><br>如果identifier为一个未定义的符号，your code就会被编译，否则剔除。<br>#ifndef identifier<br>your code<br>#endif<br><br><strong>3、#if expression</strong><br><br>如果expression非零，your code就会被编译，否则剔除。<br>#if expression<br>your code<br>#endif<br><br><strong>4、#ifdef identifier</strong><br><br>如果identifier为一个定义了的符号，your code1就会被编译，否则your code2就会被编译。<br>#ifdef identifier<br>your code1<br>#else<br>your code2<br>#endif<br><br><strong>5、#else与#elif</strong><br><br>如果epression1非零，就编译your code1，否则，如果expression2非零，就编译your code2，否则，就编译your code3。<br>#if expressin1<br>your code1<br>#elif expression2 //呵呵，elif<br>your code2<br>#else<br>your code3<br>#enif<br><br>其他预编译指令除了上面我们说的集中常用的编译指令，还有3种不太常见的编译指令：#line、#error、#pragma，我们接下来就简单的谈一下。<br><br><strong>6，#line</strong><br><br>语法如下：<br><br>#line number filename<br><br>例如：<br><br>#line 30 a.h<br><br>其中，文件名a.h可以省略不写。这条指令可以改变当前的行号和文件名，例如上面的这条预处理指令就可以改变当前的行号为30，文件名是a.h。初看起来似乎没有什么用，不过，他还是有点用的，那就是用在编译器的编写中，我们知道编译器对C++源码编译过程中会产生一些中间文件，通过这条指令，可以保证文件名是固定的，不会被这些中间文件代替，有利于进行分析。<br><br><strong>7，#error</strong><br><br>语法如下：<br><br>#error info<br><br>例如：<br><br>#ifndef UNIX<br>#error This software requires the UNIX OS.<br>#endif<br><br>这条指令主要是给出错误信息，上面的这个例子就是，如果没有在UNIX环境下，就会输出This software requires the UNIX OS.然后诱发编译器终止。所以总的来说，这条指令的目的就是在出现其它编译错误之前能够给出一定的信息。<br><br><strong>8，#pragma</strong><br><br>它是非统一的，他要依靠各个编译器生产者。例如VC++中：<br><br>#pragma comment(lib,"dllTest.lib")<br><br>导入库dllTest.lib。<br><br><span style="FONT-SIZE: 18pt">八、预定义标识符</span><br><br>为了处理一些有用的信息，预处理定义了一些预处理标识符，虽然各种编译器的预处理标识符不尽相同，但是他们都会处理下面的4种：<br><br>__FILE__ 正在编译的文件的名字<br>__LINE__ 正在编译的文件的行号<br>__DATE__ 编译时刻的日期字符串，例如： "25 Dec 2000"<br>__TIME__ 编译时刻的时间字符串，例如： "12:30:55"<br><br>例如：cout&lt;&lt;"The file is :"&lt;&lt;__FILE__"&lt;&lt;"! The lines is:"&lt;&lt;__LINE__&lt;&lt;endl;<br><br><span style="FONT-SIZE: 18pt">九、预处理何去何从<br></span><br>如何取代#include预处理指令，我们在这里就不再一一讨论了。C++并没有为#include提供替代形式，但是namespace提供了一种作用域机制，它能以某种方式支持组合，利用它可以改善#include的行为方式，但是我们还是无法取代#include。<br><br>#pragma应该算是一个可有可无的预处理指令，按照Bjarne的话说，就是：&#8220;#pragma被过分的经常的用于将语言语义的变形隐藏到编译系统里，或者被用于提供带有特殊语义和笨拙语法的语言扩充。&#8221;<br><br>对于#ifdef，我们仍然束手无策，就算是我们利用if语句和常量表达式，仍然不足以替代它，因为一个if语句的正文必须在语法上正确，满足类检查，即使他处在一个绝不会被执行的分支里面。<br><br><span style="FONT-SIZE: 18pt">十、预编译头文件的补充说明</span><br><br>这里介绍VC6的预编译功能的使用，由于预编译详细使用比较的复杂，这里只介绍几个最重要的预编译指令: /Yu, /Yc,/Yx,/Fp。其它的详细资料可以参考:<br><br>MSDN -&gt; Visual Studio 6.0 Document -&gt; Visual C++ 6.0 Document -&gt; VC++ Programmer Guider -&gt; Compiler and Linker -&gt; Details -&gt; Creating Precompiled Header files<br><br>预编译头的概念：<br><br>所谓的预编译头就是把一个工程中的那一部分代码，预先编译好放在一个文件里（通常是以.pch为扩展名的），这个文件就称为预编译头文件这些预先编译好的代码可以是任何的C/C++代码，甚至是inline的函数，但是必须是稳定的，在工程开发的过程中不会被经常改变。如果这些代码被修改，则需要重新编译生成预编译头文件。注意生成预编译头文件是很耗时间的。同时你得注意预编译头文件通常很大，通常有6-7M大。注意及时清理那些没有用的预编译头文件。<br><br>也许你会问：现在的编译器都有Time stamp的功能，编译器在编译整个工程的时候，它只会编译那些经过修改的文件，而不会去编译那些从上次编译过，到现在没有被修改过的文件。那么为什么还要预编译头文件呢？答案在这里，我们知道编译器是以文件为单位编译的，一个文件经过修改后，会重新编译整个文件，当然在这个文件里包含的所有头文件中的东西（.eg Macro, Preprocessor ）都要重新处理一遍。VC的预编译头文件保存的正是这部分信息。以避免每次都要重新处理这些头文件。<br><br>根据上文介绍，预编译头文件的作用当然就是提高便宜速度了，有了它你没有必要每次都编译那些不需要经常改变的代码。编译性能当然就提高了。但根据我的实践经验，使用VC6编译器，在编译一个小程序的时候，用不用预编译头文件，基本看不出编译速度的差距，可能对于一个大型程序来说，这种编译速度差才能体现出来。<br><br>要使用预编译头，我们必须指定一个头文件，这个头文件包含我们不会经常改变的代码和其他的头文件，然后我们用这个头文件来生成一个预编译头文件（.pch文件）想必大家都知道 StdAfx.h这个文件。很多人都认为这是VC提供的一个&#8220;系统级别&#8221;的，编译器带的一个头文件。其实不是的，这个文件可以是任何名字的。我们来考察一个典型的由AppWizard生成的MFC Dialog Based程序的预编译头文件。（因为AppWizard会为我们指定好如何使用预编译头文件，默认的是StdAfx.h，这是VC起的名字）。我们会发现这个头文件里包含了以下的头文件：<br><br>#include &lt;afxwin.h&gt;&nbsp;&nbsp;&nbsp; // MFC core and standard components<br>#include &lt;afxext.h&gt;&nbsp;&nbsp;&nbsp; // MFC extensions<br>#include &lt;afxdisp.h&gt;&nbsp;&nbsp; // MFC Automation classes<br>#include &lt;afxdtctl.h&gt;&nbsp; // MFC support for Internet Explorer 4 Common Controls<br>#include &lt;afxcmn.h&gt;<br><br>这些正是使用MFC的必须包含的头文件，当然我们不太可能在我们的工程中修改这些头文件的，所以说他们是稳定的。<br><br>那么我们如何指定它来生成预编译头文件。我们知道一个头文件是不能编译的。所以我们还需要一个cpp文件来生成.pch 文件。这个文件默认的就是StdAfx.cpp。在这个文件里只有一句代码就是：#include &#8220;Stdafx.h&#8221;。原因是理所当然的，我们仅仅是要它能够编译而已―――也就是说，要的只是它的.cpp的扩展名。我们可以用/Yc编译开关来指定StdAfx.cpp来生成一个.pch文件，通过/Fp编译开关来指定生成的pch文件的名字。打开project -&gt;Setting-&gt;C/C++ 对话框。把Category指向Precompiled Header。在左边的树形视图里选择整个工程，如下图：<br><br><img height=389 src="http://www.cppblog.com/images/cppblog_com/guogangj/20090423_precompile_1.jpg" width=410 border=0><br>（图１）<br><br>在图中我们的Project Options(右下角的那个白的地方)可以看到 /Fp &#8220;debug/PCH.pch&#8221;，这就是指定生成的.pch文件的名字，默认的通常是　&lt;工程名&gt;.pch（我的示例工程名就是PCH）。<br><br>然后，在左边的树形视图里选择StdAfx.cpp.如图：<br><br><img height=378 src="http://www.cppblog.com/images/cppblog_com/guogangj/20090423_precompile_2.jpg" width=505 border=0><br>（图２）<br><br>这时原来的Project Option变成了 Source File Option（原来是工程，现在是一个文件，当然变了）。在这里我们可以看到 /Yc开关，/Yc的作用就是指定这个文件来创建一个Pch文件。/Yc后面的文件名是那个包含了稳定代码的头文件，一个工程里只能有一个文件的可以有YC开关。VC就根据这个选项把 StdAfx.cpp编译成一个Obj文件和一个PCH文件。<br><br>然后我们再选择一个其它的文件来看看，如图：<br><img height=400 src="http://www.cppblog.com/images/cppblog_com/guogangj/20090423_precompile_3.jpg" width=566 border=0><br>（图3）<br><br>在这里，Precomplier 选择了 Use &#8230;&#8230;&#8230;一项，头文件是我们指定创建PCH 文件的stdafx.h文件。事实上，这里是使用工程里的设置，（如图1）/Yu "stdafx.h"。<br><br>这样，我们就设置好了预编译头文件。也就是说，我们可以使用预编译头功能了。以下是注意事项：<br><br>1，如果使用了/Yu，就是说使用了预编译，我们在每个.cpp文件的最开头，我强调一遍是最开头，包含你指定产生pch文件的.h文件（默认是stdafx.h）不然就会有问题。如果你没有包含这个文件，就告诉你Unexpected file end. 如果你不是在最开头包含的，你自己试以下就知道了，绝对有很惊人的效果。<br><br>2，如果你把pch文件不小心丢了，根据以上的分析，你只要让编译器生成一个pch文件就可以了。也就是说把 stdafx.cpp（即指定/Yc的那个cpp文件）重新编译一遍就可以了。当然你可以傻傻的 Rebuild all。简单一点就是选择那个cpp文件，按一下Ctrl + F7就可以了。</p>
<img src ="http://www.cppblog.com/guogangj/aggbug/80806.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2009-04-23 10:01 <a href="http://www.cppblog.com/guogangj/archive/2009/04/23/80806.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【CSDN】Win32 GDI基础（笔记）</title><link>http://www.cppblog.com/guogangj/archive/2009/04/03/78844.html</link><dc:creator>Jiang Guogang</dc:creator><author>Jiang Guogang</author><pubDate>Fri, 03 Apr 2009 11:02:00 GMT</pubDate><guid>http://www.cppblog.com/guogangj/archive/2009/04/03/78844.html</guid><wfw:comment>http://www.cppblog.com/guogangj/comments/78844.html</wfw:comment><comments>http://www.cppblog.com/guogangj/archive/2009/04/03/78844.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guogangj/comments/commentRss/78844.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guogangj/services/trackbacks/78844.html</trackback:ping><description><![CDATA[<p style="FONT-FAMILY: 宋体"><span style="COLOR: red">【20060307发表于blog.csdn.net，20090403重编辑】</span><br><br><span style="FONT-SIZE: 18pt">1、GDI名字的意义<br></span>GDI Graphic Device Interface，我说不清和GUI有什么区别。可能一种针对设备，一种针对用户而言吧，反正以后都说GDI，也就是Windows的图形编程。<br><br><span style="FONT-SIZE: 18pt">2、设备描述上下文HDC</span><br>Handle Device Context<br>这个是关键的关键，可以理解成画图的环境，何谓环境？画板，纸，笔，尺寸，字体，颜色，区域等。反正包括你能想到的和未能想到的了。要画出不同的图形，很大程度上是对HDC的修改。<br><br><span style="FONT-SIZE: 18pt">3、HDC的创建方式<br></span>WM_PAINT消息来的时候，用：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">hdc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;BeginPaint(hwnd,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">ps);<br></span><span style="COLOR: #008000">//...</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">EndPaint(hwnd,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">ps);</span></div>
<p style="FONT-FAMILY: 宋体">结束后ps区域自动变有效。还有：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">hdc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetDC(hwnd);<br></span><span style="COLOR: #008000">//...</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">ReleaseDC(hwnd,&nbsp;hdc);</span></div>
<p style="FONT-FAMILY: 宋体">这一对需要调用ValidateRect()函数来使得区域有效。</p>
<p style="FONT-FAMILY: 宋体">还有别的办法，但不常用，这里略过。不过有一个还是值得一说，那就是取得Window HDC的办法，用它可以在Windows非客户区画图：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">hdcWindow&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetWindowDC(hwnd);<br></span><span style="COLOR: #008000">//...</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">ReleaseDC(hwnd,&nbsp;hdcWindow);</span></div>
<p style="FONT-FAMILY: 宋体"><br><span style="FONT-SIZE: 18pt">4、获取HDC信息</span><br>GetDeviceCaps()<br>其中比较重要的指标是：<br>HORZRES - horizontal resolution<br>VERTRES - vertical resolution<br>BITSPIXEL - 色深<br><br><span style="FONT-SIZE: 18pt">5、保存HDC与还原HDC</span></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">SaveDC(hdc);<br>RestoreDC(hdc,&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);</span></div>
<p style="FONT-FAMILY: 宋体"><br><span style="FONT-SIZE: 18pt">6、画图画图！</span></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">[伪码]<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;-----&nbsp;点&nbsp;-----<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画点</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">SetPixel(hdc,&nbsp;x,&nbsp;y,&nbsp;crColor);<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">取点颜色</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">crColor&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetPixel(hdc,&nbsp;x,&nbsp;y);<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;-----&nbsp;直线&nbsp;-----<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">最后一参数为NULL表示不返回最后点</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">MoveToEx(hdc,&nbsp;x,&nbsp;y,&nbsp;lpPrevPoint);<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画线</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">LineTo(hdc,&nbsp;x,&nbsp;y);<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画多线，不移动当前点</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Polyline(hdc,&nbsp;lpPoint,&nbsp;cPointNum);<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画多线，移动当前点</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">PolylineTo(hdc,&nbsp;lpPoint,&nbsp;cPointNum);<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画多组多线</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">PolyPolyline(hdc,&nbsp;lppt,&nbsp;lpNum,&nbsp;cCount);<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">-----&nbsp;曲线&nbsp;-----<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画椭圆线</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Arc();<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画比泽尔曲线，不移动但前点</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">PolyBezier();<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画比泽尔曲线，移动当前点</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">PolyBezierTo();<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">-----&nbsp;区域&nbsp;-----<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画矩形</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Rectangle();<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画椭圆</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Ellipse();<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画带圆角的矩形</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">RoundRect();<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画扇</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Pie();<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">画弓</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Chord();</span></div>
<p style="FONT-FAMILY: 宋体"><br><span style="FONT-SIZE: 18pt">7、画笔HPEN（改变线条）<br></span>方法1：<br>HPEN hPen = GetStockObject(ARGUMENTS);<br>ARGUMENTS为：BLACK_PEN 黑笔WHITE_PEN 白笔</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">HPEN&nbsp;hPen&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;SelectObject(hdc,&nbsp;GetStockObject(WHITE_PEN));<br>DelectObject(hPen);</span></div>
<p style="FONT-FAMILY: 宋体">方法2：<br>HPEN hPen = CreatePen(iPenStyle, iWidth, crColor);<br>iPenStyle为：PS_SOLID实线PS_DASH虚线PS_DOT点线PS_DASHDOT虚点线PS_DASHDOTDOT虚双点线PS_NULL空线PS_INSIDEFRAME？？</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">DeleteObject(SelectObject(hdc,&nbsp;GetStockObject(BLACK_PEN)));</span></div>
<p style="FONT-FAMILY: 宋体">获取画笔信息：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">GetObject(hPen,&nbsp;</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(LOGPEN),&nbsp;(LPVOID)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">logpen);</span></div>
<p style="FONT-FAMILY: 宋体">选出HDC中的画笔：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">hPen&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetCurrentObject(hdc,&nbsp;OBJ_PEN);</span></div>
<p style="FONT-FAMILY: 宋体"><br><span style="FONT-SIZE: 18pt">8、背景模式</span><br>改变背景模式，也就是制定虚线间间隙的填充问题了：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">SetBkColor(hdc,&nbsp;crColor);<br>SetBkMode(hdc,&nbsp;TRANSPARENT);<br>SetBkMode(hdc,&nbsp;OPAQUE);</span></div>
<p style="FONT-FAMILY: 宋体">有Set嘛，相应地有Get了，这里略过。<br><br><span style="FONT-SIZE: 18pt">9、叠加模式</span></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">SetROP2(hdc,&nbsp;iDrawMode);<br>iDrawMode&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetROP2(hdc);</span></div>
<p style="FONT-FAMILY: 宋体"><br><span style="FONT-SIZE: 18pt">10、画刷HBRUSH（改变填充）</span><br>画刷能指明区域填充模式。<br>方法1：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">HBRUSH&nbsp;hBrush&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetStockObject(GRAY_BRUSH);<br>SelectObject(hdc,&nbsp;hBrush);</span></div>
<p style="FONT-FAMILY: 宋体">方法2：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">HBRUSH&nbsp;hBrush&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateSolidBrush(crColor);<br>HBRUSH&nbsp;hBrush&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateHatchBrush(iHatchStyle,&nbsp;crColor);</span></div>
<p style="FONT-FAMILY: 宋体"><br><span style="FONT-SIZE: 18pt">11、多边形填充模式及画多边形</span></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">SetPolyFillMode(hdc,&nbsp;iMode);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">iMode：ALTERNAME&nbsp;WINDING</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Polygon();</span></div>
<p style="FONT-FAMILY: 宋体"></p>
<p style="FONT-FAMILY: 宋体"><span style="FONT-SIZE: 18pt">12、区域HRGN（绘画范围）</span></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">HRGN&nbsp;hRgn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateRectRgn(x1,&nbsp;y1,&nbsp;x2,&nbsp;y2);<br>HRGN&nbsp;hRgn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateRectRgnIndirect(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">rect);<br>HRGN&nbsp;hRgn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateEllipticRgn(x1,&nbsp;y1,&nbsp;x2,&nbsp;y2);<br>HRGN&nbsp;hRgn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateEllipticRgnIndirect(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">rect);</span></div>
<p style="FONT-FAMILY: 宋体">区域合并</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">CombineRgn(hDestRgn,&nbsp;hSrcRgn1,&nbsp;hSrcRgn2,&nbsp;iCombine);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">iCombine:&nbsp;RGN_AND,&nbsp;RGN_OR,&nbsp;RGN_XOR,&nbsp;RGN_DIFF,&nbsp;RGN_COPY</span></div>
<p style="FONT-FAMILY: 宋体">注意：hDestRgn, hSrcRgn1, hSrcRgn2都必须有效。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">FillRgn();&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">填充区域。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">FrameRgn();&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">给区域画边。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">InvertRgn();&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">反转区域。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">HRGN&nbsp;hRgnPrev&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;SelectObject(hdc,&nbsp;hRgn);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">将区域放置入HDC。</span></div>
<p style="FONT-FAMILY: 宋体">使区域无效/有效：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">InvalidateRgn(hRgn);<br>ValidateRgn(hRgn);</span></div>
<img src ="http://www.cppblog.com/guogangj/aggbug/78844.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guogangj/" target="_blank">Jiang Guogang</a> 2009-04-03 19:02 <a href="http://www.cppblog.com/guogangj/archive/2009/04/03/78844.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>