<?xml version="1.0" encoding="gb2312"?>

<!-- RSS generated by oioj.net on 4/16/2004 ; 感谢LeXRus提供 RSS 2.0 文档; 此文件可自由使用，但请保留此行信息 --> 
<!-- Source download URL: http://blogger.org.cn/blog/rss2.asp       -->
<rss version="2.0">

<channel>
<title>oceanblue的博客</title>
<link>http://blogger.org.cn/blog/blog.asp?name=oceanblue</link>
<description>oceanblue的博客</description>
<copyright>blogger.org.cn</copyright>
<generator>W3CHINA Blog</generator>
<webMaster>webmaster@blogger.org.cn</webMaster>
<item>
<title><![CDATA[批处理for命令详解]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45952</link>
<author>oceanblue</author>
<pubDate>2009/6/11 17:34:12</pubDate>
<description><![CDATA[<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">批处理for命令详解 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">2008-03-07 11:00 </SPAN></P>
<DIV>
<TABLE style="BORDER-COLLAPSE: collapse" border=0>
<COLGROUP>
<COL style="WIDTH: 582px"></COLGROUP>
<TBODY vAlign=top>
<TR>
<TD style="PADDING-RIGHT: 1px; PADDING-LEFT: 1px; PADDING-BOTTOM: 1px; PADDING-TOP: 1px" vAlign=center>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">FOR这条命令基本上都被用来处理文本,但还有其他一些好用的功能! </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">看看他的基本格式(这里我引用的是批处理中的格式,直接在命令行只需要一个%号) <BR>FOR 参数 %%变量名 IN (相关文件或命令) DO 执行的命令 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">参数:FOR有4个参数 /d&nbsp;&nbsp; /l&nbsp;&nbsp; /r&nbsp;&nbsp; /f&nbsp;&nbsp; 他们的作用我在下面用例子解释 <BR>%%变量名 :这个变量名可以是小写a-z或者大写A-Z,他们区分大小写,FOR会把每个读取到的值给他; <BR>IN:命令的格式,照写就是了; <BR>(相关文件或命令) :FOR要把什么东西读取然后赋值给变量,看下面的例子 <BR>do:命令的格式,照写就是了! <BR>执行的命令:对每个变量的值要执行什么操作就写在这. </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">可以在CMD输入for /?看系统提供的帮助!对照一下 <BR>FOR %%variable IN (set) DO command [command-parameters] </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">%%variable 指定一个单一字母可替换的参数。 <BR>(set)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定一个或一组文件。可以使用通配符。 <BR>command&nbsp;&nbsp;&nbsp; 指定对每个文件执行的命令。 <BR>command-parameters <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为特定命令指定参数或命令行开关。 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><BR>现在开始讲每个参数的意思 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="COLOR: #ff6600">/d</SPAN> <BR>仅为目录 <BR>如果 Set (也就是我上面写的 "相关文件或命令") 包含通配符（* 和 ?），将对与 Set 相匹配的每个目 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">录（而不是指定目录中的文件组）执行指定的 Command。 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">系统帮助的格式:FOR /D %%variable IN (set) DO command <BR>他主要用于目录搜索,不会搜索文件,看这样的例子 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">@echo off <BR>for /d %%i in (*) do @echo %%i <BR>pause </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">把他保存放在C盘根目录执行,就会把C盘目录下的全部目录名字打印出来,而文件名字一个也不显示! <BR>在来一个,比如我们要把当前路径下文件夹的名字只有1-3个字母的打出来 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">@echo off <BR>for /d %%i in (???) do @echo %%i <BR>pause </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">这样的话如果你当前目录下有目录名字只有1-3个字母的,就会显示出来,没有就不显示了 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><BR>思考题目: </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">@echo off <BR>for /d %%i in (window?) do @echo %%i <BR>pause </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">保存到C盘下执行,会显示什么呢?自己看吧! <BR>/D参数只能显示当前目录下的目录名字,这个大家要注意! </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="COLOR: #ff6600">/R</SPAN> <BR>递归 <BR>进入根目录树 [Drive:]Path，在树的每个目录中执行 for 语句。如果在 /R 后没有指定目录，则认为是 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">当前目录。如果 Set 只是一个句点 (.)，则只枚举目录树。 <BR>系统帮助的格式:FOR /R [[drive:]path] %%variable IN (set) DO command </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">上面我们知道,/D只能显示当前路径下的目录名字,那么现在这个/R也是和目录有关,他能干嘛呢?放心他比 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">/D强大多了! <BR>他可以把当前或者你指定路径下的文件名字全部读取,注意是文件名字,有什么用看例子! </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">@echo off <BR>for /r c:\ %%i in (*.exe) do @echo %%i <BR>pause </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">咋们把这个BAT保存到D盘随便哪里然后执行,我会就会看到,他把C盘根目录,和每个目录的子目录下面全部 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">的EXE文件都列出来了,这里的c:\就是目录了。 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">再来一个 <BR>@echo off <BR>for /r %%i in (*.exe) do @echo %%i <BR>pause </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">参数不一样了，这个命令前面没加那个C:\也就是搜索路径,这样他就会以当前目录为搜索路径,比如你这 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">个BAT你把他防灾d:\test目录下执行,那么他就会把D:\test目录和他下面的子目录的全部EXE文件列出 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">来!!! </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><BR><SPAN style="COLOR: #ff6600">/L</SPAN> <BR>迭代数值范围 <BR>使用迭代变量设置起始值 (Start#)，然后逐步执行一组范围的值，直到该值超过所设置的终止值 (End#) </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">。/L 将通过对 Start# 与 End# 进行比较来执行迭代变量。如果 Start# 小于 End#，就会执行该命令。 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">如果迭代变量超过 End#，则命令解释程序退出此循环。还可以使用负的 Step# 以递减数值的方式逐步执 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">行此范围内的值。例如，(1,1,5) 生成序列 1 2 3 4 5，而 (5,-1,1) 则生成序列 (5 4 3 2 1)。语法是： </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">系统帮助的格式:for /L %% Variable in (Start#,Step#,End#) do Command </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">例如： </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">@echo off <BR>for /l %%i in (1,1,5) do @echo %%i <BR>pause </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">保存执行看效果,他会打印从1 2 3 4 5 这样5个数字 <BR>(1,1,5)这个参数也就是表示从1开始每次加1直到5终止! </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">再看这个例子 <BR>@echo off <BR>for /l %%i in (1,1,5) do start cmd <BR>pause </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">执行后是不是吓了一跳,怎么多了5个CMD窗口,呵呵!如果把那个 (1,1,5)改成 (1,1,65535)会有什么结果, </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">我先告诉大家,会打开65535个CMD窗口....这么多你不死机算你强! </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">当然我们也可以把那个start cmd改成md %%i 这样就会建立指定个目录了!!!名字为1-65535 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">看完这个被我赋予破坏性质的参数后,我们来看最后一个参数 </SPAN></P>
<P><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体"><SPAN style="COLOR: #ff6600">/f</SPAN> </SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red">含有/F的for详细说明</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt"><SPAN style="COLOR: black">含有/F的for有很大的用处，在批处理中使用的最多，用法如下：</SPAN> <BR>格式： <BR><SPAN style="COLOR: red"><STRONG>FOR /F ["options"] %%i IN (file) DO command</STRONG></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>FOR /F ["options"] %%i IN ("string") DO command</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>FOR /F ["options"] %%i IN ('command') DO command</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">这个可能是最常用的，也是最强的命令，主要用来处理文件和一些命令的输出结果。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">file代表一个或多个文件</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">string 代表字符串</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">command代表命令</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">["options"] 可选</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">对于FOR /F %%i IN (file) DO command</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">file为文件名，按照官方的说法是，for会依次将file中的文件打开，并且在进行到下一个文件之前将每个文件读取到内存，按照每一行分成一个一个的元素，忽略空白的行，看个例子。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">假如文件a.txt中有如下内容：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>第1行第1列 第1行第2列 第1行第3列 <BR>第2行第1列 第2行第2列 第2行第3列 <BR>第3行第1列 第3行第2列 第3行第3列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">你想显示a.txt中的内容，会用什么命令呢？当然是type，type a.txt</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">for也可以完成同样的命令：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">for /f %%i in (a.txt) do echo %%i</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">还是先从括号执行，因为含有参数/f,所以for会先打开a.txt，然后读出a.txt里面的所有内容，把它作为一个集合，并且以每一行作为一个元素，所以会产生这样的集合，</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>{"第1行第1列 第1行第2列 第1行第3列"， //第一个元素</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>"第2行第1列 第2行第2列 第2行第3列"， //第二个元素</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>"第3行第1列 第3行第2列 第3行第3列"}&nbsp;&nbsp; //第三个元素</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">集合中只有3个元素，同样用%%i依次代替每个元素，然后执行do后面的命令。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">具体过程：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>用%%i代替"第1行第1列 第1行第2列 第1行第3列"，执行do后面的echo %%i，显示"第1行第1列 第1行第2列 第1行第3列"，</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>用%%i代替"第2行第1列 第2行第2列 第2行第3列"，执行echo %%i，显示"第2行第1列 第2行第2列 第2行第3列"，</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>依次，直到每个元素都代替完为止。</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">为了加强理解/f的作用，请执行一下两个命令，对比即可明白：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>for /f %%i in (a.txt) do echo %%i //这个会显示a.txt里面的内容，因为/f的作用，会读出a.txt中 <BR>的内容。</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>for %%i in (a.txt) do echo %%i //而这个只会显示a.txt这个名字，并不会读取其中的内容。</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">通过上面的学习，我们发现for /f会默认以每一行来作为一个元素，但是如果我们还想把每一行再分解更小的内容，该怎么办呢？不用担心，for命令还为我们提供了更详细的参数，使我们将每一行分为更小的元素成为可能。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">它们就是：<SPAN style="COLOR: red"><STRONG>delims和tokens</STRONG></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">delims 用来告诉for每一行应该拿什么作为分隔符，默认的分隔符是空格和tab键</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">比如，还是上面的文件，我们执行下面的命令：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>for /f "delims= " %%i in (a.txt) do echo %%i</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">显示的结果是：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>第1行第1列 <BR>第2行第1列 <BR>第3行第1列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">为什么是这样的呢。因为这里有了delims这个参数，=后面有一个空格，意思是再将每个元素以空格分割，默认是只取分割之后的第一个元素。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">执行过程是：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>将第一个元素"第1行第1列 第1行第2列 第1行第3列"分成三个元素："第1行第1列" "第1行第2列" "第1行第3列"，它默认只取第一个，即"第1行第1列"，然后执行do后面的命令，依次类推。</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">但是这样还是有局限的，如果我们想要每一行的第二列元素，那又如何呢？</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">这时候，<SPAN style="COLOR: blue"><STRONG>tokens</STRONG></SPAN>跳出来说，我能做到。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">它的作用就是当你通过delims将每一行分为更小的元素时，由它来控制要取哪一个或哪几个。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">还是上面的例子，执行如下命令：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>for /f "tokens=2 delims= " %%i in (a.txt) do echo %%i</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">执行结果：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>第1行第2列 <BR>第2行第2列 <BR>第3行第2列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">如果要显示第三列，那就换成tokens=3。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">同时tokens支持通配符*，以及限定范围。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">如果要显示第二列和第三列，则换成tokens=2,3或tokens=2-3,如果还有更多的则为：tokens=2-10之类的。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">此时的命令为：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>for /f "tokens=2,3 delims= " %%i in (a.txt) do echo %%i %%j</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: #993366"><STRONG>怎么多出一个%%j？</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">这是因为你的tokens后面要取每一行的两列，用%%i来替换第二列，用%%j来替换第三列。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">并且必须是按照英文字母顺序排列的，%%j不能换成%%k，因为i后面是j</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">执行结果为：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>第1行第2列 第1行第3列 <BR>第2行第2列 第2行第3列 <BR>第3行第2列 第3行第3列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">对以通配符*，就是把这一行全部或者这一行的剩余部分当作一个元素了。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">比如：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>for /f "tokens=* delims= " %%i in (a.txt) do echo %%i</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">执行结果为：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>第1行第1列 第1行第2列 第1行第3列 <BR>第2行第1列 第2行第2列 第2行第3列 <BR>第3行第1列 第3行第2列 第3行第3列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">其实就跟for /f %%i in (a.txt) do echo %%i的执行结果是一样的。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">再如：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>for /f "tokens=2,* delims= " %%i in (a.txt) do echo %%i %%j</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">执行结果为：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>第1行第2列 第1行第3列 <BR>第2行第2列 第2行第3列 <BR>第3行第2列 第3行第3列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">用%%i代替第二列，用%%j代替剩余的所有</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">最后还有skip合eol，这俩个简单，skip就是要忽略文件的前多少行，而eol用来指定当一行以什么符号开始时，就忽略它。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">比如：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: red"><STRONG>for /f "skip=2 tokens=*" %%i in (a.txt) do echo %%i</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">结果为:</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>第3行第1列 第3行第2列 第3行第3列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">用skip来告诉for跳过前两行。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">如果不加tokens=*的话，执行结果为：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>第3行第1列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">不知道怎么回事。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">再如，当a.txt内容变成：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>.第1行第1列 第1行第2列 第1行第3列 <BR>.第2行第1列 第2行第2列 第2行第3列 <BR>第3行第1列 第3行第2列 第3行第3列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">执行<SPAN style="COLOR: red"><STRONG>for /f "eol=. tokens=*" %%i in (a.txt) do echo %%i</STRONG></SPAN>结果是：</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt; COLOR: blue"><STRONG>第3行第1列 第3行第2列 第3行第3列</STRONG></SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 10pt">用eol来告诉for忽略以"."开头的行。</SPAN><SPAN style="FONT-SIZE: 12pt"> </SPAN></SPAN></P>
<P><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">同样也必须加tokens=*，否则只会显示"第3行第1列"</SPAN></P></TD></TR></TBODY></TABLE></DIV>]]></description>
</item><item>
<title><![CDATA[工作中的问题]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45757</link>
<author>oceanblue</author>
<pubDate>2009/6/2 8:19:39</pubDate>
<description><![CDATA[
<DIV class=tit>恶心的2005</DIV>
<DIV class=date>
<P></P>
<P>原文链接：<A href="http://hi.baidu.com/freedomknightduzhi/blog/item/60a5012e512bba554fc226e9.html">http://hi.baidu.com/freedomknightduzhi/blog/item/60a5012e512bba554fc226e9.html</A></P></DIV>
<TABLE style="TABLE-LAYOUT: fixed">
<TBODY>
<TR>
<TD>
<DIV class=cnt>
<P>用VC2003一直很爽,到新公司要用2005,早听说其检查严格,没想到,完全是没事找事型的编译器.</P>
<P>且不说满屏幕的:</P>
<P>"警告 4 warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 "</P>
<P>运行个MFC的东西就报"由于应用程序的配置不正确，应用程序未能启动"</P>
<P>一查才知道,这是05的特权,缺少动态库也不说,直接报个配置不正确,Fuck.不如直接弹出个警告框"程序无法运行"适用性更大呢.</P>
<P><FONT color=#ff0000>这里是重置2005配置的</FONT><FONT color=#ff0000>方法:</FONT></P>
<P><FONT color=#ff0000>命令行输入:</FONT><FONT size=2><FONT color=#c60a00>devenv</FONT> /resetuserdata</FONT></P><FONT size=2>
<P>[[</P>
<P>开始执行程序时出现错误提示：<BR><FONT color=#ff0000>没有</FONT><FONT color=#ff0000>找到MSVCP80D.dll，因此这个应用程序未能启动。重新安装应用程序可能会修复此问题。</FONT></P>
<P><FONT color=#000000>解决方法：</FONT></P>
<P>项目-&gt;属性-&gt;配置属性-&gt;清单工具-&gt;常规-&gt;使用FAT32解决办法<BR>改为“是”即可</P>
<P>此时，应该将上次产生的debug文件夹删除才能正确运行。</P>
<P>]]</P>
<P>原因大致是由于2005编译时，FAT32格式硬盘会给程序加以时间戳，换机器运行时由于时间戳不符的原因导致无法运行，如果编译机器格式为NTFS格式则也不会出现该问题。</P>
<P>这两天有点焦头烂额, 我们这边运行的好好的程序, 到了测试的机器上就不能启动(是根本运行不了, 而不是运行出错), 弄得我异常郁闷。 经过了一番摸索, 发现和 winxp、win2003中为解决dll hell而引入的manifest机制有关系。而以前我们用vs2003开发, 它并没有强制程序使用manifest, 但到了vs2005中, 这已经改成必需的了, 而我们并没有按照需要进行相关的配置, 所以程序启动不了了。 根据目前的经验, vs2005编译的程序不能启动大致有两个原因, 下面简单介绍解决办法。<BR>1、在开发组的机器上(安装有vs2005)有时都不能启动<BR>这一般是项目的文件被放在了fat/fat32分区上导致的, 解决方法是把它们都移动到ntfs分区上, 或者把“项目属性|Manifest Tool|General|Use FAT32 Work-around”设为yes。<BR>2、开发组运行正常, 换到其它机器上就不行了<BR>这一般就是系统dll(包括crt,mfc,atl等)没有正确配置导致的。 如果程序是release版, 那么很简单, 只要把“\SDK\v2。0\BootStrapper\Packages\vcredist_x86”下的"vcredist_x86。exe"拷贝到目标机器上运行即可, 这是以x86平台为例的, 如果你用的是别的cpu平台(amd64或ia64)把x86替换成相应的内容就可以了。</P>
<P>注：[[ ]] 内信息转自<A href="http://hi.baidu.com/crafter_xmu/blog/item/104040b44b4876768bd4b281.html">http://hi.baidu.com/crafter_xmu/blog/item/104040b44b4876768bd4b281.html</A></P></FONT>
<P><FONT color=#ff0000>这里是"<FONT color=#000000><FONT color=#ff0000>general error c101008a: Failed to save the updated manifest to the file</FONT> </FONT>"网上普遍的解决方法:</FONT></P>
<P>在用vs2005时,默认编码为unicode,如果在项目中途改变,则编译时会碰到错误general error c101008a: Failed to save the updated manifest to the file ".\Debug\Menu.exe.embed.manifest". Bpcn mt.exe .这时清理解决方案,再重新生成项目便可解决.</P>
<P><FONT color=#ff0000>这里是"warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 "网上普遍的解决方法:</FONT></P>
<P>一般来说，这个警告没有什么影响。要想去掉这个警告的方法有：</P>
<P>（1）转换Code文件为Unicode格式；</P>
<P>（2）在Project -&gt; Properties -&gt; Configuration Properties -&gt; C/C++ -&gt; Advance 的 Disable Specific Warnings 中添加相应的警告编号：4819；</P>
<P>（3）或找出不符合Unicode格式的文件，然后在该文件的开始处加入下面的语句：</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # pragma warning (disable:4819)</P>
<P><FONT color=#ff0000>2005断点无法命中的解决方案</FONT></P>
<P>1:重新编译该工程.</P>
<P>2:文件的编码格式不匹配造成的;修改步骤: 菜单-&gt;文件-&gt;XXX文件另存为-&gt;编码保存(保存按钮旁边的下拉菜单)-&gt;Unicode (UTF-8 带签名)-&gt;确定</P>
<P><FONT color=#ff0000>这里是"由于应用程序的配置不正确，应用程序未能启动"网上普遍的解决方法:</FONT></P>
<P>方法一：在类似C:\Program Files\Microsoft Visual Studio 8\VC\redi st\Debug_NonRedist\x86\Microsoft.VC80.DebugCRT 下找到了下列文件： msvcm80d.dll msvcp80d.dll msvcr80d.dll Microsoft.VC80.DebugCRT.manifest 把这几个文件拷贝到目标机器上，与运行程序同一文件夹或放到system32下，就可以正确运行了。 其他release版、MFC程序什么的都是拷redist下相应文件夹下的文件就可以了,文件夹后都有标识!</P>
<P>结果: 把这几个Dll Copy过去,无效....</P>
<P>方法二：工程－》属性－》配置属性－》c/c++ -〉代码生成里，修改运行时库选项，将/MD或/MDd 改为 /MT或/MTd，这样就实现了对VC运行时库的静态链接，在运行时就不再需要VC的dll了。</P>
<P>结果:由于我的程序使用了DLL输出,使用多线程调试是不行的,必须多线程调试DLL,这招也无效....</P>
<P>方法三: 工程－》属性－》配置属性－》常规－》MFC的使用，选择“在静态库中使用mfc” 这样生成的exe文件应该就可以在其他机器上跑了。</P>
<P>结果: 告诉我缺少Boost库,编译一次Boost够我吃顿饭回来了- -</P>
<P>方法四: 你的vc8安装盘上找到再分发包vcredist_xxx.exe和你的程序捆绑安装</P></DIV></TD></TR></TBODY></TABLE><BR>]]></description>
</item><item>
<title><![CDATA[Directshow]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45609</link>
<author>oceanblue</author>
<pubDate>2009/5/22 23:37:18</pubDate>
<description><![CDATA[
<P align=left>本文描述了Directshow SDK ,Windows SDK,DirectX SDK ,VS200?之间的关系<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VS2002中包含有Windows SDK 2002版(支持Windows XP及其以前的Windows 并包含有DirctX 8.1 SDK(包括DirectShow SDK)),这之后DirectX9 SDK不被包含在Windows SDK中.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VS2003中包含有Windows SDK 2003版(支持Windows Server 2003及其以前的Windows)和DirectX 8.1 SDK(其中包括Directshow8 SDK)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DirectX 9.0C SDK 的第一个版本是DirectX&nbsp;SDK Summer 2004也是整合有Directshow SDK 的最后一个版本,这之后面向DirectX 9.0C用C++开发应用程序没有发生太大变化,以后的版本主要是针对MDX做的改动,如果在VS2003下用C++开发DirectShow应用程序使用这个版本最合适.另外Windows XP SP2 中包含的DirectX 的版本就是9.0c ,这也是广泛使用的DirectX版本.Windows SDK 2004版,支持Windows XP SP2及其以前的Windows 但不包含DirectX SDK.<BR>&nbsp;&nbsp;&nbsp;&nbsp;之后 Directshow&nbsp; SDK 不被整合在DirectX SDK中而是以Extras 的形式发布.Directshow SDK的最后一个版本是在2005.2版的DirectX&nbsp;SDK <SPAN style="COLOR: red">Extras</SPAN>中,这之后Directshow SDK被整合在Windows SDK中 Windows SDK 2005版(支持Windows Server 2003 SP1 及其之前的Windows)中包含有Directshow SDK,Windows SDK 2006年3月版(支持Windows Server 2003 R2及其之前的Windows)也包含.<BR>&nbsp;&nbsp;&nbsp; VS2005 中包含有Windows SDK 2005 版,但是没有Directshow SDK,所以在VS2005中开发Dirctshow 应用程序要手工安装DirectX&nbsp;SDK <SPAN style="COLOR: red">Extras </SPAN>2005,2 版,和2005年2月之后的DirectX SDK(因为DirectShow 会调用DirectDraw),我使用的是2005.4版,如果面向MDX开发则要使用最新版的DirectX SDK.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows SDK for Vista&nbsp;&nbsp;已经正式发布,Directshow&nbsp;的换代产品是Media Foundation,它将取代Directshow 就象当年Directshow 取代 Video&nbsp;for Windows 一样.<BR>晕了<BR><BR>DirectX SDK下载页<BR><A href="http://www.microsoft.com/downloads/Browse.aspx?displaylang=en&amp;categoryid=2"><SPAN style="TEXT-DECORATION: underline"><SPAN style="COLOR: #0000ff">http://www.microsoft.com/downloads/Browse.aspx?displaylang=en&amp;categoryid=2</SPAN></SPAN></A><BR></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="FONT-SIZE: small; FONT-FAMILY: Times New Roman"><SPAN style="FONT-SIZE: x-small; FONT-FAMILY: Arial"><FONT size=1>DirectX SDK </FONT><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">9.0c</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"> October 2006</SPAN><FONT size=1>&nbsp;版 下载地址</FONT></SPAN><BR><A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=D625324C-59B4-4951-849E-640B508DC442&amp;displaylang=en"><SPAN style="COLOR: #336699"><FONT size=2>http://www.microsoft.com/downloads/details.aspx?FamilyId=D625324C-59B4-4951-849E-640B508DC442&amp;displaylang=en</FONT></SPAN></A><FONT size=2> </FONT></SPAN></SPAN><SPAN lang=EN-US><SPAN style="FONT-SIZE: small; FONT-FAMILY: Times New Roman"><BR></SPAN></SPAN>DirectX SDK 2005.4版 下载地址<BR><A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=afc15f29-d7c9-4cf7-a8d5-8ab81f14ae1b&amp;DisplayLang=en"><SPAN style="TEXT-DECORATION: underline"><SPAN style="COLOR: #0000ff">http://www.microsoft.com/downloads/details.aspx?FamilyID=afc15f29-d7c9-4cf7-a8d5-8ab81f14ae1b&amp;DisplayLang=en</SPAN></SPAN></A><BR>DirectX SDK 2005.2版 下载地址<BR><A href="http://download.microsoft.com/download/7/b/9/7b92308a-ec8d-4016-8d45-2f91dd130bf2/dxsdk_feb2005.exe"><SPAN style="COLOR: #336699">http://download.microsoft.com/download/7/b/9/7b92308a-ec8d-4016-8d45-2f91dd130bf2/dxsdk_feb2005.exe</SPAN></A><BR>DirectX SDK Summer 2004&nbsp;版 下载地址<BR><A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=fd044a42-9912-42a3-9a9e-d857199f888e&amp;DisplayLang=en"><SPAN style="TEXT-DECORATION: underline"><SPAN style="COLOR: #0000ff">http://www.microsoft.com/downloads/details.aspx?FamilyID=fd044a42-9912-42a3-9a9e-d857199f888e&amp;DisplayLang=en</SPAN></SPAN></A><BR><BR>DirectX&nbsp;SDK <SPAN style="COLOR: red">Extras</SPAN><SPAN style="COLOR: red"> </SPAN>2005,2 版 下载地址<BR><A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=8af0afa9-1383-44b4-bc8b-7d6315212323&amp;DisplayLang=en"><SPAN style="TEXT-DECORATION: underline"><SPAN style="COLOR: #0000ff">http://www.microsoft.com/downloads/details.aspx?FamilyID=8af0afa9-1383-44b4-bc8b-7d6315212323&amp;DisplayLang=en</SPAN></SPAN></A><BR><A href="http://download.microsoft.com/download/d/9/1/d91c44b9-fbac-4e8e-bee1-4a75777923ec/dxsdk_feb2005_extras.exe"><SPAN style="COLOR: #336699">http://download.microsoft.com/download/d/9/1/d91c44b9-fbac-4e8e-bee1-4a75777923ec/dxsdk_feb2005_extras.exe</SPAN></A><BR><BR>Windows&nbsp;SDK 2006.3 版 for Windows&nbsp;Server 2003&nbsp;R2 下载地址 <BR><A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=E15438AC-60BE-41BD-AA14-7F1E0F19CA0D&amp;displaylang=en"><SPAN style="TEXT-DECORATION: underline"><SPAN style="COLOR: #0000ff">http://www.microsoft.com/downloads/details.aspx?FamilyId=E15438AC-60BE-41BD-AA14-7F1E0F19CA0D&amp;displaylang=en</SPAN></SPAN></A><BR>这个版本的好处是不含有.net SDK 一张CD-R可以刻下<BR><BR>Windows SDK for Vista 下载地址<BR><A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c2b1e300-f358-4523-b479-f53d234cdccf&amp;DisplayLang=en"><SPAN style="TEXT-DECORATION: underline"><SPAN style="COLOR: #0000ff">http://www.microsoft.com/downloads/details.aspx?FamilyID=c2b1e300-f358-4523-b479-f53d234cdccf&amp;DisplayLang=en</SPAN></SPAN></A><BR><A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=7614fe22-8a64-4dfb-aa0c-db53035f40a0&amp;DisplayLang=en"><SPAN style="TEXT-DECORATION: underline"><SPAN style="COLOR: #0000ff">http://www.microsoft.com/downloads/details.aspx?FamilyID=7614fe22-8a64-4dfb-aa0c-db53035f40a0&amp;DisplayLang=en</SPAN></SPAN></A><BR>包含有.net 3 SDK</P>
<P align=left>还真麻烦呢</P>
<P align=left>还不仅仅是上述这些问题; DirectShow在PlatformSDK2006多媒体目录下，baseClass没有dsw提供，仅有makefile提供；　可以把它转成dsw的工程编译；release版本加上 "NODEBUG"的参数；</P>
<P align=left>另外，PlatformSDK2006不支持VC6,要使用PlatformSDK2006,得用 VS2003或者VS2005</P>]]></description>
</item><item>
<title><![CDATA[pthead 学习]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45546</link>
<author>oceanblue</author>
<pubDate>2009/5/19 21:14:06</pubDate>
<description><![CDATA[
<P class=MsoNormal><SPAN lang=EN-US>#include &lt;stdio.h&gt;<?XML:NAMESPACE PREFIX = O /><O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>#include &lt;pthread.h&gt;<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>#include &lt;semaphore.h&gt;<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P>void *thread_a(void *in)<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>{<O:P></O:P></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21.75pt"><SPAN lang=EN-US>printf("I am thread_a\n");</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21.75pt"><SPAN lang=EN-US>pthread_exit((void *)0);</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>}<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>void *thread_b(void *in)<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>{<O:P></O:P></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21.75pt"><SPAN lang=EN-US>printf("I am thread_b\n");</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21.75pt"><SPAN lang=EN-US>pthread_exit((void *)0);</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>}<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>void *thread_c(void *in)<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>{<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>printf("I am thread_c\n");<O:P></O:P></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21.75pt"><SPAN lang=EN-US>pthread_exit((void *)0);</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>}<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>int main()<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>{<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_t a,b,c;<SPAN>&nbsp; </SPAN>/* thread id a, b, c*/<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>int val;<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>/* used for function return result */<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>/* create thread a, b, c */<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_create(&amp;a, NULL, thread_a, (void *)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_create(&amp;b, NULL, thread_b, (void *)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_create(&amp;c, NULL, thread_c, (void *)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>/* main thread waits for termination of a,b,c */<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_join(a, (void **)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_join(b, (void **)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_join(c, (void **)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>printf("Main thread is over\n");<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>return 0;<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>}</SPAN></P>在Linux下进行编译: gcc -o My_Thread My_Thread.c ./MyThread <BR>得到的输出:<BR>&nbsp;I am thread_a <BR>I am thread_b <BR>I am thread_c <BR>Main thread is over <BR><BR>现在我们希望线程C的最先打印，然后线程B打印，最后线程A打印。即三个线程之间的打印有一定的先后关系。看下面程序：<BR><BR>
<P class=MsoNormal><SPAN lang=EN-US>#include &lt;stdio.h&gt;<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>#include &lt;pthread.h&gt;<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>#include &lt;semaphore.h&gt;<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>sem_t sem1;<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>sem_t sem2;<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>void *thread_a(void *in)<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>{<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>sem_wait(&amp;sem1);<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>/* wait for sem1 */<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>printf("I am thread_a\n");<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_exit((void *)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>}<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>void *thread_b(void *in)<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>{<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>sem_wait(&amp;sem2);<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>/* wait for sem2 */<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>printf("I am thread_b\n");<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>sem_post(&amp;sem1);<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>/* increase sem1 by 1, make thread_a run*/<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_exit((void *)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>}<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>void *thread_c(void *in)<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>{<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>printf("I am thread_c\n");<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>sem_post(&amp;sem2);<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>/* increase sem2 by 1, make thread_b run*/<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_exit((void *)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>}<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>int main()<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>{<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_t a,b,c;<SPAN>&nbsp; </SPAN>/* thread id a, b, c*/<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>int val;<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>/* used for function return result */<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>/* init sem1 sem2 to 0 , any thread waits for it will be blocked*/<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>sem_init(&amp;sem1, 0, 0);<O:P></O:P></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN lang=EN-US>sem_init(&amp;sem2, 0, 0);</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN lang=EN-US>/* create thread a, b, c */<O:P></O:P></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN lang=EN-US>pthread_create(&amp;a, NULL, thread_a, (void *)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN lang=EN-US>pthread_create(&amp;b, NULL, thread_b, (void *)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN lang=EN-US>pthread_create(&amp;c, NULL, thread_c, (void *)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>/* main thread waits for termination of a,b,c */<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_join(a, (void **)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_join(b, (void **)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>pthread_join(c, (void **)0);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>/* destroy sem1 sem2 */<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>sem_destroy(&amp;sem1);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>sem_destroy(&amp;sem2);<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><O:P>&nbsp;</O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>printf("Main thread is over\n");<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>return 0;<O:P></O:P></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>}</SPAN></P>
<P>gcc -o My_thread1 My_thread1.c -lpthread<BR>./My_thread1<BR>I am thread_c<BR>I am thread_b<BR>I am thread_a<BR>Main thread is over<BR><BR>可以见到，线程的执行顺序已经改变。</P>
<P>pthread便是大名鼎鼎的posix多线程库了.然而pthread的多线程基于C回调函数,在C++中应用是个不大方便的问题.由于c++的类成员函数指针是无法直接在pthread中回调的,因此,如果我们想要在C++中使用pthread多线程,必须要借助其他的技巧才可以做到.</P>
<P>首先,我们要兼容pthread的静态函数式回调,同时又要动态调用成员函数,因此,要有一个类负责转发调用,再次,我们考虑如何调用类,为了方便,我们用C++仿函数在线程内调用成员函数.</P>
<P>所以,首先我们想到实现一个ThreadCall类:</P>
<DIV class=codeText>
<DIV class=codeHead>C++代码</DIV>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN class=keyword>class</SPAN><SPAN>&nbsp;ThreadCall{ &nbsp;&nbsp;</SPAN></SPAN> 
<LI class=""><SPAN class=keyword>public</SPAN><SPAN>: &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=keyword>static</SPAN><SPAN>&nbsp;</SPAN><SPAN class=keyword>void</SPAN><SPAN>&nbsp;*Fun(</SPAN><SPAN class=keyword>void</SPAN><SPAN>&nbsp;*data){ &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=comment>//这儿如何定义呢? </SPAN><SPAN>&nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>};&nbsp;&nbsp;</SPAN> </LI></OL></DIV>
<P><BR>我们这儿只能传入一个void*的数据,但是我们需要知道的数据呢?应该包括要调用的类,以及要传入的参数.同时,对这个类,我们还要求拥有仿函数接口,因此,我们做如下定义:</P>
<DIV class=codeText>
<DIV class=codeHead>C++代码</DIV>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN class=comment>//首先定义一个ThreadClass接口,所有回调类都直接或者间接继承自该类 </SPAN><SPAN>&nbsp;&nbsp;</SPAN></SPAN> 
<LI class=""><SPAN class=comment>//它规定了回调接口 </SPAN><SPAN>&nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN class=keyword>class</SPAN><SPAN>&nbsp;ThreadClass{ &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN class=keyword>public</SPAN><SPAN>: &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=keyword>virtual</SPAN><SPAN>&nbsp;</SPAN><SPAN class=keyword>void</SPAN><SPAN>&nbsp;*operator()(</SPAN><SPAN class=keyword>void</SPAN><SPAN>&nbsp;*)=0; &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>};&nbsp;&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=codeText>
<DIV class=codeHead>C++代码</DIV>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN class=comment>//再定义一个线程信息结构,其中包含了要调用的class和出入的数据 </SPAN><SPAN>&nbsp;&nbsp;</SPAN></SPAN> 
<LI class=""><SPAN class=keyword>struct</SPAN><SPAN>&nbsp;_threadInfo{ &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;ThreadClass&nbsp;*threadClass; &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=keyword>void</SPAN><SPAN>&nbsp;*data; &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>}; &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN class=keyword>typedef</SPAN><SPAN>&nbsp;_threadInfo&nbsp;ThreadInfo; &nbsp;&nbsp;</SPAN> </LI></OL></DIV>
<P><BR>OK,再次回到我们的ThreadCall类,现在我们就可方便的写出它的实现了:</P>
<DIV class=codeText>
<DIV class=codeHead>C++代码</DIV>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN class=keyword>class</SPAN><SPAN>&nbsp;ThreadCall{ &nbsp;&nbsp;</SPAN></SPAN> 
<LI class=""><SPAN class=keyword>public</SPAN><SPAN>: &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=keyword>static</SPAN><SPAN>&nbsp;</SPAN><SPAN class=keyword>void</SPAN><SPAN>&nbsp;*Fun(</SPAN><SPAN class=keyword>void</SPAN><SPAN>&nbsp;*data){ &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ThreadInfo&nbsp;*info=(ThreadInfo&nbsp;*)data; &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=keyword>return</SPAN><SPAN>&nbsp;info-&gt;threadClass-&gt;operator&nbsp;()(info-&gt;data); &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>};&nbsp;&nbsp;</SPAN> </LI></OL></DIV>
<P><BR>这样,我们就实现了C++式的使用pthread,虽然麻烦了点,但是实现了类成员函数线程调用,还是值得的.现在我们来测试下:</P>
<P>&nbsp;</P>
<DIV class=codeText>
<DIV class=codeHead>C++代码</DIV>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN class=keyword>class</SPAN><SPAN>&nbsp;MyThreadClass&nbsp;:&nbsp;ThreadClass{ &nbsp;&nbsp;</SPAN></SPAN> 
<LI class=""><SPAN class=keyword>public</SPAN><SPAN>: &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=keyword>virtual</SPAN><SPAN>&nbsp;</SPAN><SPAN class=keyword>void</SPAN><SPAN>&nbsp;*operator()(</SPAN><SPAN class=keyword>void</SPAN><SPAN>&nbsp;*data){ &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=datatypes>char</SPAN><SPAN>&nbsp;*str=(</SPAN><SPAN class=datatypes>char</SPAN><SPAN>&nbsp;*)data; &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;str&lt;&lt;endl; &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=keyword>return</SPAN><SPAN>&nbsp;NULL; &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>}; &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN class=datatypes>int</SPAN><SPAN>&nbsp;main(</SPAN><SPAN class=datatypes>int</SPAN><SPAN>&nbsp;argc,</SPAN><SPAN class=datatypes>char</SPAN><SPAN>&nbsp;*argv[]){ &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyThreadClass&nbsp;threadClass; &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;ThreadInfo&nbsp;info; &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;info.threadClass=(ThreadClass&nbsp;*)&amp;threadClass; &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;info.data=</SPAN><SPAN class=string>"hello"</SPAN><SPAN>; &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;pthread_t&nbsp;pid; &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;pthread_create(&amp;pid,NULL,&amp;ThreadCall::Fun,&amp;info); &nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;system(</SPAN><SPAN class=string>"pause"</SPAN><SPAN>); &nbsp;&nbsp;</SPAN> 
<LI class=""><SPAN>}&nbsp;&nbsp;</SPAN> </LI></OL></DIV>
<P>&nbsp;</P>
<P>执行程序,子线程成功打印出"hello"的信息.</P>]]></description>
</item><item>
<title><![CDATA[blt notsrccopy原理]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45335</link>
<author>oceanblue</author>
<pubDate>2009/5/11 11:04:04</pubDate>
<description><![CDATA[&nbsp; 用过NOTSRCCOPY的朋友都会知道可以出来一个类似底片的效果。可是它内部执行了怎样的象素运算你清楚吗？是与，或，或者怎样的组合呢？
<DIV>&nbsp;&nbsp; 这个效果术语叫Image Invert。有兴趣的朋友可到网上查找。这里简略的描述一下算法。假设有一个前景象素A(204,0,0)和背景B(255,255,255)如果对A进行Invert(去反)，计算如下：</DIV>
<DIV>&nbsp;&nbsp;&nbsp; A(204,0,0)-&gt;A(11001100,00000000,00000000)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 化为二进制</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&gt;A(00110011,11111111,11111111)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Invert取反</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt;A(51,255,255)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt;R(|A-(255-B)|)即R(|51-(255-255)|,|255-(255-255)|,|255-(255-255)|)</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt;R(51,255,255)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后结果</DIV>
<DIV>如果背景为蓝色B(0,0,255),则R=(204,0,255)</DIV>]]></description>
</item><item>
<title><![CDATA[agg study.]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45306</link>
<author>oceanblue</author>
<pubDate>2009/5/9 21:58:08</pubDate>
<description><![CDATA[
<DIV>
<DIV>/*</DIV>
<DIV>类型：原创</DIV>
<DIV>作者：陈亮</DIV>
<DIV>Email : <A href="mailto:clzzclzz@hotmail.com">clzzclzz@hotmail.com</A></DIV>
<DIV>*/</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;前言：</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 自已写的算法和主流太有差距了，所以找了个很棒的2D绘图引擎—–AGG，准备用它做项目。AGG的主要思想就是，建一个窗口，然后把客户区当成一块位图区域，然后向里面添像素，最后把它显示出来。。</DIV>
<DIV>&nbsp;</DIV>
<DIV>画线：</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.打开例子的中Purl Api工程，就有画线的例子，这里画的是一个三角形.主要代码如下。</DIV>
<DIV>/*agg::rendering_buffer是AGG的管理像素内存的低层类， 一般要与像素格式类配合使用，如agg::pixfmt_bgra32……..*/</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agg::rendering_buffer rbuf;</DIV>
<DIV>/*初如化 rbuf，&nbsp;buf就是客户区位图的指针，width,height是位图宽度与高度，因为上面创建位图时用的是32位的位图格式，所以要 -width*4,4表示(RGBA–4BYTE) 因为windowsGDI的座标系与AGG的正好是反的所以加了-号*/</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rbuf.attach((unsigned char*)buf, width, height, -width*4);</DIV>
<DIV>/*因为上面创建位图时用的是32位的位图格式，所以这里要用agg::pixfmt_bgra32类*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agg::pixfmt_bgra32 pixf(rbuf);</DIV>
<DIV>/*agg::renderer_base主要是AGG渲染的基础类，比agg::pixfmt_bgra32类多了管理边框的功能*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agg::renderer_base&lt;agg::pixfmt_bgra32&gt; renb(pixf);</DIV>
<DIV>/*agg::renderer_base.clear将所有像素清除为指定颜色*/</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; renb.clear(agg::rgba8(255, 255, 255, 255));</DIV>
<DIV>/*agg::renderer_scanline_aa_solid类可以将直线渲染为实心色的*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agg::renderer_scanline_aa_solid&lt;agg::renderer_base&lt;agg::pixfmt_bgra32&gt; &gt; ren(renb);</DIV>
<DIV>/*agg::rasterizer_scanline_aa是AGG的核心类，用于光删化图形*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agg::rasterizer_scanline_aa&lt;&gt; ras;</DIV>
<DIV>/*agg::scanline_p8用于渲染*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agg::scanline_p8 sl;</DIV>
<DIV>&nbsp;</DIV>
<DIV>/*下面三行代码画三角形*/</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ras.move_to_d(20.7, 34.15);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ras.line_to_d(398.23, 123.43);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ras.line_to_d(165.45, 401.87);<BR>&nbsp;/*设三角形的填充颜色，通过ren设置*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ren.color(agg::rgba8(80, 90, 60));</DIV>
<DIV>/*agg::render_scanlines 通过调用本函数渲染图形*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; agg::render_scanlines(ras, sl, ren);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //============================================================</DIV>
<DIV>&nbsp;</DIV></DIV>]]></description>
</item><item>
<title><![CDATA[Windows CE图形特性 (MSDN)]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45305</link>
<author>oceanblue</author>
<pubDate>2009/5/9 21:48:10</pubDate>
<description><![CDATA[
<DIV class=post>
<H2><A id=homepage1_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl00_TitleUrl href="http://www.cnblogs.com/menghuanshitou/archive/2009/03/28/1424123.html"></A>&nbsp;</H2><EM><FONT face="Times New Roman" size=3>
<P>在Microsoft&reg; Windows&reg; CE操作系统和其他的Microsoft Win32&reg; 操作系统中，控制文本和图形显示的子系统称为图形设备接口（Graphics Device Interface，简称GDI)。与桌面产品类似，Windows CE GDI在显示设备和打印设备上绘制直线、曲线、闭图形、文本和位图图像。 </P>
<P>在Windows CE 2.0中，对GDI功能进行了扩展，包括了许多其他Win32应用程序编程接口（API）中高级图形特性。优良的图形显示从此不再局限于桌面计算机；GDI让基于 Windows CE的设备可以创建吸引人的、有用的图形。 </P>
<P>本文着眼于讨论GDI的每一个特性。着重讨论对Windows CE 1.0所作的改进或者实质性的修改。文章还讨论了这每一个特性与标准的基于Win32的应用程序编程接口的差别。 </P>
<P>在这篇文章中，GDI仅仅指Window CE子系统，不是等价于其他基于Windows的平台。 </P>
<P><STRONG>设备上下文 </STRONG></P>
<P>设备上下文（Device Context，简称DC)是一种结构，GDI用它来保存图形对象的信息，这些信息决定了文本和图形在显示器和打印机上的外观。用来决定显示的笔、刷子、字体、颜色和位图的类型都保存在设备上下文中。 </P>
<P>Windows CE支持下表所描述的设备上下文。 </P>
<P>
<TABLE style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-table-layout-alt: fixed; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt" cellSpacing=0 cellPadding=0 width=403 border=1>
<TBODY>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid" vAlign=top align=middle width=134>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>设备上下文类型 </FONT></STRONG></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt" vAlign=top align=middle width=238>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>目的 </FONT></STRONG></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=134>
<P><FONT class=90v>显示器 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=238>
<P><FONT class=90v>支持视频显示器上的绘制操作 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=134>
<P><FONT class=90v>打印机 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=238>
<P><FONT class=90v>支持打印机上的绘制操作 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=134>
<P><FONT class=90v>内存 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=238>
<P><FONT class=90v>支持设备独立位图的绘制操作 </FONT></P></TD></TR></TBODY></TABLE></P>
<P>应用程序绝对不可以直接访问设备上下文；它通过调用可以访问DC的函数间接操纵设备上下文结构。 </P>
<P>可以通过调用BeginPaint 函数获得指向设备上下文的句柄。通过GetDC 函数获得设备上下文，通过CreateDC和CreateCompatibleDC函数创建设备上下文。 </P>
<P><STRONG>2.0版本中的新特性 </STRONG><BR>在2.0版本中改进了内存设备上下文，它现在可以与显示DC完全兼容了。打印DC是2.0中的新特性。 </P>
<P><STRONG>与其它基于Win32的平台的差异 </STRONG><BR>Windows CE不支持信息设备上下文。 </P>
<P><STRONG>图形绘制和填充 </STRONG></P>
<P>除了简单的直线绘制功能以外，GDI还可以使用下列功能绘制更多的图形： </P>
<P>
<TABLE style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-table-layout-alt: fixed; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt" cellSpacing=0 cellPadding=0 width=464 border=1>
<TBODY>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid" vAlign=top align=middle width=88>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>函数名称 </FONT></STRONG></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt" vAlign=top align=middle width=345>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>目的 </FONT></STRONG></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=88>
<P><FONT class=90v>Ellipse </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=left width=345>
<P><FONT class=90v>绘制和填充椭圆 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=88>
<P><FONT class=90v>Polygon </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=left width=345>
<P><FONT class=90v>绘制和填充用户定义的图形 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=88>
<P><FONT class=90v>Polyline </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=left width=345>
<P><FONT class=90v>由一系列连接的直线段构成，最终的折线可以构成任何形状 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=88>
<P><FONT class=90v>Rectangle </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=left width=345>
<P><FONT class=90v>绘制和填充矩形 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=88>
<P><FONT class=90v>RoundRect </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=left width=345>
<P><FONT class=90v>绘制和填充圆角矩形 </FONT></P></TD></TR></TBODY></TABLE></P>
<P><STRONG>2.0版本的新特性 </STRONG><BR>在2.0版本中，修改了polygon函数，在此基础上可以正确的填充凹多边形和自相交多边形。自相交多边形是指在绘制时，两条边交叉的多边形。 </P>
<P>与其他基于Win32的平台GDI不同的是，它既不支持路径或非矩形区域的创建，也不支持LineTo和MoveTo函数。此外，GDI不支持创建下列图形和直线的函数。 </P>
<UL>
<LI>弧线 
<LI>Bezier曲线 
<LI>可变基准线 
<LI>饼图 
<LI>PolyPolygon 
<LI>PolyPolyline </LI></UL>
<P><STRONG>笔和刷子 </STRONG></P>
<P>笔是用于绘制直线的图形对象GDI；刷子是用于填充闭图形内部的图形对象。 </P>
<P><STRONG>笔 </STRONG><BR>BLACK_PEN和WHITE_PEN都可以以各自的颜色绘制一个像素宽的实线。这些笔以及不绘制任何图形的NULL_PEN都是库里存放的GDI笔。可以使用GetStockObject函数选择库存的笔。 </P>
<P>CreatePen和CreatePenIndirect函数可以用来创建不同于库存笔的函数。这些函数可以让用户定义笔的线宽、颜色和样式。下面罗列了可能支持的笔的样式： </P>
<P>
<TABLE style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-table-layout-alt: fixed; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt" cellSpacing=0 cellPadding=0 width=228 border=1>
<TBODY>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid" vAlign=top width=80>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>笔的样式 </FONT></STRONG></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt" vAlign=top width=117>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>功能描述 </FONT></STRONG></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=80>
<P><FONT class=90v>PS_SOLID </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=117>
<P><FONT class=90v>绘制实线 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=80>
<P><FONT class=90v>PS_DASH </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=117>
<P><FONT class=90v>绘制虚线 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=80>
<P><FONT class=90v>PS_NULL </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=117>
<P><FONT class=90v>不绘制任何线 </FONT></P></TD></TR></TBODY></TABLE></P>
<P><STRONG>刷子 </STRONG><BR>库存的刷子和库存的笔一样，可以利用SelectObject函数选进设备环境中。CreateDIBPatternBrushPt函数可以用来创建任何尺寸的刷子。图案刷子可以是任何一种颜色或者颜色的组合。 </P>
<P><STRONG>2.0版本的新特性 </STRONG><BR>带有颜色的笔、带有颜色和图案的刷子都是2.0版本中的新特性。 </P>
<P><STRONG>与其他基于Win32的平台的差异 </STRONG><BR>GDI可以支持宽笔和绘制虚线的笔，但是它不支持绘制虚线的宽笔、绘制点线的笔、内部边框笔、任何用于自定义的端盖样式(例如PS_ENDCAP_ROUND). </P>
<P>Windows CE不支持带有阴影线的刷子。但是可以通过CreateDIBPatternBrushPt函数创建定制刷子达到这样的效果。 </P>
<P>Windows CE可以支持Microsoft Windows NT&reg; 操作系统支持的多尺寸图案刷子。Microsoft Windows 95操作系统仅仅支持标准的8*8像素的刷子。 </P>
<P><STRONG>位块传输函数</STRONG></P>
<P>位块传输函数（Bit block transfer，简称blts)用来传输、改变位图。有四种blt函数--PatBlt、BitBlt、MaskBlt、StretchBlt，以及一个相关函数TransparentImage。 </P>
<P>Blt函数对像素进行逐位布尔操作，一般称之为光栅操作编码（raster operation code，简称ROPS)。下面的表格描述了ROP编码和使用它们的blt函数。 </P>
<P>
<TABLE style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-table-layout-alt: fixed; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt" cellSpacing=0 cellPadding=0 width=468 border=1>
<TBODY>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid" vAlign=top width=112>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>ROP类型 </FONT></STRONG></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt" vAlign=top width=325>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><FONT class=90v><STRONG>描述</STRONG></FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=112>
<P><FONT class=90v>ROP2 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=325>
<P><FONT class=90v>将笔或刷子与目标位图按照16种方式之一进行结合。</FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=112>
<P><FONT class=90v>ROP3 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=325>
<P><FONT class=90v>将刷子、源位图和目标位图按照256种方式之一结合 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=112>
<P><FONT class=90v>ROP4 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=325>
<P><FONT class=90v>使用二进制位“掩码”位图结合前景ROP3和背景ROP3。掩码使用0和1标记使用ROP3的位 </FONT></P></TD></TR></TBODY></TABLE></P>
<P><FONT class=90v>&nbsp; </FONT></P>
<TABLE style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-table-layout-alt: fixed; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt" cellSpacing=0 cellPadding=0 width=468 border=1>
<TBODY>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid" vAlign=top width=111>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>BLT函数 </FONT></STRONG></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt" vAlign=top width=326>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>描述 </FONT></STRONG></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=111>
<P><FONT class=90v>PatBlt </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=326>
<P><FONT class=90v>使用选择的刷子和ROP3码绘制选定的矩形 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=111>
<P><FONT class=90v>BitBlt </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=326>
<P><FONT class=90v>使用选定的刷子、源位图和ROP3码绘制选定的矩形 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=111>
<P><FONT class=90v>MaskBlt </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=326>
<P><FONT class=90v>使用两个位图和ROP4码绘制给定的矩形 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=111>
<P><FONT class=90v>StretchBlt </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=326>
<P><FONT class=90v>将位图从源矩形拷贝到目标矩形，把源位图按照目标矩形的尺寸进行拉伸或压缩 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=111>
<P><FONT class=90v>TransparentImage </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=326>
<P><FONT class=90v>拷贝位图，省略透明颜色绘制的部分 </FONT></P></TD></TR></TBODY></TABLE>
<P>Blt函数和ROP码给应用程序编程人员提供强大的、非常有用的工具集，可以用来移动、结合、转换位图。 </P>
<P><STRONG>2.0版本的新特性 </STRONG><BR>1.0版本仅仅支持一部分ROP码；但是在2.0版本中完全获得支持。在新的版本中已经改进了StretchBlt函数，这样被拉伸的图像与源图像更加相似。1.0版本中不支持图像倒置，但是在2.0得到了完全支持。TransparentImage是2.0版本的新特性。 </P>
<P><STRONG>颜色 </STRONG></P>
<P>Windows CE 2.0版本中最令人激动的是增加了对颜色的支持。新的Windows CE GDI支持其他基于Windows的32位平台所支持的所有颜色。 </P>
<P>显示设备或操作系统支持的颜色范围主要由它所支持的像素深度所决定。像素深度是用位/像素（bpp）来决定的。每一个位可以是0或者1。仅仅支持1bpp的显示器只支持黑白两种颜色。像素深度为2 bpp可以支持四种颜色(两位的所有可能的结合情况)值：黑色、白色、浅灰色、深灰色。一般情况下，所支持的颜色个数是2的幂函数，其指数是像素的深度。 </P>
<P>新的Windows CE GDI支持的颜色深度是1、2、4、8、16、24和32 bpp。更高端像素深度可以支持真彩色显示器，低端的像素深度仅仅支持黑白显示器和应用程序。 </P>
<P>GDI颜色系统不仅仅十分强大，而且非常通用。它可以支持不同像素深度的位图之间进行位块传输。这一切都归功于 GDI使用了设备无关位图（device-independent bitmap，简称DIB)。DIB在内部存储数据，独立于任何一种显示器或者打印设备。它自带颜色信息，可以以许多颜色格式显示或者打印，这依赖于显示器或者打印机硬件的性能。几乎所有的GDI图形信息都是以DIB格式进行存储的。 </P>
<P><STRONG>2.0版本的新特性 </STRONG><BR>颜色是2.0版本的新特性。1.0版本仅仅支持1bpp和2bpp的像素深度。 </P>
<P><STRONG>与其他基于Win32的平台的差异 </STRONG><BR>Windows CE支持2bpp像素深度，其他32位Windows平台中不支持这个。 </P>
<P>Windows CE不支持抖动 </P>
<P>Windows CE不支持压缩位图格式，例如行程长度编码（run-length encoded，简称RLE）位图。 </P>
<P><STRONG>调色板 </STRONG></P>
<P>GDI可以让基于Windows CE的应用程序和显示设备联合确定图形显示的最优方式。应用程序需要使用GetDeviceCaps函数访问显示设备的特征。这样就可以根据设备的最佳显示策略创建设备上下文。 </P>
<P>GDI支持调色板和非调色板颜色显示设备。调色板设备在显卡中包括自己内置的颜色调色板；GDI扫描设备显卡中的颜色编码，在颜色表中查找相应的颜色。 </P>
<P>调色板设备直接在帧缓冲区像素中进行编码。它们使用像素的位值直接定义颜色，而不使用硬编码调色板。 </P>
<P>一旦设备上下文的颜色性能确定了，应用程序就可以使用CreatePalette 函数创建调色板，然后使用SelectPalette将它选进当前的设备上下文。通过这两个函数创建和选择的调色板是逻辑调色板，不同于显示设备使用的系统调色板。RealizePalette函数使系统恢复当前选中的逻辑调色板中的值。 </P>
<P><STRONG>2.0版本中的新特性 </STRONG><BR>颜色调色板和它们相关的函数是2.0版本中的新特性。 </P>
<P><STRONG>与其它基于Win32平台的差异 </STRONG><BR>从编程人员的角度来看，Windows CE和其他Win32操作系统的最大差别是Windows CE不判断后台应用程序调色板和前台应用程序调色板的优先级。运行在前台的应用程序可以完全控制系统调色板。正是因为这样，强烈建议基于Windows CE的应用程序只使用库存调色板中的前十种和后十种颜色，即所谓的"Windows颜色"。即使使用这些颜色的应用程序在后台运行，它们也可以适当的显示，但是使用其它颜色的应用程序就不能了。 </P>
<P><STRONG>字体 </STRONG></P>
<P>GDI支持TrueType&reg; 字体和光栅字体，但是在给定的平台上只可以使用其中的一种。 </P>
<P>TrueType字体的轮廓不是通过像素模式定义的，而是由直线和曲线的编码集合决定的，相反光栅字体是由前者决定的。TrueType字体可以被重新调节甚至是旋转。GDI支持所有的Windows标准TrueType字体文件。 </P>
<P><STRONG>2.0版本中的新特性 </STRONG><BR>TrueType字体是2.0版本中的新特性。1.0版本只支持光栅字体。 </P>
<P><STRONG>打印 </STRONG></P>
<P>GDI支持完全的图形打印。 </P>
<P><STRONG>2.0版本中的新特性 </STRONG><BR>打印是Windows CE 2.0的新特性。 </P>
<P><STRONG>与其它基于Win32平台的差异 </STRONG><BR>Windows CE既没有打印机管理器，也不支持假脱机打印或多份打印。打印是单线程，因为一次只允许一个应用程序打印。 </P>
<P><STRONG>显示器特征 </STRONG></P>
<P>Windows CE支持剪辑区域，这可以让应用程序将它们的输出限定在客户区域的某一个子区域上。剪辑区域必须选进给定设备的设备上下文中。 </P>
<P><STRONG>与其它基于Win32平台的差异 </STRONG><BR>Windows CE 不支持多种映射模式。GDI仅仅支持文本映射模式（基于Win32的桌面平台称为MM-TEXT模式），这种方式按照文本的读入方式将位图映射到显示设备，即从左到右，从上到下。视点的初始位置是显示区域的左上角，可以使用SetViewPointOrg函数改变。 </P>
<P><STRONG>小技巧 </STRONG></P>
<P>主要运行在2-bpp或者4-bpp显示设备上的应用程序在任何时候都应该避免使用8-bpp位图，因为颜色转换将会降低blt操作的速度。 </P>
<P>IUsage参数在所有函数中应该设置为DIB_RGB_COLORS。但是当使用8-bpp位图的时候它可以被设置称为DIB_PAL_COLORS，这样BITMAPINFO 结构中的bmiColors数组成员的值将会被忽略。 </P>
<P><STRONG>总结 </STRONG></P>
<P>Windows GDI是一个功能完善的图形系统，支持下列特性。 </P>
<P>
<TABLE style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-table-layout-alt: fixed; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt" height=151 cellSpacing=0 cellPadding=0 width=458 border=1>
<TBODY>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid" vAlign=top align=middle width=89 height=22>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>GDI特性 </FONT></STRONG></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt" vAlign=top width=338 height=22>
<P class=MsoNormal style="TEXT-ALIGN: center" align=center><STRONG style="mso-bidi-font-weight: normal"><FONT class=90v>支持的属性 </FONT></STRONG></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=89 height=15>
<P class=MsoNormal><FONT class=90v>图形绘制 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=338 height=15>
<P class=MsoNormal><FONT class=90v>Ellipse、Polygon、Polyline、Rectangle、RoundRect </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=89 height=12>
<P class=MsoNormal><FONT class=90v>笔和刷子 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=338 height=12>
<P class=MsoNormal><FONT class=90v>虚线、点线、宽的、实线笔；多尺寸刷子 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=89 height=15>
<P class=MsoNormal><FONT class=90v>Blt函数 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=338 height=15>
<P class=MsoNormal><FONT class=90v>PatBlt、BitBlt、MaskBlt、StretchBlt、TransparentImage </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=89 height=15>
<P class=MsoNormal><FONT class=90v>ROP编码 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=338 height=15>
<P class=MsoNormal><FONT class=90v>ROP2、ROP3和ROP4码 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=89 height=15>
<P class=MsoNormal><FONT class=90v>颜色 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=338 height=15>
<P class=MsoNormal><FONT class=90v>1、2、4、8、16、24和 32 bbp像素深度 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=89 height=12>
<P class=MsoNormal><FONT class=90v>调色板 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=338 height=12>
<P class=MsoNormal><FONT class=90v>调色板和非调色板设备支持 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=89 height=15>
<P class=MsoNormal><FONT class=90v>字体 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=338 height=15>
<P class=MsoNormal><FONT class=90v>TrueType和光栅字体 </FONT></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 0.5pt solid; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-top-alt: solid windowtext .5pt" vAlign=top align=middle width=89 height=12>
<P class=MsoNormal><FONT class=90v>打印 </FONT></P></TD>
<TD style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: medium none; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" vAlign=top width=338 height=12>
<P class=MsoNormal><FONT class=90v>图形打印 </FONT></P></TD></TR></TBODY></TABLE></P>
<P>Windows CE的功能，包括GDI，既没有基于Win32的桌面系统强大，也没有打算实现如此强大的功能。Windows CE设备不需要的显示和打印函数已经从GDI中删除了。因此GDI是一个空间占有量较小的、强大的、真彩色的图形显示系统。它的小尺寸和多功能性使得它可以在许多Windows CE设备上显示文本和图形，其中有一些还是目前无法想象的。 </P></FONT></EM>
<P class=postfoot>posted @ <A title=permalink href="http://www.cnblogs.com/menghuanshitou/archive/2009/03/28/1424123.html">2009-03-28 21:33</A> 梦幻石头 阅读(12) | <A title="comments, pingbacks, trackbacks" href="http://www.cnblogs.com/menghuanshitou/archive/2009/03/28/1424123.html#FeedBack">评论 (0)</A> |&nbsp;<A href="http://www.cnblogs.com/menghuanshitou/admin/EditPosts.aspx?postid=1424123">编辑</A> </P></DIV>
<DIV class=post>
<H2><A id=homepage1_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl01_TitleUrl href="http://www.cnblogs.com/menghuanshitou/archive/2009/03/28/1424080.html">透明位图的显示(作者：王俊）</A></H2>
<P><FONT face=Verdana><A href="http://www.vckbase.net/document/viewdoc/?id=532">http://www.vckbase.net/document/viewdoc/?id=532</A></FONT></P>
<P>包含透明色的位图的绘制方法有多种，最简单的方法是调用现成的函数：TransparentBlt,也可以通过自己的代码实现类似TransparentBlt的功能，实现过程也有两种形式，一种是事先做一张掩码位图，另一种是动态生成掩码位图。本文将介绍动态生成掩码位图绘制具有透明区域位图的方法。<BR><BR><STRONG>一、TransparentBlt 函数的使用 </STRONG><BR><BR>TransparentBlt 函数在Windows98/Windows2000以上版本运行，系统中需要包含 Msimg32.dll，使用时可以链接 Msimg32.lib。<BR>Windows98下的TransparentBlt会产生资源泄漏，所以不建议在WIN98下使用该函数。<BR>TransparentBlt函数原型如下: </P><PRE>BOOL TransparentBlt(
HDC hdcDest,      // 目标DC
int nXOriginDest,   // 目标X偏移
int nYOriginDest,   // 目标Y偏移
int nWidthDest,     // 目标宽度
int hHeightDest,    // 目标高度
HDC hdcSrc,         // 源DC
int nXOriginSrc,    // 源X起点
int nYOriginSrc,    // 源Y起点
int nWidthSrc,      // 源宽度
int nHeightSrc,     // 源高度
UINT crTransparent  // 透明色,COLORREF类型
);
</PRE>
<P>使用示例: </P><PRE>CBitmap FootballBMP;
FootballBMP.LoadBitmap(IDB_FOOTBALLBMP);
CDC ImageDC;
ImageDC.CreateCompatibleDC(pDC);
CBitmap *pOldImageBMP = ImageDC.SelectObject(&amp;FootballBMP);
TransparentBlt(pDC-&gt;m_hDC, 0, 0, 218, 199, ImageDC.m_hDC, 0, 0, 218, 199, RGB(0,0,0xff));
ImageDC.SelectObject(pOldImageBMP);
</PRE>
<P>&nbsp;</P>
<P>二、TransparentBlt2，类似于TransparentBlt的实现原理</P>
<P>void TransparentBlt2( HDC hdcDest,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 目标DC<BR>int nXOriginDest,&nbsp;&nbsp; // 目标X偏移<BR>int nYOriginDest,&nbsp;&nbsp; // 目标Y偏移<BR>int nWidthDest,&nbsp;&nbsp;&nbsp;&nbsp; // 目标宽度<BR>int nHeightDest,&nbsp;&nbsp;&nbsp; // 目标高度<BR>HDC hdcSrc,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 源DC<BR>int nXOriginSrc,&nbsp;&nbsp;&nbsp; // 源X起点<BR>int nYOriginSrc,&nbsp;&nbsp;&nbsp; // 源Y起点<BR>int nWidthSrc,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 源宽度<BR>int nHeightSrc,&nbsp;&nbsp;&nbsp;&nbsp; // 源高度<BR>UINT crTransparent&nbsp; // 透明色,COLORREF类型<BR>)<BR>{<BR>HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest); // 创建兼容位图<BR>HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); // 创建单色掩码位图<BR>HDC hImageDC = CreateCompatibleDC(hdcDest);<BR>HDC hMaskDC = CreateCompatibleDC(hdcDest);<BR>hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);<BR>hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);<BR><BR>// 将源DC中的位图拷贝到临时DC中<BR>if (nWidthDest == nWidthSrc &amp;&amp; nHeightDest == nHeightSrc)<BR>BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);<BR>else<BR>StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, <BR>hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);<BR><BR>// 设置透明色<BR>SetBkColor(hImageDC, crTransparent);<BR><BR>// 生成透明区域为白色，其它区域为黑色的掩码位图<BR>BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);<BR><BR>// 生成透明区域为黑色，其它区域保持不变的位图<BR>SetBkColor(hImageDC, RGB(0,0,0));<BR>SetTextColor(hImageDC, RGB(255,255,255));<BR>BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);<BR><BR>// 透明部分保持屏幕不变，其它部分变成黑色<BR>SetBkColor(hdcDest,RGB(255,255,255));<BR>SetTextColor(hdcDest,RGB(0,0,0));<BR>BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);<BR><BR>// "或"运算,生成最终效果<BR>BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);<BR><BR>// 清理、恢复 <BR>SelectObject(hImageDC, hOldImageBMP);<BR>DeleteDC(hImageDC);<BR>SelectObject(hMaskDC, hOldMaskBMP);<BR>DeleteDC(hMaskDC);<BR>DeleteObject(hImageBMP);<BR>DeleteObject(hMaskBMP);<BR>}</P></DIV>]]></description>
</item><item>
<title><![CDATA[图象处理]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45264</link>
<author>oceanblue</author>
<pubDate>2009/5/8 9:54:59</pubDate>
<description><![CDATA[在VC中显示位图常用取BitBlt（）方法，它是将一幅位图从一个设备场景复制到另一个。源和目标DC相互间必须兼容。<BR>虽然此方法的功能是这样的，但是我一直没有理解网上一些例子代码，不知道其用到的各DC和位图如何得到，及它们之间的关系。<BR>今天工作中要将一些位图显示到窗口中，所以重要学习了一下。<BR>我已经将要用的位图导入到工程资源中，所以我可以用：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CBitmap cbmp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cbmp.LoadBitmap(IDB_BMP1);<BR>这样得到一个CBitmap对象。<BR>然后：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BITMAP bitmap;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cbmp.GetBitmap(&amp;bitmap);<BR>这样得到一个BITMAP对象，之所以要得到此对象是因为从其中可以得到位图的大小数据。<BR>然后计算得到要在什么位置显示此位图（可以放在一个CRect rect;对象中）。<BR><BR><STRONG>然后显示此位图，这是最重要的一步：</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CDC dcMemory;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dcMemory.CreateCompatibleDC(pDC);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hOldBitmap = dcMemory.SelectObject(&amp;cbmp);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pDC-&gt;BitBlt(rect.left,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rect.top,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap.bmWidth,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bitmap.bmHeight,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;dcMemory,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0,0,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SRCCOPY);<BR>其中pDC是一个CDC*，是将要在其中显示位图的设备环境。<BR><BR>这样位图就已经显示出来了，但是还要<STRONG>释放资源</STRONG>：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cbmp.DeleteObject();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dcMemory.SelectObject(hOldBitmap);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dcMemory.DeleteDC();<BR>其中，要将临时设备环境选择入初始时位图，否则将<STRONG>不能正确释放</STRONG>！！<BR><BR>总结：<BR>要在一个设备环境中显示位图，不能直接在上面“画”（目前我是我么觉得的），需要创建一个与之相兼容的新设备环境然后将位图选择入些新设备环境，然后再从些新设备环境中拷备位图以显示到正确的设备环境中。而选入这个动作相当与已经将位图“画在了临时设备环境中”（实际上并没有画，否则就可以直接选入要画图的 CDC了），而且选入后位图在临时设备环境中的位置是左上角！]]></description>
</item><item>
<title><![CDATA[工作簿]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45232</link>
<author>oceanblue</author>
<pubDate>2009/5/7 14:52:08</pubDate>
<description><![CDATA[
<P>1.mysql 远程登录 mysql -u&nbsp;username -ppwd</P>
<P>&nbsp; 2掛載 NFS 目錄</P>
<P>命令列模式:</P>
<P>cd \SFU\common<BR>mount linux_ip:/path drive_id: (如: mount 192.168.0.1:/abc e: → 掛載到 E 槽)</P>
<P>MySQL授权:</P>
<P>grant all privileges on *.*&nbsp; to <A href="mailto:name@'IP'">name@'IP'</A> identified by '12345'</P>]]></description>
</item><item>
<title><![CDATA[写程序是一种态度（一）strcmp]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=45079</link>
<author>oceanblue</author>
<pubDate>2009/4/27 15:37:01</pubDate>
<description><![CDATA[<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><font size="3"><span style="font-family: 宋体;" lang="ZH-CN">写程序正如做人，是一种态度。在写一个商业级的程序，从写代码的层次来说是否遵守默认的代码风格（</span>code convention<span style="font-family: 宋体;" lang="ZH-CN">）？是否遵循简单、易读和效率？是否防范了预期的错误？是否检查了内存泄漏？是否考虑会有多线程重入？等等。从设计的层次来说是否引入了软件工程的思想？是否采用了</span>OO<span style="font-family: 宋体;" lang="ZH-CN">的模式分析？是否使用</span>UML<span style="font-family: 宋体;" lang="ZH-CN">来主导了整个流程？是否考虑单元测试和集成测试的</span>QA<span style="font-family: 宋体;" lang="ZH-CN">同步？是否定期生成稳定版本？等等。</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><o:p><font size="3">&nbsp;</font></o:p></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><font size="3"><span style="font-family: 宋体;" lang="ZH-CN">所有的“是”，是一种正确的软件开发态度，它们会让我们短期痛苦，但长远快乐。想成为一个真正有责任感的软件工程师，或者是一个真正有经验的软件架构师（</span>Architect<span style="font-family: 宋体;" lang="ZH-CN">），只有从这一个个“是”中，慢慢体会。</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><o:p><font size="3">&nbsp;</font></o:p></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;" lang="ZH-CN"><font size="3">六
年不停的软件开发，有时并没有让我有什么骄傲感，相反面对有的经典代码，面对前辈或先哲的醍醐灌顶，我的冷汗溢出每个毛孔，令我感到了在这个领域的渺小和
无知。也许是好事，人生本来就是螺旋式上升发展的，也许我到了另一个螺旋的开始了。希望用这个系列，同大家探讨一下成长的上升过程，而不是原地盘旋。我将
扔掉六年所有的浮躁，从头开始端正态度做程序。</font></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><o:p><font size="3">&nbsp;</font></o:p></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><font size="3"><span style="font-family: 宋体;" lang="ZH-CN">分析经典代码是一种最佳方式，我将从最简单但又最绝妙的开始：</span>strcmp</font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: blue; font-family: Verdana;">int</span><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"> <span style="color: blue;">__cdecl</span> strcmp (<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">const</span> <span style="color: blue;">char</span> * src,<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">const</span> <span style="color: blue;">char</span> * dst<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>)<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;">{<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">int</span> ret = 0 ;<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">while</span>( ! (ret = *(<span style="color: blue;">unsigned</span> <span style="color: blue;">char</span> *)src - *(<span style="color: blue;">unsigned</span> <span style="color: blue;">char</span> *)dst) &amp;&amp; *dst)<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>++src, ++dst;<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">if</span> ( ret &lt; 0 )<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp; </span><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>ret = -1 ;<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">else</span> <span style="color: blue;">if</span> ( ret &gt; 0 )<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ret = 1 ;<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span>( ret );<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="background: silver none repeat scroll 0% 0%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; font-family: Verdana;">}<o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><font size="3"><span style="font-family: 宋体;" lang="ZH-CN">这是</span>MS C run-time<span style="font-family: 宋体;" lang="ZH-CN">中的</span>strcmp<span style="font-family: 宋体;" lang="ZH-CN">实现源码。几个问题将揭示它的精髓，会对我们写出相应功能的高质量代码提供指导。</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><o:p><font size="3">&nbsp;</font></o:p></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt;"><font size="3"><span style=""><span style="">1．</span></span>src<span style="font-family: 宋体;" lang="ZH-CN">和</span>dst<span style="font-family: 宋体;" lang="ZH-CN">都为空串</span><span style="font-family: 宋体;" lang="ZH-CN">如何返回？</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt;"><font size="3"><span style=""><span style="">2．</span></span><span style="font-family: 宋体;" lang="ZH-CN">为什么要用</span>unsigned char*<span style="font-family: 宋体;" lang="ZH-CN">强制转换？</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt;"><font size="3"><span style=""><span style="">3．</span></span><span style="font-family: 宋体;" lang="ZH-CN">可否用</span>*src<span style="font-family: 宋体;" lang="ZH-CN">替换</span>*dst<span style="font-family: 宋体;" lang="ZH-CN">作为</span>while<span style="font-family: 宋体;" lang="ZH-CN">条件？</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt;"><font size="3"><span style=""><span style="">4．</span></span><span style="font-family: 宋体;" lang="ZH-CN">是否是</span>multithread-safe<span style="font-family: 宋体;" lang="ZH-CN">？</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt;"><font size="3"><span style=""><span style="">5．</span></span><span style="font-family: 宋体;" lang="ZH-CN">能否用于</span>multibyte-character strings<span style="font-family: 宋体;" lang="ZH-CN">的比较？</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt; text-indent: -18pt;"><font size="3"><span style=""><span style="">6．</span></span><span style="font-family: 宋体;" lang="ZH-CN">能否用更少行表达？</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><o:p><font size="3">&nbsp;</font></o:p></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;" lang="ZH-CN"><font size="3">仔细回答了这些问题之后，你会发现思路是否开阔了一些？希望有这种效果。</font></span></p>]]></description>
</item><item>
<title><![CDATA[Big Endian与little Endian]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=44994</link>
<author>oceanblue</author>
<pubDate>2009/4/22 12:44:18</pubDate>
<description><![CDATA[
<P style="TEXT-INDENT: 2em">谈到字节序的问题，必然牵涉到两大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存储数据，而x86系列则采用little endian方式存储数据。那么究竟什么是big endian，什么又是little endian呢？</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp; 其实big endian是指低地址存放最高有效字节（MSB），而little endian则是低地址存放最低有效字节（LSB）。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp; 用文字说明可能比较抽象，下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示：</P>
<P style="TEXT-INDENT: 2em"><STRONG>Big&nbsp;Endian</STRONG></P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; 低地址&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 高地址</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; -----------------------------------------&gt;</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; 12&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;34&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;56&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp; 78&nbsp;&nbsp;&nbsp; |</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</P>
<P style="TEXT-INDENT: 2em"><STRONG>Little Endian</STRONG></P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; 低地址&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 高地址</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; -----------------------------------------&gt;</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;78&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;56&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;34&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12&nbsp;&nbsp;&nbsp; |</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp; 从上面两图可以看出，采用big endian方式存储数据是符合我们人类的思维习惯的。而little endian，!@#$%^&amp;*，见鬼去吧 -_-|||</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp; 为什么要注意字节序的问题呢？你可能这么问。当然，如果你写的程序只在单机环境下面运行，并且不和别人的程序打交道，那么你完全可以忽略字节序的存在。但是，如果你的程序要跟别人的程序产生交互呢？在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的，而JAVA编写的程序则唯一采用big endian方式来存储数据。试想，如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果？就拿上面的0x12345678来说，你的程序传递给别人的一个数据，将指向0x12345678的指针传给了JAVA程序，由于JAVA采取big endian方式存储数据，很自然的它会将你的数据翻译为0x78563412。什么？竟然变成另外一个数字了？是的，就是这种后果。因此，在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp; 无独有偶，所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序。当两台采用不同字节序的主机通信时，在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。ANSI C中提供了下面四个转换字节序的宏。</P>
<P style="TEXT-INDENT: 2em">big&nbsp;endian：最高字节在地址最低位，最低字节在地址最高位，依次排列。 </P>
<P style="TEXT-INDENT: 2em">little&nbsp;endian：最低字节在最低位，最高字节在最高位，反序排列。 </P>
<P style="TEXT-INDENT: 2em">endian指的是当物理上的最小单元比逻辑上的最小单元小时，逻辑到物理的单元排布关系。咱们接触到的物理单元最小都是byte，在通信领域中，这里往往是bit，不过原理也是类似的。</P>
<P style="TEXT-INDENT: 2em">一个例子：</P>
<P style="TEXT-INDENT: 2em">如果我们将0x1234abcd写入到以0x0000开始的内存中，则结果为</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; big-endian&nbsp;&nbsp;&nbsp;&nbsp; little-endian</P>
<P style="TEXT-INDENT: 2em">0x0000&nbsp;&nbsp;&nbsp;&nbsp; 0x12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0xcd</P>
<P style="TEXT-INDENT: 2em">0x0001&nbsp;&nbsp;&nbsp;&nbsp; 0x34&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0xab</P>
<P style="TEXT-INDENT: 2em">0x0002&nbsp;&nbsp;&nbsp;&nbsp; 0xab&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x34</P>
<P style="TEXT-INDENT: 2em">0x0003&nbsp;&nbsp;&nbsp;&nbsp; 0xcd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x12</P>
<P style="TEXT-INDENT: 2em">目前应该little&nbsp;endian是主流，因为在数据类型转换的时候（尤其是指针转换）不用考虑地址问题。</P>
<P style="TEXT-INDENT: 2em">PS：</P>
<P style="TEXT-INDENT: 2em">这两个术语来自于&nbsp;Jonathan&nbsp;Swift&nbsp;的《《格利佛游记》其中交战的两个派别无法就应该从哪一端－－小端还是大端－－打开一个半熟的鸡蛋达成一致。：） </P>
<P style="TEXT-INDENT: 2em">在那个时代，Swift是在讽刺英国和法国之间的持续冲突，Danny&nbsp;Cohen，一位网络协议的早期开创者，第一次使用这两个术语来指代字节顺序，后来这个术语被广泛接纳了 </P>
<P style="TEXT-INDENT: 2em">摘自《深入理解计算机系统》 </P>
<P style="TEXT-INDENT: 2em">很好的一本书：）</P>]]></description>
</item><item>
<title><![CDATA[DirectShow 在VS2005中环境配置]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=44851</link>
<author>oceanblue</author>
<pubDate>2009/4/14 17:38:24</pubDate>
<description><![CDATA[
<H1 class=xspace-title>DirectShow 在VS2005中环境配置</H1>
<P class=xspace-smalltxt>&nbsp;</P>
<DIV class=xspace-itemmessage id=xspace-showmessage>
<P>一．DirectShow的环境配置：<BR>本人使用的是VS2005,要使用DirectShow进行编程，需要对环境进行必要的配置。</P>
<P>第一步：对dssdk中的baseclass.sln进行编译，生成需要的debug和release文件，具体步骤如下：<BR>在VS6中，安装DirectShow9c版本之后，直接打开BaseClass中的VS6工程baseclasses.dsw文件，直接编译即可，编译Debug&nbsp; Release Debug_Unicode&nbsp;&nbsp; Release_Unicode四个版本，都需要进行额外的设置（头<A onclick="javascript:tagshow(event, '%CE%C4%BC%FE');" href="javascript:;" target=_self><U><STRONG>文件</STRONG></U></A>或者<A onclick="javascript:tagshow(event, '%C1%B4%BD%D3');" href="javascript:;" target=_self><U><STRONG>链接</STRONG></U></A>库目录设置）。<BR>DirectShow的BaseClass中已经带了VS2005的工程文件baseclasses.sln，在vs2005中打开此文件，提示你进行必要的工程转换，转换之后开始编译，编译过程一般会出现下面两个问题：<BR>（1）C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(222) : error C2146: syntax error : missing ';' before identifier 'PVOID64'<BR>（2）error C4430: missing type specifier - int assumed. Note: C++ does not support default-int<BR>（3）error C2065: 'Count' : undeclared identifier<BR>第一类问题的解决：安装xpsp2，如何将其include目录包含进去；一般将其放在dshow头文件之后，放在platsdk目录之前；<BR>第二类问题的解决：错误发生在：operator=(LONG);函数定义中，这是因为在VC6中，如果没有显示的指定返回值类型，编译器将其视为默认整形；但是vs2005不支持默认整形，解决这个问题不能修改每个没有显示指示返回值类型的函数地方，可以用wd4430来解决；具体的在工程选项中的c++/Command Line中添加/wd4430即可。<BR>第三个错误发生在for循环中，vs6中for循环中定义的变量相当于在for外面定义，可以在for之外地方使用；但是vs2005for循环中定义变量相当于域{}变量，只能在for循环中使用。要解决这个问题，可以通过修改vs2005的工程选项：”Project Option” --– “ C++ ” —--&nbsp; “Language” --- “Force Comformance in For Loop Scrope” 设置为No即可。<BR>完成上面的设置，BaseClass工程基本可以编译通过了。</P>
<P>第二步：需要设置相应的配置<BR>在把dxsdk中提供的baseclass编译通过后，用四种方式编译，会分别生成四个lib，一般只用到了其中的Debug和Release文件，在tool|option|vc++ directories中包含的files中设置如下。<BR>这里需要加入得include files有三种：<BR>D:\SDK\DXSDK\Include<BR>D:\SDK\DXSDK\Samples\C++\DirectShow\BaseClasses<BR>D:\SDK\DXSDK\Samples\C++\Common\Include</P>
<P>在后边的library files中也需要增加三到四种的文件：<BR>D:\SDK\DXSDK\Lib<BR>D:\SDK\DXSDK\Samples\C++\DirectShow\BaseClasses\Debug<BR>D:\SDK\DXSDK\Samples\C++\DirectShow\BaseClasses\Release</P>
<P>把以上设置好，基本就可以将DirectShow程序在vs2005环境中编译通过。</P></DIV>]]></description>
</item><item>
<title><![CDATA[vc连接ado的方法]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=44606</link>
<author>oceanblue</author>
<pubDate>2009/4/9 20:50:23</pubDate>
<description><![CDATA[
<H2>准备工作</H2>
<H3>(1)、引入ADO类</H3>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN class=preprocessor>#import&nbsp;"c:\program&nbsp;files\common&nbsp;files\system\ado\msado15.dll"&nbsp;\</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;no_namespace&nbsp;\</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;rename&nbsp;(<SPAN class=string>"EOF"</SPAN><SPAN>,&nbsp;</SPAN><SPAN class=string>"adoEOF"</SPAN><SPAN>)&nbsp;</SPAN></SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    #import "c:\program files\common files\system\ado\msado15.dll" \
        no_namespace \
        rename ("EOF", "adoEOF") </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H3>(2)、初始化COM</H3>&nbsp;&nbsp;&nbsp; 在MFC中可以用AfxOleInit();非MFC环境中用: <BR>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>CoInitialize(NULL);</SPAN></SPAN> 
<LI><SPAN>CoUnInitialize();&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    CoInitialize(NULL);
    CoUnInitialize(); </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H3>(3)#import 包含后就可以用3个智能指针了:_ConnectionPtr、_RecordsetPtr和_CommandPtr</H3>
<H2>1.连接和关闭数据库</H2>
<H3>(1)连接</H3>&nbsp;&nbsp;&nbsp; 例子:连接Access数据库 <BR>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>AfxOleInit();</SPAN><SPAN class=comment>//初始化</SPAN></SPAN> 
<LI><SPAN><SPAN class=datatypes>HRESULT</SPAN><SPAN>&nbsp;hr;</SPAN></SPAN> 
<LI class=alt><SPAN><SPAN class=keyword>try</SPAN></SPAN> 
<LI><SPAN>{</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;hr&nbsp;=&nbsp;m_pConnection.CreateInstance(<SPAN class=string>"ADODB.Connection"</SPAN><SPAN>);</SPAN><SPAN class=comment>///创建Connection对象</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=keyword>if</SPAN><SPAN>(SUCCEEDED(hr))</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;{</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pConnection-&gt;ConnectionTimeout&nbsp;=&nbsp;0;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hr&nbsp;=&nbsp;m_pConnection-&gt;Open(&nbsp;<SPAN class=string>"Provider=Microsoft.Jet.OLEDB.4.0;Data&nbsp;Source=db.mdb"</SPAN><SPAN>,&nbsp;</SPAN><SPAN class=string>""</SPAN><SPAN>,&nbsp;</SPAN><SPAN class=string>""</SPAN><SPAN>,&nbsp;adModeUnknown);</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=comment>//m_pConnection-&gt;PutDefaultDatabase&nbsp;((_bstr_t)"DB");//设置默认数据库</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pCommand.CreateInstance(__uuidof(Command));</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pCommand-&gt;CommandTimeout&nbsp;=&nbsp;5;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pCommand-&gt;ActiveConnection&nbsp;=&nbsp;m_pConnection;</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN> 
<LI class=alt><SPAN>}</SPAN> 
<LI><SPAN><SPAN class=keyword>catch</SPAN><SPAN>(_com_error&nbsp;e)</SPAN><SPAN class=comment>///捕捉异常</SPAN></SPAN> 
<LI class=alt><SPAN>{</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;errormessage;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;errormessage.Format(<SPAN class=string>"连接数据库失败! 错误信息:%s"</SPAN><SPAN>,e.ErrorMessage());</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;AfxMessageBox(errormessage);<SPAN class=comment>///显示错误信息</SPAN></SPAN> 
<LI class=alt><SPAN>}&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    AfxOleInit();//初始化
    HRESULT hr;
    try
    {
        hr = m_pConnection.CreateInstance("ADODB.Connection");///创建Connection对象
        if(SUCCEEDED(hr))
        {
            m_pConnection-&gt;ConnectionTimeout = 0;
            hr = m_pConnection-&gt;Open( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db.mdb", "", "", adModeUnknown);
            //m_pConnection-&gt;PutDefaultDatabase ((_bstr_t)"DB");//设置默认数据库
            m_pCommand.CreateInstance(__uuidof(Command));
            m_pCommand-&gt;CommandTimeout = 5;
            m_pCommand-&gt;ActiveConnection = m_pConnection;
        }
    }
    catch(_com_error e)///捕捉异常
    {
        CString errormessage;
        errormessage.Format("连接数据库失败!
错误信息:%s",e.ErrorMessage());
        AfxMessageBox(errormessage);///显示错误信息
    } </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H3>(2)、关闭</H3>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN class=comment>//如果数据库连接有效</SPAN></SPAN> 
<LI><SPAN><SPAN class=keyword>if</SPAN><SPAN>(&nbsp;m_pConnection-&gt;State&nbsp;)</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_pConnection-&gt;Close();</SPAN> 
<LI><SPAN>m_pConnection&nbsp;=&nbsp;NULL;&nbsp;&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    //如果数据库连接有效
    if( m_pConnection-&gt;State )
        m_pConnection-&gt;Close();
    m_pConnection = NULL;  </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H3>(3)、设置连接时间 <BR>&nbsp;</H3>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN class=comment>//设置连接时间-----------------------------------</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;pConnection-&gt;put_ConnectionTimeout(<SPAN class=datatypes>long</SPAN><SPAN>(5));</SPAN></SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>//设置连接时间-----------------------------------
    pConnection-&gt;put_ConnectionTimeout(long(5));</PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H2>2.打开一个结果集</H2>
<H3>(1)打开,首先创建一个_RecordsetPtr实例,然后调用Open()得到一条SQL语句的执行结果</H3>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>_RecordsetPtr&nbsp;m_pRecordset;</SPAN></SPAN> 
<LI><SPAN>m_pRecordset.CreateInstance(__uuidof(Recordset));</SPAN> 
<LI class=alt><SPAN><SPAN class=comment>//&nbsp;在ADO操作中建议语句中要常用try...catch()来捕获错误信息，</SPAN></SPAN> 
<LI><SPAN><SPAN class=comment>//&nbsp;因为它有时会经常出现一些意想不到的错误。jingzhou&nbsp;xu</SPAN></SPAN> 
<LI class=alt><SPAN><SPAN class=keyword>try</SPAN></SPAN> 
<LI><SPAN>{</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_pRecordset-&gt;Open(<SPAN class=string>"SELECT&nbsp;*&nbsp;FROM&nbsp;DemoTable"</SPAN><SPAN>,</SPAN><SPAN class=comment>//&nbsp;查询DemoTable表中所有字段</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pConnection.GetInterfacePtr(),&nbsp;&nbsp;<SPAN class=comment>//&nbsp;获取库接库的IDispatch指针</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;adOpenDynamic,</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;adLockOptimistic,</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;adCmdText);</SPAN> 
<LI><SPAN>}</SPAN> 
<LI class=alt><SPAN><SPAN class=keyword>catch</SPAN><SPAN>(_com_error&nbsp;*e)</SPAN></SPAN> 
<LI><SPAN>{</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;AfxMessageBox(e-&gt;ErrorMessage());</SPAN> 
<LI><SPAN>}&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    _RecordsetPtr m_pRecordset;
    m_pRecordset.CreateInstance(__uuidof(Recordset));
    // 在ADO操作中建议语句中要常用try...catch()来捕获错误信息，
    // 因为它有时会经常出现一些意想不到的错误。jingzhou xu
    try
    {
        m_pRecordset-&gt;Open("SELECT * FROM DemoTable",// 查询DemoTable表中所有字段
            m_pConnection.GetInterfacePtr(),  // 获取库接库的IDispatch指针
            adOpenDynamic,
            adLockOptimistic,
            adCmdText);
    }
    catch(_com_error *e)
    {
        AfxMessageBox(e-&gt;ErrorMessage());
    } </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H3>(2)关闭结果集</H3>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>m_pRecordset-&gt;Close();&nbsp;</SPAN></SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>m_pRecordset-&gt;Close(); </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H2>3.操作一个结果集</H2>
<H3>(1)、遍历(读取)</H3>
<H4>&nbsp;&nbsp;&nbsp; a)、用pRecordset-&gt;adoEOF来判断数据库指针是否已经移到结果集的末尾了；m_pRecordset-&gt;BOF判断是否 在第一条记录前面：</H4>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN class=keyword>while</SPAN><SPAN>(!m_pRecordset-&gt;adoEOF)</SPAN></SPAN> 
<LI><SPAN>{</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;=&nbsp;m_pRecordset-&gt;GetCollect(<SPAN class=string>"Name"</SPAN><SPAN>);</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=keyword>if</SPAN><SPAN>(var.vt&nbsp;!=&nbsp;VT_NULL)</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;strName&nbsp;=&nbsp;(<SPAN class=datatypes>LPCSTR</SPAN><SPAN>)_bstr_t(var);</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;=&nbsp;m_pRecordset-&gt;GetCollect(<SPAN class=string>"Age"</SPAN><SPAN>);</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=keyword>if</SPAN><SPAN>(var.vt&nbsp;!=&nbsp;VT_NULL)</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;strAge&nbsp;=&nbsp;(<SPAN class=datatypes>LPCSTR</SPAN><SPAN>)_bstr_t(var);</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_AccessList.AddString(&nbsp;strName&nbsp;+&nbsp;<SPAN class=string>"&nbsp;--&gt;&nbsp;"</SPAN><SPAN>+strAge&nbsp;);</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_pRecordset-&gt;MoveNext();</SPAN> 
<LI class=alt><SPAN>}&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    while(!m_pRecordset-&gt;adoEOF)
    {
        var = m_pRecordset-&gt;GetCollect("Name");
        if(var.vt != VT_NULL)
        strName = (LPCSTR)_bstr_t(var);
        var = m_pRecordset-&gt;GetCollect("Age");
        if(var.vt != VT_NULL)
        strAge = (LPCSTR)_bstr_t(var);
        m_AccessList.AddString( strName + " --&gt; "+strAge );
        m_pRecordset-&gt;MoveNext();
    } </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H4>&nbsp;&nbsp;&nbsp; b)、取得一个字段的值的办法有两种办法</H4>
<H5>&nbsp;&nbsp;&nbsp; 一是</H5>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>&nbsp;</SPAN><SPAN class=comment>//表示取得第0个字段的值</SPAN></SPAN> 
<LI><SPAN>rdset-&gt;GetCollect(<SPAN class=string>"Name"</SPAN><SPAN>);</SPAN></SPAN> 
<LI class=alt><SPAN><SPAN class=comment>//&nbsp;或者</SPAN></SPAN> 
<LI><SPAN>rdset-&gt;GetCollect(_variant_t(<SPAN class=datatypes>long</SPAN><SPAN>(0));</SPAN></SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>        //表示取得第0个字段的值
m_pRecordset-&gt;GetCollect("Name");
       // 或者
m_pRecordset-&gt;GetCollect(_variant_t(long(0));
</PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV><BR>
<H5>&nbsp;&nbsp;&nbsp; 二是</H5>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>pRecordset-&gt;get_Collect(</SPAN><SPAN class=string>"COLUMN_NAME"</SPAN><SPAN>);</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=comment>//或者&nbsp;</SPAN></SPAN> 
<LI class=alt><SPAN>pRecordset-&gt;get_Collect(<SPAN class=datatypes>long</SPAN><SPAN>(index));&nbsp;</SPAN></SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>pRecordset-&gt;get_Collect("COLUMN_NAME");
        //或者 
pRecordset-&gt;get_Collect(long(index)); </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H3>(2)、添加</H3>
<OL>
<LI>&nbsp;&nbsp;&nbsp; 调用m_pRecordset-&gt;AddNew(); 
<LI>&nbsp;&nbsp;&nbsp; 调用m_pRecordset-&gt;PutCollect();给每个字段赋值 
<LI>&nbsp;&nbsp;&nbsp; 调用m_pRecordset-&gt;Update();确认 </LI></OL>
<H3>(3)、修改</H3>
<H3>(4)、删除</H3>
<H4>&nbsp;&nbsp;&nbsp; a)、把记录指针移动到要删除的记录上,然后调用</H4>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>Delete(adAffectCurrent)</SPAN></SPAN> 
<LI><SPAN><SPAN class=keyword>try</SPAN></SPAN> 
<LI class=alt><SPAN>{</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=comment>//&nbsp;假设删除第二条记录</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_pRecordset-&gt;MoveFirst();</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_pRecordset-&gt;Move(1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=comment>//&nbsp;从0开始</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_pRecordset-&gt;Delete(adAffectCurrent);&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=comment>//&nbsp;参数adAffectCurrent为删除当前记录</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_pRecordset-&gt;Update();</SPAN> 
<LI class=alt><SPAN>}</SPAN> 
<LI><SPAN><SPAN class=keyword>catch</SPAN><SPAN>(_com_error&nbsp;*e)</SPAN></SPAN> 
<LI class=alt><SPAN>{</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;AfxMessageBox(e-&gt;ErrorMessage());</SPAN> 
<LI class=alt><SPAN>}&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    Delete(adAffectCurrent)
    try
    {
        // 假设删除第二条记录
        m_pRecordset-&gt;MoveFirst();
        m_pRecordset-&gt;Move(1);       
        // 从0开始
        m_pRecordset-&gt;Delete(adAffectCurrent); 
        // 参数adAffectCurrent为删除当前记录
        m_pRecordset-&gt;Update();
    }
    catch(_com_error *e)
    {
        AfxMessageBox(e-&gt;ErrorMessage());
    } </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H2>4.直接执行SQL语句,除了要用到结果集其余的大部分功能都可以直接用SQL语言实现</H2>
<H3>(1)、用_CommandPtr和_RecordsetPtr配合</H3>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>_CommandPtr&nbsp;m_pCommand;</SPAN></SPAN> 
<LI><SPAN>m_pCommand.CreateInstance(__uuidof(Command));</SPAN> 
<LI class=alt><SPAN><SPAN class=comment>//&nbsp;将库连接赋于它</SPAN></SPAN> 
<LI><SPAN>m_pCommand-&gt;ActiveConnection&nbsp;=&nbsp;m_pConnection;&nbsp;</SPAN> 
<LI class=alt><SPAN><SPAN class=comment>//&nbsp;SQL语句</SPAN></SPAN> 
<LI><SPAN>m_pCommand-&gt;CommandText&nbsp;=&nbsp;<SPAN class=string>"SELECT&nbsp;*&nbsp;FROM&nbsp;DemoTable"</SPAN><SPAN>;&nbsp;</SPAN></SPAN> 
<LI class=alt><SPAN><SPAN class=comment>//&nbsp;执行SQL语句，返回记录集</SPAN></SPAN> 
<LI><SPAN>m_pRecordset&nbsp;=&nbsp;m_pCommand-&gt;Execute(NULL,&nbsp;NULL,adCmdText);&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    _CommandPtr m_pCommand;
    m_pCommand.CreateInstance(__uuidof(Command));
    // 将库连接赋于它
    m_pCommand-&gt;ActiveConnection = m_pConnection; 
    // SQL语句
    m_pCommand-&gt;CommandText = "SELECT * FROM DemoTable"; 
    // 执行SQL语句，返回记录集
    m_pRecordset = m_pCommand-&gt;Execute(NULL, NULL,adCmdText); </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H3>(2)、直接用_ConnectionPtr执行SQL语句</H3>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>_RecordsetPtr&nbsp;Connection15::Execute&nbsp;(&nbsp;_bstr_t&nbsp;CommandText,</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;VARIANT&nbsp;*&nbsp;RecordsAffected,</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=datatypes>long</SPAN><SPAN>&nbsp;Options&nbsp;)&nbsp;</SPAN></SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    _RecordsetPtr Connection15::Execute ( _bstr_t CommandText,
        VARIANT * RecordsAffected,
        long Options ) </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV><BR>&nbsp;&nbsp;&nbsp; 其中CommandText是命令字串，通常是SQL命令。 <BR>&nbsp;&nbsp;&nbsp; 参数RecordsAffected是操作完成后所影响的行数, <BR>&nbsp;&nbsp;&nbsp; 参数Options表示CommandText中内容的类型，Options可以取如下值之一： 
<UL>
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adCmdText:表明CommandText是文本命令 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adCmdTable:表明CommandText是一个表名 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adCmdProc:表明CommandText是一个存储过程 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adCmdUnknown:未知 </LI></UL>&nbsp;&nbsp;&nbsp; 例子: <BR>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>_variant_t&nbsp;RecordsAffected;</SPAN></SPAN> 
<LI><SPAN>m_pConnection-&gt;Execute(<SPAN class=string>"UPDATE&nbsp;users&nbsp;SET&nbsp;old&nbsp;=&nbsp;old+1"</SPAN><SPAN>,&amp;RecordsAffected,adCmdText);&nbsp;</SPAN></SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>        _variant_t RecordsAffected;
        m_pConnection-&gt;Execute("UPDATE users SET old = old+1",&amp;RecordsAffected,adCmdText); </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H2>5.调用存储过程</H2>
<H3>(1)、利用_CommandPtr</H3>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>_CommandPtrm_pCommand;</SPAN></SPAN> 
<LI><SPAN>m_pCommand.CreateInstance(__uuidof(Command));</SPAN> 
<LI class=alt><SPAN>m_pCommand-&gt;ActiveConnection&nbsp;=&nbsp;m_pConnection;&nbsp;&nbsp;<SPAN class=comment>//&nbsp;将库连接赋于它</SPAN></SPAN> 
<LI><SPAN>m_pCommand-&gt;CommandText&nbsp;=&nbsp;<SPAN class=string>"Demo"</SPAN><SPAN>;&nbsp;</SPAN></SPAN> 
<LI class=alt><SPAN>m_pCommand-&gt;Execute(NULL,NULL,&nbsp;adCmdStoredProc);&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    _CommandPtrm_pCommand;
    m_pCommand.CreateInstance(__uuidof(Command));
    m_pCommand-&gt;ActiveConnection = m_pConnection;  // 将库连接赋于它
    m_pCommand-&gt;CommandText = "Demo"; 
    m_pCommand-&gt;Execute(NULL,NULL, adCmdStoredProc); </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H3>(2)、直接用_ConnectionPtr直接调用(见4.(2))</H3>
<H2>6.遍历数据库中的所有表名</H2>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>_ConnectionPtr&nbsp;m_pConnect;</SPAN></SPAN> 
<LI> 
<LI class=alt><SPAN>_RecordsetPtr&nbsp;pSet;</SPAN> 
<LI><SPAN><SPAN class=datatypes>HRESULT</SPAN><SPAN>&nbsp;hr;</SPAN></SPAN> 
<LI class=alt><SPAN><SPAN class=keyword>try</SPAN></SPAN> 
<LI><SPAN>{&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;hr&nbsp;=&nbsp;m_pConnect.CreateInstance(<SPAN class=string>"ADODB.Connection"</SPAN><SPAN>);&nbsp;&nbsp;&nbsp;</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=keyword>if</SPAN><SPAN>(SUCCEEDED(hr))&nbsp;</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;{</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;dd;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dd.Format(<SPAN class=string>"Provider=Microsoft.Jet.OLEDB.4.0;Data&nbsp;Source=%s"</SPAN><SPAN>,file);&nbsp;</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hr&nbsp;=&nbsp;m_pConnect-&gt;Open((_bstr_t)dd,<SPAN class=string>""</SPAN><SPAN>,</SPAN><SPAN class=string>""</SPAN><SPAN>,adModeUnknown);&nbsp;</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pSet&nbsp;=&nbsp;m_pConnect-&gt;OpenSchema(adSchemaTables);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=keyword>while</SPAN><SPAN>(!(pSet-&gt;adoEOF))&nbsp;</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=comment>//获取表格&nbsp;&nbsp;&nbsp;</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_bstr_t&nbsp;table_name&nbsp;=&nbsp;pSet-&gt;Fields-&gt;GetItem(<SPAN class=string>"TABLE_NAME"</SPAN><SPAN>)-&gt;Value;</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=comment>//获取表格类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_bstr_t&nbsp;table_type&nbsp;=&nbsp;pSet-&gt;Fields-&gt;GetItem(<SPAN class=string>"TABLE_TYPE"</SPAN><SPAN>)-&gt;Value;</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=comment>//过滤一下，只输出表格名称，其他的省略</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=keyword>if</SPAN><SPAN>&nbsp;(&nbsp;strcmp(((</SPAN><SPAN class=datatypes>LPCSTR</SPAN><SPAN>)table_type),</SPAN><SPAN class=string>"TABLE"</SPAN><SPAN>)==0){</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;tt;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tt.Format(<SPAN class=string>"%s"</SPAN><SPAN>,(</SPAN><SPAN class=datatypes>LPCSTR</SPAN><SPAN>)table_name);&nbsp;&nbsp;&nbsp;</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AfxMessageBox(tt);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pSet-&gt;MoveNext();&nbsp;&nbsp;&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pSet-&gt;Close();&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_pConnect-&gt;Close();&nbsp;</SPAN> 
<LI class=alt><SPAN>}<SPAN class=keyword>catch</SPAN><SPAN>(_com_error&nbsp;e)</SPAN><SPAN class=comment>///捕捉异常</SPAN></SPAN> 
<LI><SPAN>{&nbsp;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;errormessage;&nbsp;</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;errormessage.Format(<SPAN class=string>"连接数据库失败!rn错误信息:%s"</SPAN><SPAN>,e.ErrorMessage());</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;AfxMessageBox(errormessage);</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;<SPAN class=keyword>return</SPAN><SPAN>&nbsp;-1;</SPAN></SPAN> 
<LI class=alt><SPAN>}&nbsp;</SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    _ConnectionPtr m_pConnect;

    _RecordsetPtr pSet;
    HRESULT hr;
    try
    { 
        hr = m_pConnect.CreateInstance("ADODB.Connection");   
        if(SUCCEEDED(hr)) 
        {
            CString dd; 
            dd.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s",file); 
            hr = m_pConnect-&gt;Open((_bstr_t)dd,"","",adModeUnknown); 
            pSet = m_pConnect-&gt;OpenSchema(adSchemaTables);     
            while(!(pSet-&gt;adoEOF)) 
            {       
                //获取表格   
                _bstr_t table_name = pSet-&gt;Fields-&gt;GetItem("TABLE_NAME")-&gt;Value;
                //获取表格类型       
                _bstr_t table_type = pSet-&gt;Fields-&gt;GetItem("TABLE_TYPE")-&gt;Value;
                //过滤一下，只输出表格名称，其他的省略
                if ( strcmp(((LPCSTR)table_type),"TABLE")==0){
                    CString tt;
                    tt.Format("%s",(LPCSTR)table_name);   
                    AfxMessageBox(tt);       
                }     
                pSet-&gt;MoveNext();   
            } 
            pSet-&gt;Close(); 
        } 
        m_pConnect-&gt;Close(); 
    }catch(_com_error e)///捕捉异常
    { 
        CString errormessage; 
        errormessage.Format("连接数据库失败!rn错误信息:%s",e.ErrorMessage());
        AfxMessageBox(errormessage);
        return -1;
    } </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H2>7.遍历一个表中的所有字段</H2>
<DIV class=HighLighter contentEditable=false>
<DIV class=dp-highlighter contentEditable=false>
<OL class=dp-cpp>
<LI class=alt><SPAN><SPAN>Field&nbsp;*&nbsp;&nbsp;field&nbsp;=&nbsp;NULL;</SPAN></SPAN> 
<LI><SPAN><SPAN class=datatypes>HRESULT</SPAN><SPAN>&nbsp;&nbsp;hr;</SPAN></SPAN> 
<LI class=alt><SPAN>Fields&nbsp;*&nbsp;&nbsp;fields&nbsp;=&nbsp;NULL;</SPAN> 
<LI><SPAN>hr&nbsp;=&nbsp;m_pRecordset-&gt;get_Fields&nbsp;(&amp;fields);<SPAN class=comment>//得到记录集的字段集和</SPAN></SPAN> 
<LI class=alt> 
<LI><SPAN><SPAN class=keyword>if</SPAN><SPAN>(SUCCEEDED(hr))</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;fields-&gt;get_Count(&amp;ColCount);</SPAN> 
<LI><SPAN><SPAN class=comment>//得到记录集的字段集合中的字段的总个数</SPAN></SPAN> 
<LI class=alt><SPAN><SPAN class=keyword>for</SPAN><SPAN>(i=0;i&nbsp;...</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;Item[i]-&gt;get_Name(&amp;bstrColName);<SPAN class=comment>//得到记录集//中的字段名</SPAN></SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;strColName=bstrColName;</SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;nameField&nbsp;=&nbsp;strColName;</SPAN> 
<LI class=alt><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;m_FieldsList.AddString(nameField);</SPAN> 
<LI><SPAN>}</SPAN> 
<LI class=alt><SPAN><SPAN class=keyword>if</SPAN><SPAN>(SUCCEEDED(hr))</SPAN></SPAN> 
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;fields-&gt;Release();<SPAN class=comment>//释放指针&nbsp;</SPAN></SPAN> </LI></OL></DIV>
<DIV class=cpp contentEditable=false style="DISPLAY: none"><PRE>    Field *  field = NULL;
    HRESULT  hr;
    Fields *  fields = NULL;
    hr = m_pRecordset-&gt;get_Fields (&amp;fields);//得到记录集的字段集和

    if(SUCCEEDED(hr))
        fields-&gt;get_Count(&amp;ColCount);
    //得到记录集的字段集合中的字段的总个数
    for(i=0;i ...
        Item[i]-&gt;get_Name(&amp;bstrColName);//得到记录集//中的字段名
        strColName=bstrColName;
        nameField = strColName;
        m_FieldsList.AddString(nameField);
    }
    if(SUCCEEDED(hr))
        fields-&gt;Release();//释放指针 </PRE></DIV>
<DIV contentEditable=false><LINK href="http://www.cppprog.com/fckeditor/editor/plugins/highlighter/dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css" type=text/css rel=stylesheet></DIV></DIV>
<H2>附:</H2>
<H3>1、_variant_t</H3>(1)、一般传给这3个指针的值都不是MFC直接支持的数据类型,而要用_variant_t转换一下 <BR>&nbsp;&nbsp;&nbsp; _variant_t(XX)可以把大多数类型的变量转换成适合的类型传入 <BR>(2)、_variant_t var;<BR>&nbsp;&nbsp;&nbsp; _variant_t -&gt; long: (long)var; <BR>&nbsp;&nbsp;&nbsp; _variant_t -&gt; CString: CString strValue = (LPCSTR)_bstr_t(var); <BR>&nbsp;&nbsp;&nbsp; CString -&gt; _variant_t: _variant_t(strSql); 
<H3>2、BSTR宽字符串与CString相互转换</H3>&nbsp;&nbsp;&nbsp; BSTR bstr; <BR>&nbsp;&nbsp;&nbsp; CString strSql; <BR>&nbsp;&nbsp;&nbsp; CString -&gt; BSTR: bstr = strSql.AllocSysString(); <BR>&nbsp;&nbsp;&nbsp; BSTR -&gt; CString: strSql = (LPCSTR)bstr; 
<H3>3、_bstr_t与CString相互转换</H3>&nbsp;&nbsp;&nbsp; _bstr_t bstr; <BR>&nbsp;&nbsp;&nbsp; CString strSql; <BR>&nbsp;&nbsp;&nbsp; CString -&gt; _bstr_t: bstr = (_bstr_t)strSql; <BR>&nbsp;&nbsp;&nbsp; _bstr_t -&gt; CString: strSql = (LPCSTR)bstr; 
<H3>4、关于时间</H3>&nbsp;&nbsp;&nbsp; Access:表示时间的字符串#2004-4-5# <BR>&nbsp;&nbsp;&nbsp; Sql:表示时间的字符串''2004-4-5'' <BR>&nbsp;&nbsp;&nbsp; DateField(时间字段) <BR>&nbsp;&nbsp;&nbsp; select * from my_table where DateField &gt; #2004-4-10# <BR>&nbsp;&nbsp;&nbsp; try <BR>&nbsp;&nbsp;&nbsp; { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pCommand-&gt;CommandText = "INSERT INTO tTest(age) VALUES('23f2') "; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pRecordset = m_pCommand-&gt;Execute(NULL,NULL, adCmdText);&nbsp; <BR>&nbsp;&nbsp;&nbsp; } <BR>&nbsp;&nbsp;&nbsp; catch(_com_error e)///捕捉异常 <BR>&nbsp;&nbsp;&nbsp; { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CString errormessage; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errormessage.Format("连接数据库失败! 错误信息:%s",e.ErrorMessage()); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AfxMessageBox(errormessage);///显示错误信息 <BR>&nbsp;&nbsp;&nbsp; }]]></description>
</item><item>
<title><![CDATA[mfc小结]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=44477</link>
<author>oceanblue</author>
<pubDate>2009/4/6 22:26:44</pubDate>
<description><![CDATA[<P>两个都要设置才能去掉help button:</P>
<P>Sheet:</P>
<P>&nbsp;&nbsp; CPropertySheet bb;</P>
<P>&nbsp;bb.m_psh.dwFlags |= PSH_NOAPPLYNOW|PSH_HASHELP;<BR>&nbsp;&nbsp;&nbsp;bb.m_psh.dwFlags&nbsp;&nbsp; &amp;=&nbsp;&nbsp; ~PSH_HASHELP;</P>
<P>Page:</P>
<P>&nbsp;&nbsp;&nbsp; m_psp.dwFlags&nbsp;&nbsp; &amp;=&nbsp;&nbsp; ~PSP_HASHELP;</P>]]></description>
</item><item>
<title><![CDATA[解决窗口刷新闪烁]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=44434</link>
<author>oceanblue</author>
<pubDate>2009/4/5 19:20:33</pubDate>
<description><![CDATA[
<P>一般的windows 复杂的界面需要使用多层窗口而且要用贴图来美化，所以不可避免在窗口移动或者改变大小的时候出现闪烁。</P>
<P>先来谈谈闪烁产生的原因</P>
<P>原因一：<BR>如果熟悉显卡原理的话，调用GDI函数向屏幕输出的时候并不是立刻就显示在屏幕<BR>上只是写到了显存里，而显卡每隔一段时间把显存的内容输出到屏幕上，这就是刷新周期。</P>
<P>一般显卡的刷新周期是 1/80秒左右，具体数字可以自己设置的。</P>
<P>这样问题就来了，一般画图都是先画背景色，然后再把内容画上去，如果这两次操作不在同一个<BR>刷新周期内完成，那么给人的视觉感受就是，先看到只有背景色的图像，然后看到画上内容的图像，<BR>这样就会感觉闪烁了。</P>
<P>解决方法：尽量快的输出图像，使输出在一个刷新周期内完成，如果输出内容很多比较慢，那么采用<BR>内存缓冲的方法，先把要输出的内容在内存准备好，然后一次输出到显存。要知道一次API调用一般可以<BR>在一个刷新周期内完成。</P>
<P>对于GDI，用创建内存DC的方法就可以了</P>
<P>原因二：</P>
<P>复杂的界面有多层窗口组成，当windows在窗口改变大小的时候是先重画父窗口，然后重画子窗口，子父<BR>窗口重画的过程一般无法在一个刷新周期内完成，所以会呈现闪烁。</P>
<P>我们知道父窗口上被子窗口挡住的部分其实没必要重画的</P>
<P>解决方法：给窗口加个风格 WS_CLIPCHILDREN ,这样父窗口上被子窗口挡住的部分就不会重画了。</P>
<P>如果同级窗口之间有重叠，那么需要再加上 WS_CLIPSIBLINGS 风格</P>
<P>原因三：</P>
<P>有时候需要在窗口上使用一些控件，比如IE，当你的窗口改变大小的时候IE会闪烁，即使你有了WS_CLIPCHILDREN<BR>也没用。原因在于窗口的类风格有CS_HREDRAW 或者 CS_VREDRAW，这两个风格表示窗口在宽度或者高度变化的时候<BR>重画，但是这样就会引起IE闪烁</P>
<P>解决方法：注册窗口类的时候不要使用这两个风格，如果窗口需要在改变大小的时候重画，那么可以在WM_SIZE的时候<BR>调用RedrawWindow。</P>
<P>原因四：</P>
<P>界面上窗口很多，而且改变大小时很多窗口都要移动和改变大小，如果使用MoveWindow或者SetWindowPos两个API来<BR>改变窗口的大小和位置，由于他们是等待窗口重画完成后才返回，所以过程很慢，这样视觉效果就可能会闪烁。</P>
<P>解决方法：</P>
<P>使用以下API来处理窗口移动，BeginDeferWindowPos, DeferWindowPos，EndDeferWindowPos<BR>先调用 BeginDeferWindowPos 设定需要移动的窗口的个数<BR>使用DeferWindowPos，来移动窗口，这个API并不真的造成窗口移动<BR>EndDeferWindowPos 一次性完成所有窗口的大小和位置的改变。</P>
<P>有个地方要特别注意，要仔细计算清楚要移动多少个窗口，BeginDeferWindowPos设定<BR>的个数一定要和实际的个数一致，否则在Win9x下，如果实际移动的窗口数多于调用BeginDeferWindowPos<BR>时设定的个数，可能会造成系统崩溃。在Windows NT系列下不会有这样的问题。</P>
<P>如果你在属性里设置了 拖动窗口显示窗口内容的话，屏幕看起来会闪许多。你可以通过api SystemParameters（） ，把它去掉在你的应用程序里。这样在用户看来会好一点。这只是我个人建议。</P>
<P>----------------------------<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、将Invalidate()替换为InvalidateRect()<BR><BR>　　Invalidate()会导致整个窗口的图象重画，需要的时间比较长，而InvalidateRect()仅仅重画Rect区域内的内容，所以所需时间会少一些。虫虫以前很懒，经常为一小块区域的重画就调用Invalidate()，不愿意自己去计算需要重画的Rect，但是事实是，如果你确实需要改善闪烁的情况，计算一个Rect所用的时间比起重画那些不需要重画的内容所需要的时间要少得多。 <BR><BR>　　2、禁止系统搽除你的窗口<BR><BR>　　系统在需要重画窗口的时候会帮你用指定的背景色来搽除窗口。可是，也许需要重画的区域也许非常小。或者，在你重画这些东西之间还要经过大量的计算才能开始。这个时候你可以禁止系统搽掉原来的图象。直到你已经计算好了所有的数据，自己把那些需要搽掉的部分用背景色覆盖掉（如：dc.FillRect(rect,&amp;brush);rect是需要搽除的区域，brush是带背景色的刷子），再画上新的图形。要禁止系统搽除你的窗口，可以重载OnEraseBkgnd()函数，让其直接返回pUE就可以了。如 <BR><BR></P>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
<TBODY>
<TR>
<TD>BOOL CMyWin::OnEraseBkgnd(CDC* pDC) <BR>{ <BR>　return pUE; <BR>　//return CWnd::OnEraseBkgnd(pDC);//把系统原来的这条语句注释掉。 <BR>} </TD></TR></TBODY></TABLE><BR>　　3、有效的进行搽除<BR><BR>　　搽除背景的时候，不要该搽不该搽的地方都搽。比如，你在一个窗口上放了一个很大的Edit框，几乎占了整个窗口，那么你频繁的搽除整个窗口背景将导致Edit不停重画形成剧烈的闪烁。事实上你可以CRgn创建一个需要搽除的区域，只搽除这一部分。如 <BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
<TBODY>
<TR>
<TD>GetClientRect(rectClient); <BR>rgn1.CreateRectRgnIndirect(rectClient); <BR>rgn2.CreateRectRgnIndirect(m_rectEdit); <BR>if(rgn1.CombineRgn(&amp;rgn1,&amp;rgn2,RGN_XOR) == ERROR)//处理后的rgn1只包括了Edit框之外的客户区域，这样，Edit将不会被我的背景覆盖而导致重画。 <BR>{ <BR>　ASSERT(FALSE); <BR>　return ; <BR>} <BR>brush.CreateSolidBrush(m_clrBackgnd); <BR>pDC-&gt;FillRgn(&amp;rgn1,&amp;brush); <BR>brush.DeleteObject(); </TD></TR></TBODY></TABLE><BR>　　注意：在使用这个方法的时候要同时使用方法二。别忘了，到时候又说虫虫的办法不灵。 <BR><BR>　　4、使用MemoryDC先在内存里把图画好，再复制到屏幕上<BR><BR>　　这对于一次画图过程很长的情况比较管用。毕竟内存操作比较快，而且复制到屏幕又是一次性的，至少不会出现可以明显看出一个东东从左画到右的情况。 <BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
<TBODY>
<TR>
<TD>void CMyWin::OnPaint() <BR>{ <BR>　CPaintDC dc1(this); // device context for painting <BR>　dcMemory.CreateCompatibleDC(&amp;dc1); <BR>　CBitmap bmp;//这里的Bitmap是必须的，否则当心弄出一个大黑块哦。 <BR>　bmp.CreateCompatibleBitmap(&amp;dc1,rectClient.Width(),rectClient.Height()); <BR>　dcMemory.SelectObject(&amp;bmp); <BR><BR>　//接下来你想怎么画就怎么画吧。 <BR>　//dcMemory.FillRect(rectClient,&amp;brush); <BR><BR>　dc1.BitBlt(0,0,rectClient.Width(),rectClient.Height(),&amp;dcMemory,0,0,SRCCOPY); <BR>　dcMemory.DeleteDC(); <BR>　// Do not call CWnd::OnPaint() for painting messages <BR>} </TD></TR></TBODY></TABLE><BR>　<B>争议</B><BR><BR>　　上述方法确实有效，但在有很多控件的情况下，计算一个窗口中需要擦除并重绘的“空白区域”是一件很麻烦的事情。为了方便这种方法的实际应用，我写了一组宏来完成”计算空白区域“的功能：<BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
<TBODY>
<TR>
<TD>
<P>/************************************************************************/<BR>/* MFC版<BR>/* 宏功能: 界面刷新时仅刷新指定控件以外的空白区域;可有效避免窗口闪烁<BR>/* 使用于: WM_ERASEBKGND 消息处理函数/************************************************************************/<BR>#define ERASE_BKGND_BEGIN \<BR>CRect bgRect;\<BR>GetClientRect(&amp;bgRect);\<BR>CRgn bgRgn;\<BR>bgRgn.CreateRectRgnIndirect(bgRect);<BR>//#define ERASE_BKGND_BEGIN <BR>// Marco parameter 'IDC' specifies the identifier of the control <BR>#define ADD_NOERASE_CONTROL(IDC)\<BR>{\<BR>　CRect controlRect;\<BR>　GetDlgItem(IDC)-&gt;GetWindowRect(&amp;controlRect);\<BR>　CRgn controlRgn;\<BR>　controlRgn.CreateRectRgnIndirect(controlRect);\<BR>　if(bgRgn.CombineRgn(&amp;bgRgn, &amp;controlRgn, RGN_XOR)==ERROR)\<BR>　　return false;\<BR>}<BR><BR>// Marco parameter 'noEraseRect' specifies a screen coordinates based RECT, <BR>// which needn't erase.<BR>#define ADD_NOERASE_RECT(noEraseRect)\<BR>{\<BR>　CRgn noEraseRgn;\<BR>　noEraseRgn.CreateRectRgnIndirect(noEraseRect);\<BR>　if(bgRgn.CombineRgn(&amp;bgRgn, &amp;noEraseRgn, RGN_XOR)==ERROR)\<BR>　　return false;\<BR>}<BR><BR>// Marco parameter 'pDC' is a kind of (CDC *) type.<BR>// Marco parameter 'clBrushColor' specifies the color to brush the area.<BR>#define ERASE_BKGND_END(pDC, clBrushColor)\<BR>CBrush brush;\<BR>brush.CreateSolidBrush(clBrushColor);\<BR>CPoint saveOrg = (pDC)-&gt;GetWindowOrg();\<BR>(pDC)-&gt;SetWindowOrg(bgRect.TopLeft());\<BR>(pDC)-&gt;FillRgn(&amp;bgRgn, &amp;brush);\<BR>(pDC)-&gt;SetWindowOrg(saveOrg);\<BR>brush.DeleteObject();\<BR>//#define ERASE_BKGND_END<BR>/*************************************************/<BR><BR><BR>/************************************************************************/<BR>/* WTL版<BR>/* 宏功能: 界面刷新时仅刷新指定控件以外的空白区域;可有效避免窗口闪烁<BR>/* 使用于: WM_ERASEBKGND 消息处理函数<BR>/************************************************************************/<BR>#define ERASE_BKGND_BEGIN \<BR>&nbsp;CRect bgRect;\<BR>&nbsp;GetClientRect(&amp;bgRect);\<BR>&nbsp;CRgn bgRgn;\<BR>&nbsp;bgRgn.CreateRectRgnIndirect(bgRect);<BR>//#define ERASE_BKGND_BEGIN <BR>// Marco parameter 'IDC' specifies the identifier of the control <BR>#define ADD_NOERASE_CONTROL(IDC)\<BR>{\<BR>&nbsp;CRect controlRect;\<BR>&nbsp;GetDlgItem(IDC)-&gt;GetWindowRect(&amp;controlRect);\<BR>&nbsp;CRgn controlRgn;\<BR>&nbsp;controlRgn.CreateRectRgnIndirect(controlRect);\<BR>&nbsp;if(bgRgn.CombineRgn(&amp;bgRgn, &amp;controlRgn, RGN_XOR)==ERROR)\<BR>&nbsp;&nbsp;return false;\<BR>}</P>
<P>// Marco parameter 'noEraseRect' specifies a screen coordinates based RECT, <BR>// which needn't erase.<BR>#define ADD_NOERASE_RECT(noEraseRect)\<BR>{\<BR>&nbsp;CRgn noEraseRgn;\<BR>&nbsp;noEraseRgn.CreateRectRgnIndirect(noEraseRect);\<BR>&nbsp;if(bgRgn.CombineRgn(bgRgn.m_hRgn, noEraseRgn.m_hRgn, RGN_XOR)==ERROR)\<BR>&nbsp;&nbsp;return false;\<BR>}</P>
<P>// Marco parameter 'pDC' is a kind of (CDC *) type.<BR>// Marco parameter 'clBrushColor' specifies the color to brush the area.<BR>#define ERASE_BKGND_END(pDC, clBrushColor)\<BR>&nbsp;CBrush brush;\<BR>&nbsp;brush.CreateSolidBrush(clBrushColor);\<BR>&nbsp;CPoint saveOrg;\<BR>&nbsp;(pDC)-&gt;GetWindowOrg(&amp;saveOrg);\<BR>&nbsp;(pDC)-&gt;SetWindowOrg(bgRect.TopLeft());\<BR>&nbsp;(pDC)-&gt;FillRgn(bgRgn.m_hRgn, brush.m_hBrush);\<BR>&nbsp;(pDC)-&gt;SetWindowOrg(saveOrg);\<BR>&nbsp;brush.DeleteObject();\<BR>//#define ERASE_BKGND_END<BR>/*************************************************/<BR></P></TD></TR></TBODY></TABLE><BR>　　说明：<BR><BR>　　1)宏 ERASE_BKGND_BEGIN 和 ERASE_BKGND_END(pDC, clBrushColor) 搭配使用。<BR><BR>　　2)宏 ADD_NOERASE_CONTROL(IDC) 和 ADD_NOERASE_RECT(noEraseRect) 根据需要放在上面两个宏的中间，用来添加不需要重绘背景的区域(正是这些区域导致了闪烁)，使用次数不限。其中参数noEraseRect是一个屏幕坐标系的RECT类型或CRect类型。<BR><BR>　　使用举例1：<BR><BR>　　在当前窗体的类中重写WM_ERASEBKGND消息处理函数如下：<BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
<TBODY>
<TR>
<TD>BOOL CMyWnd::OnEraseBkgnd(CDC* pDC) <BR>{<BR>　ERASE_BKGND_BEGIN;<BR>　ADD_NOERASE_RGN(IDC_BUTTON2);<BR>　ADD_NOERASE_RGN(IDC_BUTTON1);<BR>　ADD_NOERASE_RGN(IDC_LIST_STAT);<BR>　ERASE_BKGND_END(pDC, GetSysColor(COLOR_3DFACE));<BR>　return false;<BR>}</TD></TR></TBODY></TABLE><BR>　　上面的IDC_BUTTON2，IDC_BUTTON1，IDC_LIST_STAT即窗体上的控件。<BR><BR>　　你可以指定其他已存在的控件。<BR><BR>　　这样，窗口在擦除背景时，将只对上述控件以后的”空白区域“使用系统色重绘，有效避免了闪烁。<BR><BR>　　备注：<BR><BR>　　重载WM_ERASEBKGND消息处理函数OnEraseBkgnd的方法，选择View-&gt;ClassWizard-&gt;classinfo选项卡:message filter下拉框:<BR><BR>　　选择window,然后再选择message maps选项卡,在messages下拉框应该可以找到wm_erasebkgnd.双击添加.<BR><BR>　　使用举例2：防止CListCtrl在拉动窗口时闪烁。<BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
<TBODY>
<TR>
<TD>/* * No further full-erasing is required, <BR>* to prevent screen flashing caused by background erase and view repaint. <BR>* Only erase the blank area. <BR>*/<BR><BR>BOOL CExListCtrl::OnEraseBkgnd(CDC* pDC) {<BR>　//compute the holding-data-items area of this list control CRect rect; <BR>　CPoint dataRgnTopLeftPoint; <BR>　CPoint dataRgnBottomRightPoint; <BR>　GetItemPosition(0 , &amp;dataRgnTopLeftPoint); <BR>　GetItemPosition(GetItemCount() , &amp;dataRgnBottomRightPoint); <BR>　if(!GetHeaderCtrl()-&gt;GetItemRect(GetHeaderCtrl()-&gt;GetItemCount()-1, rect)) return <BR>　CListCtrl::OnEraseBkgnd(pDC);<BR>　dataRgnBottomRightPoint.x = rect.right;<BR>　rect.SetRect(dataRgnTopLeftPoint, (CPoint)(dataRgnBottomRightPoint - CPoint(2,2)));<BR>　ClientToScreen(dataRgnRect); <BR>　//compute and erase the blank area. Using the Marco. ERASE_BKGND_BEGIN; <BR>　ADD_NOERASE_RECT(dataRgnRect);<BR>　ERASE_BKGND_END(pDC, GetBkColor());<BR>　return false;<BR>}</TD></TR></TBODY></TABLE><BR>　　说明：CListCtrl在拉动的时候，会前以背景色重刷背景，再在上面绘制有数据的Items， 而没有数据的区域则保持背景色。因此，如果在BOOL CExListCtrl::OnEraseBkgnd(CDC* pDC) 函数中简单的return false，那么没有数据的区域将显示不正常。 故举例2中先计算出有数据的items的区域，这是不需要以背景重刷的区域。 再使用本文的宏，就可以有效避免CListCtrl在拉动时候的闪烁。]]></description>
</item><item>
<title><![CDATA[GetWindowRect、GetClientRect、ScreenToClient与ClientToScreen]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=44420</link>
<author>oceanblue</author>
<pubDate>2009/4/4 11:50:45</pubDate>
<description><![CDATA[GetWindowRect是取得窗口在屏幕坐标系下的RECT坐标（包括客户区和非客户区），这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置。 
<P>GetClientRect取得窗口客户区(不包括非客户区)在客户区坐标系下的RECT坐标,可以得到窗口的大小，而不能得到相对屏幕的位置，因为这个矩阵是在客户区坐标系下（相对于窗口客户区的左上角）的。　　<BR>用GetClientRect返回的RECT结构上左为零, 右下分别对应客户区的宽度和高度;</P>
<P>ScreenToClient把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标. 　　　　<BR>我们对同一个窗口先GetWindowRect取得一个RECT，再用ScreenToClient转换到客户坐标系。<BR>然后GetClientRect取得一个RECT，再用ClientToScreen转换到屏幕坐标系。<BR>显然，GetWindowRect取得的矩阵不小于GetClientRect取得的矩阵。因为前者包含了非客户区，而后包括了客户区。　　　</P>
<P>对GetWindowRect取得的矩阵ScreenToClient后，矩阵的大小没有变小，left,top是窗口的左上角的坐标，相对窗口客户区左上角。　　　</P>
<P>对GetClientRect取得的矩阵ClientToScreen后，矩阵的大小也没有变大，新得到的矩阵是窗口客户区在屏幕坐标系上的RECT。</P>
<P>---------------------------</P>
<P>例：</P>
<P>获取某控件相对于对话框的位置：</P>
<P><FONT face=Arial><FONT face=Arial>CRect rt;</FONT><BR>GetDlgItem(IDC_CB)-&gt;GetWindowRect(rt);&nbsp;&nbsp; //取得在屏幕中的位置<BR>ScreenToClient(rt);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //转换到在对话框中的位置<BR>rt.left和rt.top为该控件在对话框中的位置；<BR><FONT face=Arial>GetDlgItem(IDC_CB)-&gt;SetWindowPos(NULL,rt.left,rt.top,0,0,SWP_NOSIZE);//设置该位置（其实还是在原位置,因为rt.left和rt.top本来就是控件在对话框中的位置，如果要调整控件的位置，修改第二和第三个参数即可</FONT></FONT></P>]]></description>
</item><item>
<title><![CDATA[使用ADO可以访问MySQL，方法如下]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=44328</link>
<author>oceanblue</author>
<pubDate>2009/3/31 21:19:10</pubDate>
<description><![CDATA[<P>使用ADO可以访问MySQL，方法如下： <BR>1、先到MySQL的网站下载MySQL &nbsp; ODBC驱动程序。 <BR>下载地址：http://dev.mysql.com/downloads/connector/odbc/3.51.html <BR>你可以选择 <BR>Windows &nbsp; (x86) &nbsp; MSI &nbsp; Installer &nbsp; &nbsp; 3.51.14 &nbsp; 2.3M &nbsp; 这个选项 <BR>2、安装驱动程序，下载后的文件就是一个msi文件，直接运行即可 <BR>3、打开管理工具--&gt; ODBC数据源，配置一个你需要的ODBC &nbsp; DSN（数据源） <BR>4、使用标准的ADO来进行操作即可。 <BR><BR>不过上面只是如何安装驱动程序。真正要做的还是要求你会使用ADO，因为ADO的用法对于所有的数据库都是一样的。</P>
<P>ADO不提供直接访问mysql数据库的驱动，你需要安装Mysql的驱动。或者安装一个mysql for odbc，设置一个mysql的ODBC驱动，然后用ADO访问ODBC。</P>]]></description>
</item><item>
<title><![CDATA[ADO数据库连接]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=44140</link>
<author>oceanblue</author>
<pubDate>2009/3/25 9:13:20</pubDate>
<description><![CDATA[<A></A>
<P>1、导入库文件</P>
<P>&nbsp;&nbsp; &nbsp;使用ADO前必须在工程的stdafx.h文件最后用直接引入符号＃import引入ADO库文件，以使编译器能正确编译。代码如下：<BR>#import "C:\Program Files\common files\system\ado\msado15.dll" no_namespace rename("EOF","EndOfFile") rename("BOF","FirstOfFile")</P>
<P>&nbsp;ADO类的定义是作为一种资源存储在ADO DLL(msado15.dll）中，在其内部称为类型库。类型库描述了自治接口，以及C＋＋使用的COM vtable接口。当使用＃import指令时，在运行时Visual C＋＋需要从ADO DLL中读取这个类型库，并以此创建一组C＋＋头文件。这些头文件具有.tli 和.tlh扩展名，读者可以在项目的目录下找到这两个文件。在C＋＋程序代码中调用的ADO类要在这些文件中定义。 <BR>&nbsp; 　程序的第三行指示ADO对象不使用名称空间。在有些应用程序中，由于应用程序中的对象与ADO中的对象之间可能会出现命名冲突，所以有必要使用名称空间。如果要使用名称空间，则可把第三行程序修改为： rename_namespace("AdoNS")。第四行代码将ADO中的EOF(文件结束)更名为adoEOF，以避免与定义了自己的EOF的其他库冲突。 </P>
<P><BR>2、初始化COM环境<BR>&nbsp;&nbsp; （1）::CoInitialize(NULL); //初始化OLE/COM库环境<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ::CoUninitialize();//既然初始化了环境，当然就有必要释放他了<BR>&nbsp;&nbsp; （2）也可以调用MFC全局函数<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AfxOleInit();</P>
<P>3、三大对象的定义和创建实例</P>
<P>&nbsp;&nbsp; (1)&nbsp; _ConnectionPtr pConnection("ADODB.Connection");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _RecordsetPtr&nbsp; pRecordset("ADODB.Recordset");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _CommandPtr&nbsp;&nbsp;&nbsp; pCommand("ADODN.Command");</P>
<P>&nbsp;&nbsp; (2) _ConnectionPtr pConnection;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _RecordsetPtr&nbsp; pRecordset;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _CommandPtr&nbsp;&nbsp;&nbsp; pCommand;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pConnection.CreateInstance(__uuidof(Connection));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pRecordset.CreateInstance(__uuidof(Recordset));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pCommand.CreateInstance(__uuidof(Command));</P>
<P>&nbsp;&nbsp; (3) _ConnectionPtr pConnection;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _RecordsetPtr&nbsp; pRecordset;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _CommandPtr&nbsp;&nbsp;&nbsp; pCommand;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pConnection.CreateInstance("ADODB.Connection");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pRecordset.CreateInstance("ADODB.Recordset");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pCommand.CreateInstance("ADODB.Command");</P>
<P>4、打开一个连接<BR>&nbsp; pConnection-&gt;Open(ConnectionString,"","",adModeUnknown);///连接数据库<BR>&nbsp; <BR>&nbsp; 上面的连接字符串ConnectionString根据不同的数据源，分别对应不同的写法<BR>&nbsp; 1）访问Access 2000<BR>&nbsp;&nbsp;&nbsp;&nbsp; "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=databaseName;User ID=userName;Password=userPassWord"</P>
<P>&nbsp; 2)访问ODBC数据<BR>&nbsp;&nbsp; "Provider=MADASQL;DSN=dsnName;UID=userName;PWD=userPassword;"<BR>&nbsp; <BR>&nbsp; 3)访问Oracle数据库<BR>&nbsp;&nbsp;&nbsp; “Provider=MSDAORA;Data Sourse=serverName;User ID=userName;Password=userPassword;"</P>
<P>&nbsp; 3)访问MS SQL数据库<BR>&nbsp;&nbsp; "Provider=SQLOLEDB,Data Source=serverName;Initial Catalog=databaseName;User ID=userName;Password=userPassword;"</P>
<P>4、执行SQL命令<BR>&nbsp;&nbsp; SQL命令比较多，但是不去考虑细节，这里只说出通用的方法<BR>&nbsp;&nbsp; CString strSQL;//定义SQL命令串，用来保存SQL语句</P>
<P>&nbsp;&nbsp; strSQL.Format("SQL statement");</P>
<P>&nbsp;&nbsp; 然后在每个要用到SQL命令串的方法中，使用strSQL.AllocSysString()的方法进行类型转换</P>
<P>5、com的专用数据类型<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp; variant ,bstr ,SafeArray<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp; variant变量的范围包括很多，使用_variant_t 进行管理<BR>&nbsp;&nbsp; bstr是一种字符串变量，使用_bstr_t进行管理<BR>&nbsp;&nbsp; <BR>6、关闭连接<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp; if(m_pConnection-&gt;State)//不能多次关闭，否则会出现错误<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pConnection-&gt;Close(); </P>
<P>7、结构化异常处理<BR>&nbsp;&nbsp; ADO封装了COM接口，所以需要进行错误处理<BR>&nbsp;&nbsp; 如下例：<BR>&nbsp; HRESULT hr;<BR>&nbsp; try<BR>&nbsp; {<BR>&nbsp; hr = m_pConnection.CreateInstance("ADODB.Connection");///创建Connection对象<BR>&nbsp; if(SUCCEEDED(hr))<BR>&nbsp; {<BR>&nbsp; hr = m_pConnection-&gt;Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb","","",adModeUnknown);///连接数据库<BR>&nbsp; ///上面一句中连接字串中的Provider是针对ACCESS2000环境的，对于ACCESS97,需要改为:Provider=Microsoft.Jet.OLEDB.3.51;&nbsp; }<BR>&nbsp; }<BR>&nbsp; catch(_com_error e)///捕捉异常<BR>&nbsp; {<BR>&nbsp; CString errormessage;<BR>&nbsp; errormessage.Format("连接数据库失败!\r\n错误信息:%s",e.ErrorMessage());<BR>&nbsp; AfxMessageBox(errormessage);///显示错误信息<BR>&nbsp; } </P>
<P><BR>8、错误原因的分析<BR>&nbsp;&nbsp; (1)不支持接口，可能是不能插入空值</P>]]></description>
</item><item>
<title><![CDATA[C#：代表（delegate）和事件(event) (转)]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=44078</link>
<author>oceanblue</author>
<pubDate>2009/3/22 21:01:06</pubDate>
<description><![CDATA[
<DIV class=postTitle>&nbsp;</DIV>
<P><STRONG>代表（delegate）：</STRONG></P>
<P>&nbsp;它是C#语言里面的函数指针，代表可以指向某一个函数，在运行的时候调用这个函数的实现。下面来看看它的实现步骤：</P>
<OL>
<LI>声明一个delegate对象。 
<LI>实现和delegate具有相同参数和返回值的函数实现（可以是静态和非静态的）。 
<LI>产生一个delegate对象的时候，把你刚刚实现的函数作为参数传给他的构造函数。 </LI></OL>
<P>请看下面例子：</P>
<P>using System;<BR>using System.Collections.Generic;<BR>using System.Text;</P>
<P>namespace UsingDelegate<BR>{<BR>&nbsp;&nbsp;&nbsp; public delegate void MyDelegate(string mydelegate);//声明一个delegate对象</P>
<P>&nbsp;&nbsp;&nbsp; public class TestClass<BR>&nbsp;&nbsp;&nbsp; {</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //实现有相同参数和返回值的函数<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void HelloDelegate(string mydelegate)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(mydelegate);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //实现有相同参数和返回值的静态函数</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void HelloStaticDelegate(string mystaticdelegate)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(mystaticdelegate);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp; class Program<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TestClass testClass = new TestClass();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate mydelegate = new MyDelegate(testClass.HelloDelegate);//产生delegate对象<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mydelegate("Hello delegate");//调用</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate myStaticDelegate = new MyDelegate(TestClass.HelloStaticDelegate);//产生delegate对象<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myStaticDelegate("Hello static delegate");//调用<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}</P>
<P>&nbsp;</P>
<P><STRONG>事件（event）：</STRONG></P>
<P>让我通过一个例子来模拟事件的整个过程：</P>
<OL>
<LI>创建一个button类，它里面有一个click 事件。 
<LI>创建一个Form类，他里面有一个我们上面定义的button类。 
<LI>要求：当我们用户单击button类的时候From类要对他进行处理，输出一条信息“我知道你被单击了” </LI></OL>
<P>请看下图：</P>
<P><IMG alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/blucexi/未命名1.bmp"></P>
<P>首先我们会单击button，然后button会通知Form，然后From就作出相应。这个过程在C#里面应该怎么做到呢？</P>
<P>下面我会列出上述例子的源代码（这里就不介绍怎么声明event等等内容了）：</P>
<P>using System;<BR>using System.Collections.Generic;<BR>using System.Text;</P>
<P>namespace UsingEvent<BR>{<BR>&nbsp;&nbsp;&nbsp; public delegate void ClickEventHandler(object sender, EventArgs e);//声明一个代表：请看文章最后面Note</P>
<P>&nbsp;&nbsp;&nbsp; public class MyButton&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //创建MyBottom<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public event ClickEventHandler ClickEvent;//声明一个事件</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void Click()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //单击MyButton<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ClickEvent != null)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("MyButton: 我被单击了");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ClickEvent(this, null);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //抛出事件，给所有相应者<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp; public class MyForm<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public MyButton myButton = new MyButton();</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public MyForm()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //添加事件到myButton中，当myButton被单击的时候就会调用相应的处理函数<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myButton.ClickEvent += new ClickEventHandler(OnClickEvent);&nbsp;&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//事件处理函数</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void OnClickEvent(object sender, EventArgs e)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("MyForm: 我知道你被单击了！");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp; class Program<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyForm form = new MyForm();//生成一个MyForm</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; form.myButton.Click();//单击MyForm中的鼠标，效果就出来了<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}<BR>&nbsp;</P>
<P><STRONG>Note</STRONG>：public delegate void ClickEventHandler(object sender, EventArgs e);这是事件委托标准的声明方法，其实在参数里面我们可以不传，也可以是其他类型的。但是最好还是使用上面的声明方法，你可以继承EventArgs，来包装你要传送的其他任何参数。</P>]]></description>
</item><item>
<title><![CDATA[enum类型的本质]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=oceanblue&amp;id=42510</link>
<author>oceanblue</author>
<pubDate>2009/1/17 20:30:58</pubDate>
<description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum类型的本质<BR>&nbsp;&nbsp;&nbsp; 至从C语言开始enum类型就被作为用户自定义分类有限集合常量的方法被引入到了语言<BR>当中，而且一度成为C++中定义编译期常量的唯一方法（后来在类中引入了静态整型常量）。<BR>&nbsp;&nbsp;&nbsp; 根据上面对enum类型的描述，到底enum所定义出来的类型是一个什么样的类型呢？作为<BR>一个用户自定义的类型其所占用的内存空间是多少呢？使用enum类型是否真的能够起到有限<BR>集合常量的边界约束呢？大家可能都知道enum类型和int类型具有隐示（自动）转换的规则，<BR>那么是否真的在任何地方都可以使用enum类型的变量来代替int类型的变量呢？下面会逐一<BR>回答这些问题。<BR>&nbsp;&nbsp;&nbsp; 1. 到底enum所定义出来的类型是一个什么样的类型呢？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在C++中大家都知道仅仅有两种大的类型分类：POD类型和类类型（不清楚的可以参<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 见我的其他文章）。enum所定义的类型其实属于POD类型，也就是说它会参与到POD<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类型的隐示转换规则当中去，所以才会出现enum类型与int类型之间的隐示转换现象。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么也就是说enum所定义的类型不具备名字空间限定能力（因为不属于类类型），<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其所定义的常量子具备和enum类型所在名字空间相同的可见性，由于自身没有名字<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 限定能力，所以会出现名字冲突现象。如：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct CEType<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum EType1 { e1, e2 };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum EType2 { e1, e2 };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面的例子会出现e1、e2名字冲突编译时错误，原因就在于枚举子（e1、e2）是<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CEType名字空间中的名字，同样在引用该CEType中的枚举子时必须采用CEType::e1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样的方式进行，而不是CEType::EType1::e1来进行引用。<BR>&nbsp;&nbsp;&nbsp; 2. 作为一个用户自定义的类型其所占用的内存空间是多少呢？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 该问题就是sizeof( EType1 )等于多少的问题，是不是每一个用户自定义的枚举类<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 型都具有相同的尺寸呢？在大多数的32位编译器下（如：VC++、gcc等）一个枚举类<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 型的尺寸其实就是一个sizeof( int )的大小，难道枚举类型的尺寸真的就应该是int<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类型的尺寸吗？其实不是这样的，在C++标准文档（ISO14882）中并没有这样来定义，<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 标准中是这样说明的：“枚举类型的尺寸是以能够容纳最大枚举子的值的整数的尺寸”，<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同时标准中也说名了：“枚举类型中的枚举子的值必须要能够用一个int类型表述”，<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也就是说，枚举类型的尺寸不能够超过int类型的尺寸，但是是不是必须和int类型<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 具有相同的尺寸呢？上面的标准已经说得很清楚了，只要能够容纳最大的枚举子的<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 值的整数就可以了，那么就是说可以是char、short和int。例如：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum EType1 { e1 = CHAR_MAX };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum EType2 { e2 = SHRT_MAX };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum EType3 { e3 = INT_MAX&nbsp; };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面的三个枚举类型分别可以用char、short、int的内存空间进行表示，也就是：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sizeof( EType1 ) == sizeof( char&nbsp; );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sizeof( EType2 ) == sizeof( short );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sizeof( EType3 ) == sizeof( int&nbsp;&nbsp; );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那为什么在32位的编译器下都会将上面三个枚举类型的尺寸编译成int类型的尺寸呢？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 主要是从32位数据内存对其方面的要求进行考虑的，在某些计算机硬件环境下具有对<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 齐的强制性要求（如：sun SPARC），有些则是因为采用一个完整的32位字长CPU处理<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 效率非常高的原因（如：IA32）。所以不可以简单的假设枚举类型的尺寸就是int类<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 型的尺寸，说不定会遇到一个编译器为了节约内存而采用上面的处理策略。<BR>&nbsp;&nbsp;&nbsp; 3. 使用enum类型是否真的能够起到有限集合常量的边界约束呢？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先看一下下面这个例子：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum EType { e1 = 0, e2 };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void func1( EType e )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( e == e1 )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // do something<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // do something because e != e1 must e == e2<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void func2( EType e )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( e == e1 )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // do something<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if ( e == e2 )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // do something<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; func1( static_cast&lt;EType&gt;( 2&nbsp; ) );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; func2( static_cast&lt;EType&gt;( -1 ) );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面的代码应该很清楚的说明了这样一种异常的情况了，在使用一个操出范围的整<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 型值调用func1函数时会导致函数采取不该采取的行为，而第二个函数可能会好一些<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 他仅仅是忽略了超出范围的值。这就说明枚举所定义的类型并不是一个真正强类型<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 的有限常量集合，这样一种条件下和将上述的两个函数参数声明成为整数类型没有<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 任何差异。所以以后要注意标准定义中枚举类型的陷阱。（其实只有类类型才是真<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正的强类型）<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 4. 是否真的在任何地方都可以使用enum类型的变量来代替int类型的变量呢？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过上面的讨论，其实枚举类型的变量和整型变量具有了太多的一致性和可互换性，<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么是不是在每一个可以使用int类型的地方都可以很好的用枚举类型来替代呢？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实也不是这样的，毕竟枚举类型是一个在编译时可区分的类型，同时第2点的分析<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 枚举类型不一定和int类型具有相同的尺寸，这两个差异就决定了在某些场合是不可<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以使用枚举类型来代替int类型的。如：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一种情况：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum EType { e1 = 0, e2, e3 };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EType val;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cin &gt;&gt; val;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第二种情况：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enum EType { e1 = 0, e2, e3 };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EType val;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::scanf( "%d", &amp;val );<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面的两种情况看是基本上属于同一种类型的问题，其实不然。第一种情况会导致<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编译时错误，会因为std::cin没有定义对应的枚举类型的重载&gt;&gt;运算符而出错，这<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 就说明枚举类型是一种独立和鉴别的类型；而第二种情况不会有任何编译时问题，<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但是可能会导致scanf函数栈被破坏而使得程序运行非法，为什么会这样呢？上面<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 已经分析过了枚举类型变量的尺寸不一定和int类型相同，这样一来我们采用%d就<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是说将枚举类型变量val当作4字节的int变量来看待并进行参数压栈，而在某些编<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 译器下sizeof( val )等于1字节，这样scanf函数就会将val变量地址中的后续的三<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字节地址也压入栈中，并对其进行赋值，也许val变量后续的三个字节的地址没有<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 特殊含义可以被改写（比如是字节对齐的空地址空间），可能会认为他不会出现错<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 误，其实不然，在scanf函数调用结束后会进行栈清理，这样一来会导致scanf函数<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 清理了过多的地址空间，从而破坏了外围函数的栈指针的指向，从而必然会导致程<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 序运行时错误。<BR><BR>&nbsp;&nbsp;&nbsp; 由上面的说明枚举类型有那么多的缺点，那我们怎样才能够有一个类型安全的枚举类型<BR>呢？其实可以采用类类型来模拟枚举类型的有限常量集合的概念，同时得到类型安全的好处，<BR>具体参见后续的文章。]]></description>
</item>
</channel>
</rss>