<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Xu Love Pan &#187; 软件</title>
	<atom:link href="http://xlp1437.me/category/%e8%bd%af%e4%bb%b6/feed/" rel="self" type="application/rss+xml" />
	<link>http://xlp1437.me</link>
	<description>{我只愿守护 由你给我的幸福}</description>
	<lastBuildDate>Thu, 15 Dec 2011 09:16:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2</generator>
		<item>
		<title>软件.{2008-02-14}.{关于CStdioFile写中文出现问题的研究}</title>
		<link>http://xlp1437.me/2008/02/14/%e8%bd%af%e4%bb%b62008-02-14%e5%85%b3%e4%ba%8ecstdiofile%e5%86%99%e4%b8%ad%e6%96%87%e5%87%ba%e7%8e%b0%e9%97%ae%e9%a2%98%e7%9a%84%e7%a0%94%e7%a9%b6/</link>
		<comments>http://xlp1437.me/2008/02/14/%e8%bd%af%e4%bb%b62008-02-14%e5%85%b3%e4%ba%8ecstdiofile%e5%86%99%e4%b8%ad%e6%96%87%e5%87%ba%e7%8e%b0%e9%97%ae%e9%a2%98%e7%9a%84%e7%a0%94%e7%a9%b6/#comments</comments>
		<pubDate>Thu, 14 Feb 2008 20:46:16 +0000</pubDate>
		<dc:creator>烧饼</dc:creator>
				<category><![CDATA[软件]]></category>

		<guid isPermaLink="false">http://www.4ever-memory.com/?p=180</guid>
		<description><![CDATA[今天下定决心,把已经耽搁了很久的某件事情解决掉 本来想用C#的,也练练手,但是工程建着建着就变成MFC了&#8230; 活活,看来我对C++还是很有感情的,那好吧~ 写啊写~花了四个小时,所有功能基本都实现了 唯独一个问题,死活解决不了 &#8211; 往本地硬盘写文件如果字符串中出现中文 该生成的文件由Notepad.exe\UltraEdit32.exe等文件编辑器打开 无法看到中文字符,但是英文字符则可以正确显示 初步判断是由于unicode的问题 GOOGLE了一下,很多反映这个问题的贴子 有些人说把工程设置改为使用多字节字符集(MBCS) 但是我觉得不解决Unicode下很不爽啊&#8230;于是没有采用这种方法 又转悠了一会儿,发现以下说法: [quote] 下代码文件以CStdioFile向无法向文本中写入中文（用notepad.exe查看不到写入的中文） CStdioFile file; file.Open(…); file.WriteString(_T(&#34;abc你好&#34;));//只能写入abc 解决办法： 使用setlocale语句设定区域 #include //头文件 CStdioFile file; file.Open(…); char* old_locale = _strdup( setlocale(LC_CTYPE,NULL) ); setlocale( LC_CTYPE, &#34;chs&#34; );//设定 file.WriteString(_T(&#34;abc你好&#34;));//正常写入 setlocale( LC_CTYPE, old_locale ); free( old_locale );//还原区域设定 简化处理可以仅使用语句setlocale( LC_CTYPE, &#34;chs&#34; ) [/quote] 果然很好使&#8230;希望给碰到这种问题的朋友一个解决方法 具体的原因正在研究中,然后在Codeproject上下了一个拓展CStdioFile的类,继续研究,本文存档&#8230;]]></description>
			<content:encoded><![CDATA[<p>今天下定决心,把已经耽搁了很久的某件事情解决掉<br />
本来想用C#的,也练练手,但是工程建着建着就变成MFC了&#8230;<br />
活活,看来我对C++还是很有感情的,那好吧~<br />
写啊写~花了四个小时,所有功能基本都实现了<br />
唯独一个问题,死活解决不了 &#8211;<br />
往本地硬盘写文件如果字符串中出现中文<br />
该生成的文件由Notepad.exe\UltraEdit32.exe等文件编辑器打开<br />
无法看到中文字符,但是英文字符则可以正确显示<br />
初步判断是由于unicode的问题<br />
GOOGLE了一下,很多反映这个问题的贴子<br />
有些人说把工程设置改为使用多字节字符集(MBCS)<br />
但是我觉得不解决Unicode下很不爽啊&#8230;于是没有采用这种方法<br />
又转悠了一会儿,发现以下说法:</p>
<p>[quote]<br />
下代码文件以CStdioFile向无法向文本中写入中文（用notepad.exe查看不到写入的中文）</p>
<p>CStdioFile file;<br />
file.Open(…);<br />
file.WriteString(_T(&#34;abc你好&#34;));//只能写入abc</p>
<p>解决办法：</p>
<p><strong>使用setlocale语句设定区域</strong></p>
<p>#include <locale>//头文件</p>
<p>CStdioFile file;<br />
file.Open(…);</p>
<p>char* old_locale = _strdup( setlocale(LC_CTYPE,NULL) );<br />
setlocale( LC_CTYPE, &#34;chs&#34; );//设定</p>
<p>file.WriteString(_T(&#34;abc你好&#34;));//正常写入</p>
<p>setlocale( LC_CTYPE, old_locale );</p>
<p>free( old_locale );//还原区域设定</p>
<p>简化处理可以仅使用语句setlocale( LC_CTYPE, &#34;chs&#34; )</p>
<p><原文出处:http://www.cnblogs.com/yoyolion/archive/2007/05/23/756643.html><br />
[/quote]</p>
<p>果然很好使&#8230;希望给碰到这种问题的朋友一个解决方法<br />
具体的原因正在研究中,然后在Codeproject上下了一个拓展CStdioFile的类,继续研究,本文存档&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://xlp1437.me/2008/02/14/%e8%bd%af%e4%bb%b62008-02-14%e5%85%b3%e4%ba%8ecstdiofile%e5%86%99%e4%b8%ad%e6%96%87%e5%87%ba%e7%8e%b0%e9%97%ae%e9%a2%98%e7%9a%84%e7%a0%94%e7%a9%b6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>狙杀Autorun.inf和soundmix.exe</title>
		<link>http://xlp1437.me/2007/01/13/%e7%8b%99%e6%9d%80autoruninf%e5%92%8csoundmixexe/</link>
		<comments>http://xlp1437.me/2007/01/13/%e7%8b%99%e6%9d%80autoruninf%e5%92%8csoundmixexe/#comments</comments>
		<pubDate>Sat, 13 Jan 2007 18:11:30 +0000</pubDate>
		<dc:creator>烧饼</dc:creator>
				<category><![CDATA[软件]]></category>

		<guid isPermaLink="false">http://www.4ever-memory.com/?p=59</guid>
		<description><![CDATA[印象中自己是一个很懒的人,不怎么喜欢摸索,就算摸索了也不怎么发什么原创的和技术哪怕有一点点关系的贴子,今天就来破一个例,希望以后自己能常常摸索出能以发他为自豪的贴子~~ 首先说说,大家都知道,最近U盘病毒那叫一个猖獗啊&#8230;.凡是在打印店打过的U盘,没有一个不中毒的&#8230;.而这些毒变种又多,再加上国际光缆还是没有修好,导致目前很多病毒的肆虐(比如说很牛X的熊猫烧香),而一些不起眼的小毒(比如我们这篇要说的soundmix.exe和autorun.inf)也是请神容易送神难~ 症状: 常见的症状就是U盘目录下有一个隐藏文件:Autorun.inf,一个隐藏文件夹Recycled(内含一个隐藏文件autorun.exe).格式化U盘删除autorun.inf后又会自动生成.同时,用户无法勾选&#34;工具 -> 文件夹选项 -> &#39;查看&#34;选项卡中的&#39;显示所有文件和文件夹&#34;,一点确定完病毒自动将其设置为&#34;不显示隐藏文件和文件夹&#34;.另外,在任务管理器中会发现一个soundmix.exe进程,无法结束(表现为结束后过一段时间自动加载).最后,U盘上有指示灯的朋友会发现指示灯每隔一段时间会闪一下. 分析: 我们先从最容易分析的指示灯开始.指示灯亮说明了不断的有程序在读写U盘,那么,我们就要借助下面的一个软件:FileMon,来实时监测到底什么软件在读写U盘. [quote] 具体操作很简单,首先在分区菜单项中选定要监测的分区,然后用工具栏上的&#34;捕获事件&#34;按钮(或在菜单项&#34;文件&#34;上,或使用键Ctrl+E),一会儿就会出来结果,到底是什么东西在访问U盘 23:33:11 soundmix.exe:2824 Cr&#101;ate N:\RECYCLER\ NAME COLLISION Options: Cr&#101;ate Directory Access: 00100001 23:33:11 soundmix.exe:2824 Cr&#101;ate N:\RECYCLER\autorun.exe NAME COLLISION Options: Cr&#101;ate Sequential Access: 00130196 23:33:11 soundmix.exe:2824 OPEN N:\autorun.inf SUCCESS Options: Open Access: 00100100 23:33:11 soundmix.exe:2824 SET INFORMATION N:\autorun.inf SUCCESS FileBasicInformation 23:33:11 soundmix.exe:2824 WRITE N: SUCCESS [...]]]></description>
			<content:encoded><![CDATA[<p>印象中自己是一个很懒的人,不怎么喜欢摸索,就算摸索了也不怎么发什么原创的和技术哪怕有一点点关系的贴子,今天就来破一个例,希望以后自己能常常摸索出能以发他为自豪的贴子~~</p>
<p>首先说说,大家都知道,最近U盘病毒那叫一个猖獗啊&#8230;.凡是在打印店打过的U盘,没有一个不中毒的&#8230;.而这些毒变种又多,再加上国际光缆还是没有修好,导致目前很多病毒的肆虐(比如说很牛X的熊猫烧香),而一些不起眼的小毒(比如我们这篇要说的soundmix.exe和autorun.inf)也是请神容易送神难~</p>
<p><strong>症状</strong>:<br />
常见的症状就是U盘目录下有一个隐藏文件:Autorun.inf,一个隐藏文件夹Recycled(内含一个隐藏文件autorun.exe).格式化U盘删除autorun.inf后又会自动生成.同时,用户无法勾选&#34;工具 -> 文件夹选项 -> &#39;查看&#34;选项卡中的&#39;显示所有文件和文件夹&#34;,一点确定完病毒自动将其设置为&#34;不显示隐藏文件和文件夹&#34;.另外,在任务管理器中会发现一个soundmix.exe进程,无法结束(表现为结束后过一段时间自动加载).最后,U盘上有指示灯的朋友会发现指示灯每隔一段时间会闪一下.</p>
<p><strong>分析</strong>:<br />
我们先从最容易分析的指示灯开始.指示灯亮说明了不断的有程序在读写U盘,那么,我们就要借助下面的一个软件:<a target="_blank" href="http://www.crsky.com/soft/1779.html">FileMon</a>,来实时监测到底什么软件在读写U盘.</p>
<p>[quote]<br />
具体操作很简单,首先在分区菜单项中选定要监测的分区,然后用工具栏上的&#34;捕获事件&#34;按钮(或在菜单项&#34;文件&#34;上,或使用键Ctrl+E),一会儿就会出来结果,到底是什么东西在访问U盘</p>
<p>23:33:11	soundmix.exe:2824	Cr&#101;ate	N:\RECYCLER\	NAME COLLISION	Options: Cr&#101;ate Directory  Access: 00100001<br />
23:33:11	soundmix.exe:2824	Cr&#101;ate	N:\RECYCLER\autorun.exe	NAME COLLISION	Options: Cr&#101;ate Sequential  Access: 00130196<br />
23:33:11	soundmix.exe:2824	OPEN	N:\autorun.inf	SUCCESS	Options: Open  Access: 00100100<br />
23:33:11	soundmix.exe:2824	SET INFORMATION 	N:\autorun.inf	SUCCESS	FileBasicInformation<br />
23:33:11	soundmix.exe:2824	WRITE 	N:	SUCCESS	Offset: 0 Length: 4096<br />
23:33:11	soundmix.exe:2824	CLOSE	N:\autorun.inf	SUCCESS<br />
23:33:11	soundmix.exe:2824	WRITE 	N:	SUCCESS	Offset: 0 Length: 4096<br />
23:33:11	soundmix.exe:2824	Cr&#101;ate	N:\autorun.inf	SUCCESS	Options: OverwriteIf  Access: 00120196<br />
23:33:11	soundmix.exe:2824	WRITE 	N:	SUCCESS	Offset: 0 Length: 4096<br />
23:33:11	soundmix.exe:2824	WRITE 	N:	SUCCESS	Offset: 0 Length: 4096<br />
23:33:11	soundmix.exe:2824	WRITE 	N:\autorun.inf	SUCCESS	Offset: 0 Length: 201<br />
23:33:11	soundmix.exe:2824	WRITE 	N:	SUCCESS	Offset: 0 Length: 4096<br />
23:33:12	soundmix.exe:2824	WRITE 	N:	SUCCESS	Offset: 0 Length: 4096<br />
23:33:12	soundmix.exe:2824	CLOSE	N:\autorun.inf	SUCCESS<br />
23:33:12	soundmix.exe:2824	WRITE 	N:	SUCCESS	Offset: 0 Length: 4096<br />
23:33:12	soundmix.exe:2824	WRITE 	N:\autorun.inf	SUCCESS	Offset: 0 Length: 4096<br />
23:33:12	Mcshield.exe:1876	OPEN	N:\autorun.inf	SUCCESS	Options: Open  Access: 00120180<br />
23:33:12	Mcshield.exe:1876	QUERY INFORMATION	N:\autorun.inf	SUCCESS	FileBasicInformation<br />
23:33:12	Mcshield.exe:1876	SET INFORMATION 	N:\autorun.inf	SUCCESS	FileBasicInformation<br />
23:33:12	Mcshield.exe:1876	QUERY INFORMATION	N:\autorun.inf	SUCCESS	FileStandardInformation<br />
23:33:12	Mcshield.exe:1876	CLOSE	N:\autorun.inf	SUCCESS<br />
23:33:12	Mcshield.exe:1876	OPEN	N:\autorun.inf	SUCCESS	Options: Open  Access: 00120180<br />
23:33:12	Mcshield.exe:1876	SET INFORMATION 	N:\autorun.inf	SUCCESS	FileBasicInformation<br />
23:33:12	Mcshield.exe:1876	QUERY INFORMATION	N:\autorun.inf	SUCCESS	FileStandardInformation<br />
23:33:12	Mcshield.exe:1876	CLOSE	N:\autorun.inf	SUCCESS<br />
23:33:12	Mcshield.exe:1876	OPEN	N:\autorun.inf	SUCCESS	Options: Open  Access: 00120181<br />
23:33:12	Mcshield.exe:1876	SET INFORMATION 	N:\autorun.inf	SUCCESS	FileBasicInformation<br />
23:33:12	Mcshield.exe:1876	READ 	N:\autorun.inf	SUCCESS	Offset: 0 Length: 8192<br />
23:33:12	Mcshield.exe:1876	CLOSE	N:\autorun.inf	SUCCESS<br />
23:33:12	Mcshield.exe:1876	OPEN	N:\autorun.inf	SUCCESS	Options: Open  Access: 00120180<br />
23:33:12	Mcshield.exe:1876	SET INFORMATION 	N:\autorun.inf	SUCCESS	FileBasicInformation<br />
23:33:12	Mcshield.exe:1876	QUERY INFORMATION	N:\autorun.inf	SUCCESS	FileBasicInformation<br />
23:33:12	Mcshield.exe:1876	CLOSE	N:\autorun.inf	SUCCESS</p>
<p>从上面的日志中我们可以看到soundmix.exe在不停的Cr&#101;ate然后Write文件到U盘,这就是U盘指示灯不停闪以及格式化U盘删除autorun.inf后又会自动生成的原因了.<br />
[/quote]</p>
<p>找到原因是soundmix.exe引起的,那么就要想办法解决这个罪魁祸首了,可是,这时候,我发现,无论用什么东西,都是结束这个进程后他又会自动启动.进入安全模式也一样,这就奇怪了,难道是什么东西调用了他?</p>
<p>当时还以为是rundll32加载了这个模块,然后在执行了regsvr32 /u soundmix.dll后提示找不到模块,那么会是什么原因呢~~在搜了一番注册表后发现了问题&#8230;</p>
<p>[quote]<br />
注册表的以下两个路径:<br />
HKEY_CLASSES_ROOT\exefile\shell\open\command<br />
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\exefile\shell\open\command</p>
<p>的exefile键值都已经被改为soundmix &#34;%1&#34; %*</p>
<p>问题找到了,原来他擅自更改了系统EXE的关联,那么一旦运行exe就会自动运行soundmix.exe了,难怪我们一直结束不了它&#8230;<br />
[/quote]</p>
<p>这时候,删除它的唯一方法就是进入DOS下了,可是我的机器上没有软驱,无法使用启动盘,怎么办呢?~~突然,我想到了XP安装盘自带的故障控制修复台,那时候尚未加载系统,系统的EXE关联一定不会影响到我们的操作,说干就干,拿出了安装盘,进入了故障控制修复台,本来还想是不是可以直接用ftype(一个命令行下修改文件关联的命令),结果发现不行&#8230;于是用help查询了一下支持的命令,发现了del&#101;te,OK,就用它了~~把%windir%\system32下的soundmix.exe直接删除掉,回到系统,这时候关联已经被破坏,不能直接运行regedit.exe,方法就是把exe改为com,这样就可以运行了.到上述的两个路径下将键值恢复为:&#34;%1&#34; %*,这样exe的关联就恢复了,可是,你会发现,&#34;显示所有文件和文件夹&#34;仍然无法选定,这个就简单了,进入路径:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Hidden\SHOWALL,把CheckedValue改成1即可(注意这里有的病毒会把CheckedValue的类型改在REG_SZ,而我们需要的是REG_DWORD,方法就是删除后自己新建一个即可).最后,格式化U盘,至此,这个病毒彻底滚了~~</p>
<p><strong>小结</strong><br />
一个小病毒也这么麻烦&#8230;.实在是~~不过这个病毒让我学到了不少知识,比如,使用filemon监测磁盘读写,使用ftype查看文件关联,还有一些常用的注册表键值所在路径等~~果然摸索还是有意思滴~~</p>
<p><strong>核心步骤</strong><br />
用任何可以不加载系统就进入命令行(如DOS启动盘或者从光盘启动进入DOS或者故障控制修复台),之后应该要首先去掉soundmix.exe的各种属性:attrib -s -h soundmix.exe,尤其是这个-s,它标识了soundmix.exe是一个系统文件,如果不去掉的话将无法使用del&#101;te(或者del)命令删除,然后就是恢复EXE文件的关联和将显示隐藏文件的注册表项改回来.</p>
<p>希望这些对大家删除这两个该死的讨厌的东西有用~~</p>
<p>最后,希望大家百毒不侵哈~~平时做好预防工作还是比什么都重要~~</p>
]]></content:encoded>
			<wfw:commentRss>http://xlp1437.me/2007/01/13/%e7%8b%99%e6%9d%80autoruninf%e5%92%8csoundmixexe/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>CString 操作指南</title>
		<link>http://xlp1437.me/2007/01/02/cstring-%e6%93%8d%e4%bd%9c%e6%8c%87%e5%8d%97/</link>
		<comments>http://xlp1437.me/2007/01/02/cstring-%e6%93%8d%e4%bd%9c%e6%8c%87%e5%8d%97/#comments</comments>
		<pubDate>Tue, 02 Jan 2007 14:24:01 +0000</pubDate>
		<dc:creator>烧饼</dc:creator>
				<category><![CDATA[软件]]></category>

		<guid isPermaLink="false">http://www.4ever-memory.com/?p=56</guid>
		<description><![CDATA[[b]CString 操作指南 [/b] 原著：Joseph M. Newcomer 翻译： littleloach 原文出处： codeproject：CString Management 通过阅读本文你可以学习如何有效地使用 CString。 　　CString 是一种很有用的数据类型。它们很大程度上简化了MFC中的许多操作，使得MFC在做字符串操作的时候方便了很多。不管怎样，使用CString有很多特殊的技巧，特别是对于纯C背景下走出来的程序员来说有点难以学习。这篇文章就来讨论这些技巧。 　　使用CString可以让你对字符串的操作更加直截了当。这篇文章不是CString的完全手册，但囊括了大部分常见基本问题。 下面我分别讨论。 1、CString 对象的连接 　　能体现出 CString 类型方便性特点的一个方面就字符串的连接，使用 CString 类型，你能很方便地连接两个字符串，正如下面的例子：CString gray(&#34;Gray&#34;);CString cat(&#34;Cat&#34;);CString graycat = gray + cat; 要比用下面的方法好得多：char gray[] = &#34;Gray&#34;;char cat[] = &#34;Cat&#34;;char * graycat = malloc(strlen(gray) + strlen(cat) + 1);strcpy(graycat, gray);strcat(graycat, cat); 2、格式化字符串 　　与其用 sprintf() 函数或 wsprintf() 函数来格式化一个字符串，还不如用 CString [...]]]></description>
			<content:encoded><![CDATA[<p>[b]CString 操作指南<br />
[/b]<br />
原著：Joseph M. Newcomer<br />
翻译：<br />
<a target="_blank" href="mailto:littleloach@sina.com">littleloach</a><br />
原文出处：<br />
<a target="_blank" href="http://www.codeproject.com/string/cstringmgmt.asp">codeproject：CString Management</a><br />
通过阅读本文你可以学习如何有效地使用 CString。<br />
　　CString 是一种很有用的数据类型。它们很大程度上简化了MFC中的许多操作，使得MFC在做字符串操作的时候方便了很多。不管怎样，使用CString有很多特殊的技巧，特别是对于纯C背景下走出来的程序员来说有点难以学习。这篇文章就来讨论这些技巧。<br />
　　使用CString可以让你对字符串的操作更加直截了当。这篇文章不是CString的完全手册，但囊括了大部分常见基本问题。</p>
<p>下面我分别讨论。<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 1、<strong>CString 对象的连接</strong><br />
　　能体现出 CString 类型方便性特点的一个方面就字符串的连接，使用 CString 类型，你能很方便地连接两个字符串，正如下面的例子：CString gray(&#34;Gray&#34;);CString cat(&#34;Cat&#34;);CString graycat = gray + cat;<br />
要比用下面的方法好得多：char gray[] = &#34;Gray&#34;;char cat[] = &#34;Cat&#34;;char * graycat = malloc(strlen(gray) + strlen(cat) + 1);strcpy(graycat, gray);strcat(graycat, cat);<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 2、<strong>格式化字符串</strong><br />
　　与其用 sprintf() 函数或 wsprintf() 函数来格式化一个字符串，还不如用 CString 对象的Format()方法：CString s;s.Format(_T(&#34;The total is %d&#34;), total);<br />
　　用这种方法的好处是你不用担心用来存放格式化后数据的缓冲区是否足够大，这些工作由CString类替你完成。<br />
　　格式化是一种把其它不是字符串类型的数据转化为CString类型的最常用技巧，比如，把一个整数转化成CString类型，可用如下方法：CString s;s.Format(_T(&#34;%d&#34;), total);<br />
　　我总是对我的字符串使用_T()宏，这是为了让我的代码至少有Unicode的意识，当然，关于Unicode的话题不在这篇文章的讨论范围。_T()宏在8位字符环境下是如下定义的：#define _T(x) x // 非Unicode版本（non-Unicode version）<br />
而在Unicode环境下是如下定义的：#define _T(x) L##x // Unicode版本（Unicode version）<br />
所以在Unicode环境下，它的效果就相当于：s.Format(L&#34;%d&#34;, total);<br />
　　如果你认为你的程序可能在Unicode的环境下运行，那么开始在意用 Unicode 编码。比如说，不要用 sizeof() 操作符来获得字符串的长度，因为在Unicode环境下就会有2倍的误差。我们可以用一些方法来隐藏Unicode的一些细节，比如在我需要获得字符长度的时候，我会用一个叫做DIM的宏，这个宏是在我的dim.h文件中定义的，我会在我写的所有程序中都包含这个文件：#define DIM(x) ( sizeof((x)) / sizeof((x)[0]) )　　这个宏不仅可以用来解决Unicode的字符串长度的问题，也可以用在编译时定义的表格上，它可以获得表格的项数，如下：<br />
class Whatever { &#8230; };Whatever data[] = {   { &#8230; },    &#8230;   { &#8230; },};for(int i = 0; i 　　这里要提醒你的就是一定要注意那些在参数中需要真实字节数的API函数调用，如果你传递字符个数给它，它将不能正常工作。如下：TCHAR data[20];lstrcpyn(data, longstring, sizeof(data) &#8211; 1); // WRONG!lstrcpyn(data, longstring, DIM(data) &#8211; 1); // RIGHTWriteFile(f, data, DIM(data), &amp;bytesWritten, NULL); // WRONG!WriteFile(f, data, sizeof(data), &amp;bytesWritten, NULL); // RIGHT<br />
造成以上原因是因为lstrcpyn需要一个字符个数作为参数，但是WriteFile却需要字节数作为参数。<br />
同样需要注意的是有时候需要写出数据的所有内容。如果你仅仅只想写出数据的真实长度，你可能会认为你应该这样做：WriteFile(f, data, lstrlen(data), &amp;bytesWritten, NULL); // WRONG<br />
但是在Unicode环境下，它不会正常工作。正确的做法应该是这样：WriteFile(f, data, lstrlen(data) * sizeof(TCHAR), &amp;bytesWritten, NULL); // RIGHT<br />
　　因为WriteFile需要的是一个以字节为单位的长度。（可能有些人会想“在非Unicode的环境下运行这行代码，就意味着总是在做一个多余的乘1操作，这样不会降低程序的效率吗？”这种想法是多余的，你必须要了解编译器实际上做了什么，没有哪一个C或C++编译器会把这种无聊的乘1操作留在代码中。在Unicode环境下运行的时候，你也不必担心那个乘2操作会降低程序的效率，记住，这只是一个左移一位的操作而已，编译器也很乐意为你做这种替换。）<br />
　　使用_T宏并不是意味着你已经创建了一个Unicode的程序，你只是创建了一个有Unicode意识的程序而已。如果你在默认的8-bit模式下编译你的程序的话，得到的将是一个普通的8-bit的应用程序（这里的8-bit指的只是8位的字符编码，并不是指8位的计算机系统）；当你在Unicode环境下编译你的程序时，你才会得到一个Unicode的程序。记住，CString 在 Unicode 环境下，里面包含的可都是16位的字符哦。<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 3、<strong>CString 型转化成 int 型</strong><br />
　　把 CString 类型的数据转化成整数类型最简单的方法就是使用标准的字符串到整数转换例程。<br />
　　虽然通常你怀疑使用_atoi()函数是一个好的选择，它也很少会是一个正确的选择。如果你准备使用 Unicode 字符，你应该用_ttoi()，它在 ANSI 编码系统中被编译成_atoi()，而在 Unicode 编码系统中编译成_wtoi()。你也可以考虑使用_tcstoul()或者_tcstol()，它们都能把字符串转化成任意进制的长整数（如二进制、八进制、十进制或十六进制），不同点在于前者转化后的数据是无符号的（unsigned），而后者相反。看下面的例子：CString hex = _T(&#34;FAB&#34;);CString decimal = _T(&#34;4011&#34;);ASSERT(_tcstoul(hex, 0, 16) == _ttoi(decimal));<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 4、<strong>CString 型和 char* 类型的相互转化</strong><br />
　　这是初学者使用 CString 时最常见的问题。有了 C++ 的帮助，很多问题你不需要深入的去考虑它，直接拿来用就行了，但是如果你不能深入了解它的运行机制，又会有很多问题让你迷惑，特别是有些看起来没有问题的代码，却偏偏不能正常工作。<br />
比如，你会奇怪为什么不能写向下面这样的代码呢：CString graycat = &#34;Gray&#34; + &#34;Cat&#34;;<br />
或者这样：CString graycat(&#34;Gray&#34; + &#34;Cat&#34;);<br />
　　事实上，编译器将抱怨上面的这些尝试。为什么呢？因为针对CString 和 LPCTSTR数据类型的各种各样的组合，“ +” 运算符 被定义成一个重载操作符。而不是两个 LPCTSTR 数据类型，它是底层数据类型。你不能对基本数据（如 int、char 或者 char*）类型重载 C++ 的运算符。你可以象下面这样做：CString graycat = CString(&#34;Gray&#34;) + CString(&#34;Cat&#34;);<br />
或者这样：CString graycat = CString(&#34;Gray&#34;) + &#34;Cat&#34;;<br />
研究一番就会发现：“ +”总是使用在至少有一个 CString 对象和一个 LPCSTR 的场合。<br />
注意，编写有 Unicode 意识的代码总是一件好事，比如：CString graycat = CString(_T(&#34;Gray&#34;)) + _T(&#34;Cat&#34;);<br />
这将使得你的代码可以直接移植。<br />
<i><strong>char* 转化为 CString</strong></i><br />
　　现在你有一个 char* 类型的数据，或者说一个字符串。怎么样创建 CString 对象呢？这里有一些例子：char * p = &#34;This is a test&#34;;<br />
或者象下面这样更具有 Unicode 意识：TCHAR * p = _T(&#34;This is a test&#34;)<br />
或LPTSTR p = _T(&#34;This is a test&#34;);<br />
你可以使用下面任意一种写法：CString s = &#34;This is a test&#34;; // 8-bit onlyCString s = _T(&#34;This is a test&#34;); // Unicode-awareCString s(&#34;This is a test&#34;); // 8-bit onlyCString s(_T(&#34;This is a test&#34;)); // Unicode-awareCString s = p;CString s(p);<br />
　　用这些方法可以轻松将常量字符串或指针转换成 CString。需要注意的是，字符的赋值总是被拷贝到 CString 对象中去的，所以你可以象下面这样操作：TCHAR * p = _T(&#34;Gray&#34;);CString s(p);p = _T(&#34;Cat&#34;);s += p;<br />
结果字符串肯定是“GrayCat”。<br />
CString 类还有几个其它的构造函数，但是这里我们不考虑它，如果你有兴趣可以自己查看相关文档。<br />
事实上，CString 类的构造函数比我展示的要复杂，比如：CString s = &#34;This is a test&#34;;<br />
　　这是很草率的编码，但是实际上它在 Unicode 环境下能编译通过。它在运行时调用构造函数的 MultiByteToWideChar 操作将 8 位字符串转换成 16 位字符串。不管怎样，如果 char * 指针是网络上传输的 8 位数据，这种转换是很有用的。<br />
<i><strong>CString 转化成 char* 之一：</strong></i>强制类型转换为 LPCTSTR；<br />
　　这是一种略微硬性的转换，有关“正确”的做法，人们在认识上还存在许多混乱，正确的使用方法有很多，但错误的使用方法可能与正确的使用方法一样多。<br />
　　我们首先要了解 CString 是一种很特殊的 C++ 对象，它里面包含了三个值：一个指向某个数据缓冲区的指针、一个是该缓冲中有效的字符记数以及一个缓冲区长度。 有效字符数的大小可以是从0到该缓冲最大长度值减1之间的任何数（因为字符串结尾有一个NULL字符）。字符记数和缓冲区长度被巧妙隐藏。<br />
　　除非你做一些特殊的操作，否则你不可能知道给CString对象分配的缓冲区的长度。这样，即使你获得了该0缓冲的地址，你也无法更改其中的内容，不能截短字符串，也 绝对没有办法加长它的内容，否则第一时间就会看到溢出。<br />
　　LPCTSTR 操作符（或者更明确地说就是 TCHAR * 操作符）在 CString 类中被重载了，该操作符的定义是返回缓冲区的地址，因此，如果你需要一个指向 CString 的 字符串指针的话，可以这样做：<br />
CString s(&#34;GrayCat&#34;);LPCTSTR p = s;<br />
　　它可以正确地运行。这是由C语言的强制类型转化规则实现的。当需要强制类型转化时，C++规测容许这种选择。比如，你可以将（浮点数）定义为将某个复数 （有一对浮点数）进行强制类型转换后只返回该复数的第一个浮点数（也就是其实部）。可以象下面这样：Complex c(1.2f, 4.8f);float realpart = c;<br />
如果(float)操作符定义正确的话，那么实部的的值应该是1.2。<br />
　　这种强制转化适合所有这种情况，例如，任何带有 LPCTSTR 类型参数的函数都会强制执行这种转换。 于是，你可能有这样一个函数（也许在某个你买来的DLL中）：BOOL DoSomethingCool(LPCTSTR s);<br />
你象下面这样调用它：CString file(&#34;c:\\myfiles\\coolstuff&#34;)BOOL result = DoSomethingCool(file);<br />
　　它能正确运行。因为 DoSomethingCool 函数已经说明了需要一个 LPCTSTR 类型的参数，因此 LPCTSTR 被应用于该参数，在 MFC 中就是返回的串地址。<br />
如果你要格式化字符串怎么办呢？CString graycat(&#34;GrayCat&#34;);CString s;s.Format(&#34;Mew! I love %s&#34;, graycat);<br />
　　注意由于在可变参数列表中的值（在函数说明中是以“&#8230;”表示的）并没有隐含一个强制类型转换操作符。你会得到什么结果呢？<br />
　　一个令人惊讶的结果，我们得到的实际结果串是：&#34;Mew! I love GrayCat&#34;。<br />
　　因为 MFC 的设计者们在设计 CString 数据类型时非常小心， CString 类型表达式求值后指向了字符串，所以这里看不到任何象 Format 或 sprintf 中的强制类型转换，你仍然可以得到正确的行为。描述 CString 的附加数据实际上在 CString 名义地址之后。<br />
　　有一件事情你是不能做的，那就是修改字符串。比如，你可能会尝试用“,”代替“.”（不要做这样的，如果你在乎国际化问题，你应该使用十进制转换的 National Language Support 特性，），下面是个简单的例子：CString v(&#34;1.00&#34;); // 货币金额，两位小数LPCTSTR p = v;p[lstrlen(p) - 3] = &#39;&#39;,&#39;&#39;;<br />
　　这时编译器会报错，因为你赋值了一个常量串。如果你做如下尝试，编译器也会错：strcat(p, &#34;each&#34;);<br />
　　因为 strcat 的第一个参数应该是 LPTSTR 类型的数据，而你却给了一个 LPCTSTR。<br />
　　不要试图钻这个错误消息的牛角尖，这只会使你自己陷入麻烦！<br />
　　原因是缓冲有一个计数，它是不可存取的（它位于 CString 地址之下的一个隐藏区域），如果你改变这个串，缓冲中的字符计数不会反映所做的修改。此外，如果字符串长度恰好是该字符串物理限制的长度（梢后还会讲到这个问题），那么扩展该字符串将改写缓冲以外的任何数据，那是你无权进行写操作的内存（不对吗？），你会毁换坏不属于你的内存。这是应用程序真正的死亡处方。<br />
<i><strong>CString转化成char* 之二：</strong></i>使用 CString 对象的 GetBuffer 方法；<br />
　　如果你需要修改 CString 中的内容，它有一个特殊的方法可以使用，那就是 GetBuffer，它的作用是返回一个可写的缓冲指针。 如果你只是打算修改字符或者截短字符串，你完全可以这样做：CString s(_T(&#34;File.ext&#34;));LPTSTR p = s.GetBuffer();LPTSTR dot = strchr(p, &#39;&#39;.&#39;&#39;); // OK, should have used s.Find&#8230;if(p != NULL)*p = _T(&#39;&#39;\0&#39;&#39;);s.ReleaseBuffer();<br />
　　这是 GetBuffer 的第一种用法，也是最简单的一种，不用给它传递参数，它使用默认值 0，意思是：“给我这个字符串的指针，我保证不加长它”。当你调用 ReleaseBuffer 时，字符串的实际长度会被重新计算，然后存入 CString 对象中。<br />
　　必须强调一点，在 GetBuffer 和 ReleaseBuffer 之间这个范围，一定不能使用你要操作的这个缓冲的 CString 对象的任何方法。因为 ReleaseBuffer 被调用之前，该 CString 对象的完整性得不到保障。研究以下代码：CString s(&#8230;);LPTSTR p = s.GetBuffer();//&#8230; 这个指针 p 发生了很多事情int n = s.GetLength(); // 很糟D!!!!! 有可能给出错误的答案!!!s.TrimRight(); // 很糟!!!!! 不能保证能正常工作!!!!s.ReleaseBuffer(); // 现在应该 OKint m = s.GetLength(); // 这个结果可以保证是正确的。s.TrimRight(); // 将正常工作。<br />
　　假设你想增加字符串的长度，你首先要知道这个字符串可能会有多长，好比是声明字符串数组的时候用：char buffer[1024];<br />
表示 1024 个字符空间足以让你做任何想做得事情。在 CString 中与之意义相等的表示法：LPTSTR p = s.GetBuffer(1024);<br />
　　调用这个函数后，你不仅获得了字符串缓冲区的指针，而且同时还获得了长度至少为 1024 个字符的空间（注意，我说的是“字符”，而不是“字节”，因为 CString 是以隐含方式感知 Unicode 的）。<br />
　　同时，还应该注意的是，如果你有一个常量串指针，这个串本身的值被存储在只读内存中，如果试图存储它，即使你已经调用了 GetBuffer ，并获得一个只读内存的指针，存入操作会失败，并报告存取错误。我没有在 CString 上证明这一点，但我看到过大把的 C 程序员经常犯这个错误。<br />
　　C 程序员有一个通病是分配一个固定长度的缓冲，对它进行 sprintf 操作，然后将它赋值给一个 CString：char buffer[256];sprintf(buffer, &#34;%&#8230;&#8230;&#34;, args, &#8230;); // &#8230; 部分省略许多细节CString s = buffer;<br />
虽然更好的形式可以这么做：CString s;s.Format(_T(&#34;%&#8230;.&#34;), args, &#8230;);<br />
如果你的字符串长度万一超过 256 个字符的时候，不会破坏堆栈。<br />
　　另外一个常见的错误是：既然固定大小的内存不工作，那么就采用动态分配字节，这种做法弊端更大：int len = lstrlen(parm1) + 13  lstrlen(parm2) + 10 + 100;char * buffer = new char[len];sprintf(buffer, &#34;%s is equal to %s, valid data&#34;, parm1, parm2);CString s = buffer;&#8230;&#8230;del&#101;te [] buffer;<br />
它可以能被简单地写成：CString s;s.Format(_T(&#34;%s is equal to %s, valid data&#34;), parm1, parm2);<br />
　　需要注意 sprintf 例子都不是 Unicode 就绪的，尽管你可以使用 tsprintf 以及用 _T() 来包围格式化字符串，但是基本 思路仍然是在走弯路，这这样很容易出错。<br />
<i><strong>CString to char * 之三：</strong></i>和控件的接口；<br />
　　我们经常需要把一个 CString 的值传递给一个控件，比如，CTreeCtrl。MFC为我们提供了很多便利来重载这个操作，但是 在大多数情况下，你使用“原始”形式的更新，因此需要将墨某个串指针存储到 TVIns&#101;rtITEMSTRUCT 结构的 TVITEM 成员中。如下：TVIns&#101;rtITEMSTRUCT tvi;CString s;// &#8230; 为s赋一些值。tvi.item.pszText = s; // Compiler yells at you here// &#8230; 填写tvi的其他域HTREEITEM ti = c_MyTree.Ins&#101;rtItem(&amp;tvi);<br />
　　为什么编译器会报错呢？明明看起来很完美的用法啊！但是事实上如果你看看 TVITEM 结构的定义你就会明白，在 TVITEM 结构中 pszText 成员的声明如下：LPTSTR pszText;int cchTextMax;<br />
　　因此，赋值不是赋给一个 LPCTSTR 类型的变量，而且编译器无法知道如何将赋值语句右边强制转换成 LPCTSTR。好吧，你说，那我就改成这样：tvi.item.pszText = (LPCTSTR)s; //编译器依然会报错。<br />
　　编译器之所以依然报错是因为你试图把一个 LPCTSTR 类型的变量赋值给一个 LPTSTR 类型的变量，这种操作在C或C++中是被禁止的。你不能用这种方法 来滥用常量指针与非常量指针概念，否则，会扰乱编译器的优化机制，使之不知如何优化你的程序。比如，如果你这么做：const int i = &#8230;;//&#8230; do lots of stuff&#8230; = a[i]; // usage 1// &#8230; lots more stuff&#8230; = a[i]; // usage 2<br />
　　那么，编译器会以为既然 i 是 const ，所以 usage1和usage2的值是相同的，并且它甚至能事先计算好 usage1 处的 a[i] 的地址，然后保留着在后面的 usage2 处使用，而不是重新计算。如果你按如下方式写的话：const int i = &#8230;;int * p = &amp;i;//&#8230; do lots of stuff&#8230; = a[i]; // usage 1// &#8230; lots more stuff(*p)++; // mess over compiler&#39;&#39;s assumption// &#8230; and other stuff&#8230; = a[i]; // usage 2<br />
　　编译器将认为 i 是常量，从而 a[i] 的位置也是常量，这样间接地破坏了先前的假设。因此，你的程序将会在 debug 编译模式（没有优化）和 release 编译模式（完全优化）中反映出不同的行为，这种情况可不好，所以当你试图把指向 i 的指针赋值给一个 可修改的引用时，会被编译器诊断为这是一种伪造。这就是为什么（LPCTSTR）强制类型转化不起作用的原因。<br />
　　为什么不把该成员声明成 LPCTSTR 类型呢？因为这个结构被用于读写控件。当你向控件写数据时，文本指针实际上被当成 LPCTSTR，而当你从控件读数据 时，你必须有一个可写的字符串。这个结构无法区分它是用来读还是用来写。<br />
因此，你会常常在我的代码中看到如下的用法：tvi.item.pszText = (LPTSTR)(LPCTSTR)s;<br />
　　它把 CString 强制类型转化成 LPCTSTR，也就是说先获得改字符串的地址，然后再强制类型转化成 LPTSTR，以便可以对之进行赋值操作。 注意这只有在使用 Set 或 Ins&#101;rt 之类的方法才有效！如果你试图获取数据，则不能这么做。<br />
　　如果你打算获取存储在控件中的数据，则方法稍有不同，例如，对某个 CTreeCtrl 使用 GetItem 方法，我想获取项目的文本。我知道这些 文本的长度不会超过 MY_LIMIT，因此我可以这样写：TVITEM tvi;// &#8230; assorted initialization of other fields of tvitvi.pszText = s.GetBuffer(MY_LIMIT);tvi.cchTextMax = MY_LIMIT;c_MyTree.GetItem(&amp;tvi);s.ReleaseBuffer();<br />
　　可以看出来，其实上面的代码对所有类型的 Set 方法都适用，但是并不需要这么做，因为所有的类 Set 方法（包括 Ins&#101;rt方法）不会改变字符串的内容。但是当你需要写 CString 对象时，必须保证缓冲是可写的，这正是 GetBuffer 所做的事情。再次强调： 一旦做了一次 GetBuffer 调用，那么在调用 ReleaseBuffer 之前不要对这个 CString 对象做任何操作。<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 5、<strong>CString 型转化成 BSTR 型</strong><br />
　　当我们使用 ActiveX 控件编程时，经常需要用到将某个值表示成 BSTR 类型。BSTR 是一种记数字符串，Intel平台上的宽字符串（Unicode），并且 可以包含嵌入的 NULL 字符。<br />
你可以调用 CString 对象的 AllocSysString 方法将 CString 转化成 BSTR：CString s;s = &#8230; ; // whateverBSTR b = s.AllocSysString();<br />
　　现在指针 b 指向的就是一个新分配的 BSTR 对象，该对象是 CString 的一个拷贝，包含终结 NULL字符。现在你可以将它传递给任何需要 BSTR 的接口。通常，BSTR 由接收它的组件来释放，如果你需要自己释放 BSTR 的话，可以这么做：::SysFreeString(b);<br />
　　对于如何表示传递给 ActiveX 控件的字符串，在微软内部曾一度争论不休，最后 Visual Basic 的人占了上风，BSTR（“Basic String”的首字母缩写）就是这场争论的结果。<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 6、<strong>BSTR 型转化成 CString 型</strong><br />
　　由于 BSTR 是记数 Unicode 字符串，你可以用标准转换方法来创建 8 位的 CString。实际上，这是 CString 内建的功能。在 CString 中 有特殊的构造函数可以把 ANSI 转化成 Unicode，也可以把Unicode 转化成 ANSI。你同样可以从 VARIANT 类型的变量中获得 BSTR 类型的字符串，VARIANT 类型是 由各种 COM 和 Automation (自动化)调用返回的类型。<br />
例如，在一个ANSI程序中：BSTR b;b = &#8230;; // whateverCString s(b == NULL ? L&#34;&#34; : b)<br />
　　对于单个的 BSTR 串来说，这种用法可以工作得很好，这是因为 CString 有一个特殊的构造函数以LPCWSTR（BSTR正是这种类型） 为参数，并将它转化成 ANSI 类型。专门检查是必须的，因为 BSTR 可能为空值，而 CString 的构造函数对于 NULL 值情况考虑的不是很周到，（感谢 Brian Ross 指出这一点!）。这种用法也只能处理包含 NUL 终结字符的单字符串；如果要转化含有多个 NULL 字符 串，你得额外做一些工作才行。在 CString 中内嵌的 NULL 字符通常表现不尽如人意，应该尽量避免。<br />
　　根据 C/C++ 规则，如果你有一个 LPWSTR，那么它别无选择，只能和 LPCWSTR 参数匹配。<br />
在 Unicode 模式下，它的构造函数是：CString::CString(LPCTSTR);<br />
正如上面所表示的，在 ANSI 模式下，它有一个特殊的构造函数：CString::CString(LPCWSTR);<br />
　　它会调用一个内部的函数将 Unicode 字符串转换成 ANSI 字符串。（在Unicode模式下，有一个专门的构造函数，该函数有一个参数是LPCSTR类型——一个8位 ANSI 字符串 指针，该函数将它加宽为 Unicode 的字符串！）再次强调：一定要检查 BSTR 的值是否为 NULL。<br />
　　另外还有一个问题，正如上文提到的：BSTRs可以含有多个内嵌的NULL字符，但是 CString 的构造函数只能处理某个串中单个 NULL 字符。 也就是说，如果串中含有嵌入的 NUL字节，CString 将会计算出错误的串长度。你必须自己处理它。如果你看看 strcore.cpp 中的构造函数，你会发现 它们都调用了lstrlen，也就是计算字符串的长度。<br />
　　注意从 Unicode 到 ANSI 的转换使用带专门参数的 ::WideCharToMultiByte，如果你不想使用这种默认的转换方式，则必须编写自己的转化代码。<br />
　　如果你在 UNICODE 模式下编译代码，你可以简单地写成：<br />
CString convert(BSTR b){    if(b == NULL)        return CString(_T(&#34;&#34;));    CString s(b); // in UNICODE mode    return s;}　　如果是 ANSI 模式，则需要更复杂的过程来转换。注意这个代码使用与 ::WideCharToMultiByte 相同的参数值。所以你 只能在想要改变这些参数进行转换时使用该技术。例如，指定不同的默认字符，不同的标志集等。 CString convert(BSTR b){    CString s;    if(b == NULL)       return s; // empty for NULL BSTR#ifdef UNICODE    s = b;#else    LPSTR p = s.GetBuffer(SysStringLen(b) + 1);     ::WideCharToMultiByte(CP_ACP,            // ANSI Code Page                          0,                 // no flags                          b,                 // source widechar string                          -1,                // assume NUL-terminated                          p,                 // target buffer                          SysStringLen(b)+1, // target buffer length                          NULL,              // use system default char                          NULL);             // don&#39;&#39;t care if default used    s.ReleaseBuffer();#endif    return s;}　　我并不担心如果 BSTR 包含没有映射到 8 位字符集的 Unicode 字符时会发生什么，因为我指定了::WideCharToMultiByte 的最后两个参数为 NULL。这就是你可能需要改变的地方。<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 7、<strong>VARIANT 型转化成 CString 型</strong><br />
　　事实上，我从来没有这么做过，因为我没有用 COM/OLE/ActiveX 编写过程序。但是我在microsoft.public.vc.mfc 新闻组上看到了 Robert Quirk 的一篇帖子谈到了这种转化，我觉得把他的文章包含在我的文章里是不太好的做法，所以在这里多做一些解释和演示。如果和他的文章有相孛的地方可能是我的疏忽。<br />
　　VARIANT 类型经常用来给 COM 对象传递参数，或者接收从 COM 对象返回的值。你也能自己编写返回 VARIANT 类型的方法，函数返回什么类型 依赖可能（并且常常）方法的输入参数（比如，在自动化操作中，依赖与你调用哪个方法。IDispatch::Invoke 可能返回（通过其一个参数）一个 包含有BYTE、WORD、float、double、date、BSTR 等等 VARIANT 类型的结果，（详见 MSDN 上的 VARIANT 结构的定义）。在下面的例子中，假设 类型是一个BSTR的变体，也就是说在串中的值是通过 bsrtVal 来引用，其优点是在 ANSI 应用中，有一个构造函数会把 LPCWCHAR 引用的值转换为一个 CString（见 BSTR-to-CString 部分）。在 Unicode 模式中，将成为标准的 CString 构造函数，参见对缺省::WideCharToMultiByte 转换的告诫，以及你觉得是否可以接受（大多数情况下，你会满意的）。VARIANT vaData;vaData = m_com.YourMethodHere();ASSERT(vaData.vt == VT_BSTR);CString strData(vaData.bstrVal);<br />
你还可以根据 vt 域的不同来建立更通用的转换例程。为此你可能会考虑：<br />
CString VariantToString(VARIANT * va){    CString s;    switch(va->vt)      { /* vt */       case VT_BSTR:          return CString(vaData->bstrVal);       case VT_BSTR | VT_BYREF:          return CString(*vaData->pbstrVal);       case VT_I4:          s.Format(_T(&#34;%d&#34;), va->lVal);          return s;       case VT_I4 | VT_BYREF:          s.Format(_T(&#34;%d&#34;), *va->plVal);       case VT_R8:          s.Format(_T(&#34;%f&#34;), va->dblVal);          return s;       &#8230; 剩下的类型转换由读者自己完成       default:          ASSERT(FALSE); // unknown VARIANT type (this ASSERT is optional)          return CString(&#34;&#34;);      } /* vt */}<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 8、<strong>载入字符串表资源</strong><br />
　　如果你想创建一个容易进行语言版本移植的应用程序，你就不能在你的源代码中直接包含本土语言字符串 （下面这些例子我用的语言都是英语，因为我的本土语是英语），比如下面这种写法就很糟：CString s = &#34;There is an error&#34;;<br />
　　你应该把你所有特定语言的字符串单独摆放（调试信息、在发布版本中不出现的信息除外）。这意味着向下面这样写比较好：s.Format(_T(&#34;%d &#8211; %s&#34;), code, text);<br />
　　在你的程序中，文字字符串不是语言敏感的。不管怎样，你必须很小心，不要使用下面这样的串：// fmt is &#34;Error in %s file %s&#34;// readorwrite is &#34;reading&#34; o&#114; &#34;writing&#34;s.Format(fmt, readorwrite, filename);<br />
　　这是我的切身体会。在我的第一个国际化的应用程序中我犯了这个错误，尽管我懂德语，知道在德语的语法中动词放在句子的最后面，我们的德国方面的发行人还是苦苦的抱怨他们不得不提取那些不可思议的德语错误提示信息然后重新格式化以让它们能正常工作。比较好的办法（也是我现在使用的办法）是使用两个字符串，一个用 于读，一个用于写，在使用时加载合适的版本，使得它们对字符串参数是非敏感的。也就是说加载整个格式，而不是加载串“reading”，“writing”：// fmt is &#34;Error in reading file %s&#34;// &#34;Error in writing file %s&#34;s.Format(fmt, filename);<br />
　　一定要注意，如果你有好几个地方需要替换，你一定要保证替换后句子的结构不会出现问题，比如在英语中，可以是主语-宾语，主语-谓语，动词-宾语的结构等等。<br />
　　在这里，我们并不讨论 FormatMessage，其实它比 sprintf/Format 还要有优势，但是不太容易和CString 结合使用。解决这种问题的办法就是我们按照参数出现在参数表中的位置给参数取名字，这样在你输出的时候就不会把他们的位置排错了。<br />
　　接下来我们讨论我们这些独立的字符串放在什么地方。我们可以把字符串的值放入资源文件中的一个称为 STRINGTABLE 的段中。过程如下：首先使用 Visual Studio 的资源编辑器创建一个字符串，然后给每一个字符串取一个ID，一般我们给它取名字都以 IDS_开头。所以如果你有一个信息，你可以创建一个字符串资源然后取名为 IDS_READING_FILE，另外一个就取名为 IDS_WRITING_FILE。它们以下面的形式出现在你的 .rc 文件中：STRINGTABLEIDS_READING_FILE &#34;Reading file %s&#34;IDS_WRITING_FILE &#34;Writing file %s&#34;END<br />
<strong>注意：</strong>这些资源都以 Unicode 的格式保存，不管你是在什么环境下编译。他们在Win9x系统上也是以Unicode 的形式存在，虽然 Win9x 不能真正处理 Unicode。<br />
然后你可以这样使用这些资源：<br />
// 在使用资源串表之前，程序是这样写的：<br />
   CString fmt;      if(&#8230;)        fmt = &#34;Reading file %s&#34;;     else       fmt = &#34;Writing file %s&#34;;  &#8230;    // much later  CString s;  s.Format(fmt, filename); // 使用资源串表之后，程序这样写：     CString fmt;        if(&#8230;)           fmt.LoadString(IDS_READING_FILE);        else           fmt.LoadString(DS_WRITING_FILE);    &#8230;      // much later    CString s;    s.Format(fmt, filename);　　现在，你的代码可以移植到任何语言中去。LoadString 方法需要一个字符串资源的 ID 作为参数，然后它从 STRINGTABLE 中取出它对应的字符串，赋值给 CString 对象。 CString 对象的构造函数还有一个更加聪明的特征可以简化 STRINGTABLE 的使用。这个用法在 CString::CString 的文档中没有指出，但是在 构造函数的示例程序中使用了。（为什么这个特性没有成为正式文档的一部分，而是放在了一个例子中，我记不得了！）——【<strong>译者注</strong>：从这句话看，作者可能是CString的设计者。其实前面还有一句类似的话。说他没有对使用GetBuffer(0)获得的指针指向的地址是否可读做有效性检查 】。这个特征就是：如果你将一个字符串资源的ID强制类型转换为 LPCTSTR，将会隐含调用 LoadString。因此，下面两个构造字符串的例子具有相同的效果，而且其 ASSERT 在debug模式下不会被触发：CString s;s.LoadString(IDS_WHATEVER);CString t( (LPCTSTR)IDS_WHATEVER );ASSERT(s == t);//不会被触发，说明s和t是相同的。<br />
　　现在，你可能会想：这怎么可能工作呢？我们怎么能把 STRINGTABLE ID 转化成一个指针呢？很简单：所有的字符串 ID 都在1~65535这个范围内，也就是说，它所有的高位都是0，而我们在程序中所使用的指针是不可能小于65535的，因为程序的低 64K 内存永远也不可能存在的，如果你试图访问0&#215;00000000到0x0000FFFF之间的内存，将会引发一个内存越界错误。所以说1~65535的值不可能是一个内存地址，所以我们可以用这些值来作为字符串资源的ID。<br />
　　我倾向于使用 MAKEINTRESOURCE 宏显式地做这种转换。我认为这样可以让代码更加易于阅读。这是个只适合在 MFC 中使用的标准宏。你要记住，大多数的方法即可以接受一个 UINT 型的参数，也可以接受一个 LPCTSTR 型的参数，这是依赖 C++ 的重载功能做到的。C++重载函数带来的 弊端就是造成所有的强制类型转化都需要显示声明。同样，你也可以给很多种结构只传递一个资源名。CString s;s.LoadString(IDS_WHATEVER);CString t( MAKEINTRESOURCE(IDS_WHATEVER));ASSERT(s == t);<br />
　　告诉你吧：我不仅只是在这里鼓吹，事实上我也是这么做的。在我的代码中，你几乎不可能找到一个字符串，当然，那些只是偶然在调试中出现的或者和语言无关的字符串除外。<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 9、<strong>CString 和临时对象</strong><br />
　　这是出现在 microsoft.public.vc.mfc 新闻组中的一个小问题，我简单的提一下，这个问题是有个程序员需要往注册表中写入一个字符串，他写道：<br />
　　我试着用 RegSetValueEx() 设置一个注册表键的值，但是它的结果总是令我困惑。当我用char[]声明一个变量时它能正常工作，但是当我用 CString 的时候，总是得到一些垃圾：&#34;ÝÝÝÝ&#8230;ÝÝÝÝÝÝ&#34;为了确认是不是我的 CString 数据出了问题，我试着用 GetBuffer，然后强制转化成 char*，LPCSTR。GetBuffer 返回的值是正确的，但是当我把它赋值给 char* 时，它就变成垃圾了。以下是我的程序段：char* szName = GetName().GetBuffer(20);RegSetValueEx(hKey, &#34;Name&#34;, 0, REG_SZ,              (CONST BYTE *) szName,             strlen (szName + 1));<br />
这个 Name 字符串的长度小于 20，所以我不认为是 GetBuffer 的参数的问题。<br />
真让人困惑，请帮帮我。<br />
亲爱的 Frustrated，<br />
你犯了一个相当微妙的错误，聪明反被聪明误，正确的代码应该象下面这样：<br />
CString Name = GetName();RegSetValueEx(hKey, _T(&#34;Name&#34;), 0, REG_SZ,                     (CONST BYTE *) (LPCTSTR)Name,                    (Name.GetLength() + 1) * sizeof(TCHAR));　　为什么我写的代码能行而你写的就有问题呢？主要是因为当你调用 GetName 时返回的 CString 对象是一个临时对象。参见：《C++ Reference manual》§12.2<br />
　　在一些环境中，编译器有必要创建一个临时对象，这样引入临时对象是依赖于实现的。如果编译器引入的这个临时对象所属的类有构造函数的话，编译器要确保这个类的构造函数被调用。同样的，如果这个类声明有析构函数的话，也要保证这个临时对象的析构函数被调用。<br />
　　编译器必须保证这个临时对象被销毁了。被销毁的确切地点依赖于实现&#8230;..这个析构函数必须在退出创建该临时对象的范围之前被调用。<br />
　　大部分的编译器是这样设计的：在临时对象被创建的代码的下一个执行步骤处隐含调用这个临时对象的析构函数，实现起来，一般都是在下一个分号处。因此，这个 CString 对象在 GetBuffer 调用之后就被析构了（顺便提一句，你没有理由给 GetBuffer 函数传递一个参数，而且没有使用ReleaseBuffer 也是不对的）。所以 GetBuffer 本来返回的是指向这个临时对象中字符串的地址的指针，但是当这个临时对象被析构后，这块内存就被释放了。然后 MFC 的调试内存分配器会重新为这块内存全部填上 0xDD，显示出来刚好就是“Ý”符号。在这个时候你向注册表中写数据，字符串的内容当然全被破坏了。<br />
　　我们不应该立即把这个临时对象转化成 char* 类型，应该先把它保存到一个 CString 对象中，这意味着把临时对象复制了一份，所以当临时的 CString 对象被析构了之后，这个 CString 对象中的值依然保存着。这个时候再向注册表中写数据就没有问题了。<br />
　　此外，我的代码是具有 Unicode 意识的。那个操作注册表的函数需要一个字节大小，使用lstrlen(Name+1) 得到的实际结果对于 Unicode 字符来说比 ANSI 字符要小一半，而且它也不能从这个字符串的第二个字符起开始计算，也许你的本意是 lstrlen(Name) + 1（OK，我承认，我也犯了同样的错误！）。不论如何，在 Unicode 模式下，所有的字符都是2个字节大小，我们需要处理这个问题。微软的文档令人惊讶地对此保持缄默：REG_SZ 的值究竟是以字节计算还是以字符计算呢？我们假设它指的是以字节为单位计算，你需要对你的代码做一些修改来计算这个字符串所含有的字节大小。<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 10、<strong>CString 的效率</strong><br />
　　CString 的一个问题是它确实掩藏了一些低效率的东西。从另外一个方面讲，它也确实可以被实现得更加高效，你可能会说下面的代码：CString s = SomeCString1;s += SomeCString2;s += SomeCString3;s += &#34;,&#34;;s += SomeCString4;<br />
比起下面的代码来，效率要低多了：char s[1024];lstrcpy(s, SomeString1);lstrcat(s, SomeString2);lstrcat(s, SomeString 3);lstrcat(s, &#34;,&#34;);lstrcat(s, SomeString4);<br />
　　总之，你可能会想，首先，它为 SomeCString1 分配一块内存，然后把 SomeCString1 复制到里面，然后发现它要做一个连接，则重新分配一块新的足够大的内存，大到能够放下当前的字符串加上SomeCString2，把内容复制到这块内存 ，然后把 SomeCString2 连接到后面，然后释放第一块内存，并把指针重新指向新内存。然后为每个字符串重复这个过程。把这 4 个字符串连接起来效率多低啊。事实上，在很多情况下根本就不需要复制源字符串（在 += 操作符左边的字符串）。<br />
　　在 VC++6.0 中，Release 模式下，所有的 CString 中的缓存都是按预定义量子分配的。所谓量子，即确定为 64、128、256 或者 512 字节。这意味着除非字符串非常长，连接字符串的操作实际上就是 strcat 经过优化后的版本（因为它知道本地的字符串应该在什么地方结束，所以不需要寻找字符串的结尾；只需要把内存中的数据拷贝到指定的地方即可）加上重新计算字符串的长度。所以它的执行效率和纯 C 的代码是一样的，但是它更容易写、更容易维护和更容易理解。<br />
　　如果你还是不能确定究竟发生了怎样的过程，请看看 CString 的源代码，strcore.cpp，在你 vc98的安装目录的 mfc\src 子目录中。看看 ConcatInPlace 方法，它被在所有的 += 操作符中调用。<br />
啊哈！难道 CString 真的这么&#34;高效&#34;吗？比如，如果我创建CString cat(&#34;Mew!&#34;);<br />
　　然后我并不是得到了一个高效的、精简的5个字节大小的缓冲区（4个字符加一个结束字符），系统将给我分配64个字节，而其中59个字节都被浪费了。<br />
　　如果你也是这么想的话，那么就请准备好接受再教育吧。可能在某个地方某个人给你讲过尽量使用少的空间是件好事情。不错，这种说法的确正确，但是他忽略了事实中一个很重要的方面。<br />
　　如果你编写的是运行在16K EPROMs下的嵌入式程序的话，你有理由尽量少使用空间，在这种环境下，它能使你的程序更健壮。但是在 500MHz, 256MB的机器上写 Windows 程序，如果你还是这么做，它只会比你认为的“低效”的代码运行得更糟。<br />
　　举例来说。字符串的大小被认为是影响效率的首要因素，使字符串尽可能小可以提高效率，反之则降低效率，这是大家一贯的想法。但是这种想法是不对的，精确的内存分配的后果要在程序运行了好几个小时后才能体现得出来，那时，程序的堆中将充满小片的内存，它们太小以至于不能用来做任何事，但是他们增加了你程序的内存用量，增加了内存页面交换的次数，当页面交换的次数增加到系统能够忍受的上限，系统则会为你的程序分配更多的页面，直到你的程序占用了所有的可用内存。由此可见，虽然内存碎片是决定效率的次要因素，但正是这些因素实际控制了系统的行为，最终，它损害了系统的可靠性，这是令人无法接受的。<br />
　　记住，在 debug 模式下，内存往往是精确分配的，这是为了更好的排错。<br />
　　假设你的应用程序通常需要连续工作好几个月。比如，我常打开 VC++，Word，PowerPoint，Frontpage，Outlook Express，Forté Agent，Internet Explorer和其它的一些程序，而且通常不关闭它们。我曾经夜以继日地连续用 PowerPoint 工作了好几天（反之，如果你不幸不得不使用像 Adobe FrameMaker 这样的程序的话，你将会体会到可靠性的重要；这个程序机会每天都要崩溃4~6次，每次都是因为用完了所有的空间并填满我所有的交换页面）。所以精确内存分配是不可取的，它会危及到系统的可靠性，并引起应用程序崩溃。<br />
　　按量子的倍数为字符串分配内存，内存分配器就可以回收用过的内存块，通常这些回收的内存块马上就可以被其它的 CString 对象重新用到，这样就可以保证碎片最少。分配器的功能加强了，应用程序用到的内存就能尽可能保持最小，这样的程序就可以运行几个星期或几个月而不出现问题。<br />
　　题外话：很多年以前，我们在 CMU 写一个交互式系统的时候，一些对内存分配器的研究显示出它往往产生很多内存碎片。Jim Mitchell，现在他在 Sun Microsystems 工作，那时侯他创造了一种内存分配器，它保留了一个内存分配状况的运行时统计表，这种技术和当时的主流分配器所用的技术都不同，且较为领先。当一个内存块需要被分割得比某一个值小的话，他并不分割它，因此可以避免产生太多小到什么事都干不了的内存碎片。事实上他在内存分配器中使用了一个浮动指针，他认为：与其让指令做长时间的存取内存操作，还不如简单的忽略那些太小的内存块而只做一些浮动指针的操作。（His observation was that the long-term saving in instructions by not having to ignore unusable small storage chunks far and away exceeded the additional cost of doing a few floating point operations on an allocation operation.）他是对的。<br />
　　永远不要认为所谓的“最优化”是建立在每一行代码都高速且节省内存的基础上的，事实上，高速且节省内存应该是在一个应用程序的整体水平上考虑的。在软件的整体水平上，只使用最小内存的字符串分配策略可能是最糟糕的一种方法。<br />
　　如果你认为优化是你在每一行代码上做的那些努力的话，你应该想一想：在每一行代码中做的优化很少能真正起作用。你可以看我的另一篇关于优化问题的文章《Your Worst Enemy for some thought-provoking ideas》。<br />
　　记住，+= 运算符只是一种特例，如果你写成下面这样：CString s = SomeCString1 + SomeCString2 + SomeCString3 + &#34;,&#34; + SomeCString4;<br />
则每一个 + 的应用会造成一个新的字符串被创建和一次复制操作。<br />
<img src="http://www.vckbase.com/document/image/paragraph.gif" border="0" alt=""/><br />
 <strong>总结</strong><br />
　　以上是使用 CString 的一些技巧。我每天写程序的时候都会用到这些。CString 并不是一种很难使用的类，但是 MFC 没有很明显的指出这些特征，需要你自己去探索、去发现。</p>
]]></content:encoded>
			<wfw:commentRss>http://xlp1437.me/2007/01/02/cstring-%e6%93%8d%e4%bd%9c%e6%8c%87%e5%8d%97/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何通过正版验证装IE7</title>
		<link>http://xlp1437.me/2006/10/27/%e5%a6%82%e4%bd%95%e9%80%9a%e8%bf%87%e6%ad%a3%e7%89%88%e9%aa%8c%e8%af%81%e8%a3%85ie7/</link>
		<comments>http://xlp1437.me/2006/10/27/%e5%a6%82%e4%bd%95%e9%80%9a%e8%bf%87%e6%ad%a3%e7%89%88%e9%aa%8c%e8%af%81%e8%a3%85ie7/#comments</comments>
		<pubDate>Fri, 27 Oct 2006 18:26:43 +0000</pubDate>
		<dc:creator>烧饼</dc:creator>
				<category><![CDATA[软件]]></category>

		<guid isPermaLink="false">http://www.4ever-memory.com/?p=7</guid>
		<description><![CDATA[最近纠结于怎么安装IE7，在广泛求教后终于得到了结果~~ 首先，先上：微软正版验证地址，下载WGA的验证插件 接下来，显然被认为是盗版的咯，而且IE7的安装过程是要求Validate your windows的~~这时候，不要急，先把网线拔了，然后进入%systemroot%\Documents and Settings\All Users\Application Data\，将该路径下的Windows Genuine Advantage文件夹整个删除，然后在断网的情况下点IE7安装过程中Validate，稍等一会儿就可以得到已经通过的提示~~^O^然后照常做就可以了` 用本本有正版用户及用番茄花园最新版本XP已经通过正版验证的朋友请忽略我吧~~^O^~~ 附上IE7下载地址，注意是英文版的哟，中文版的得等到11月份才会推出~~ IE7下载]]></description>
			<content:encoded><![CDATA[<p>最近纠结于怎么安装IE7，在广泛求教后终于得到了结果~~</p>
<p>首先，先上：<a target="_blank" href="http://go.microsoft.com/fwlink/?linkid=33171&amp;LegitCheckError=8">微软正版验证地址</a>，下载WGA的验证插件</p>
<p>接下来，显然被认为是盗版的咯，而且IE7的安装过程是要求Validate your windows的~~这时候，不要急，先把网线拔了，然后进入%systemroot%\Documents and Settings\All Users\Application Data\，将该路径下的Windows Genuine Advantage文件夹整个删除，然后在断网的情况下点IE7安装过程中Validate，稍等一会儿就可以得到已经通过的提示~~^O^然后照常做就可以了`</p>
<p>用本本有正版用户及用番茄花园最新版本XP已经通过正版验证的朋友请忽略我吧~~^O^~~</p>
<p>附上IE7下载地址，注意是英文版的哟，中文版的得等到11月份才会推出~~</p>
<p><a target="_blank" href="http://www.microsoft.com/windows/ie/downloads/default.mspx">IE7下载</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xlp1437.me/2006/10/27/%e5%a6%82%e4%bd%95%e9%80%9a%e8%bf%87%e6%ad%a3%e7%89%88%e9%aa%8c%e8%af%81%e8%a3%85ie7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows小项目&#8212;-进度5%Complete</title>
		<link>http://xlp1437.me/2006/10/17/windows%e5%b0%8f%e9%a1%b9%e7%9b%ae-%e8%bf%9b%e5%ba%a65complete/</link>
		<comments>http://xlp1437.me/2006/10/17/windows%e5%b0%8f%e9%a1%b9%e7%9b%ae-%e8%bf%9b%e5%ba%a65complete/#comments</comments>
		<pubDate>Tue, 17 Oct 2006 17:42:19 +0000</pubDate>
		<dc:creator>烧饼</dc:creator>
				<category><![CDATA[软件]]></category>

		<guid isPermaLink="false">http://www.4ever-memory.com/?p=38</guid>
		<description><![CDATA[项目功能需求分析 Version 0.1 by 枫 &#160; 1、&#160; 绘制直线、圆、矩形、多边形（可选功能：改变图形的颜色） a)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 直线：满足正常的画直线功能，并可改变宽度和样式 可选功能：按信Shift时只能画出0度，45度和90度的直线 b)&#160;&#160;&#160;&#160;&#160;&#160;&#160; 矩形/多边形/圆形：满足正常的只有边框填充区域为NULL的矩形/多边形/圆形 注：多边形当鼠标拖动的时候与直线相同，但当点击左键的时候，系统首先应该判断该点与上一个点是否属于同一点，若不相同，则此时自动上前一个点，而鼠标左键点击时所在位置与上一个点间出现一条连线。当松开左键时，判断点是否与起始点重合，若不重合，则下一次点击继续画线；若重合，则绘图结束。当产生了双击消息时自动将左键当时位置与起始点连接起来 &#160; 可选功能：用前景色画边框，背景色填充；用前景色填充 &#160; 2、&#160; 数据保存/读取功能，能够把图形数据保存到文件中或从文件中读取（可选功能：实现动态创建） 能够实现提示保存对话框。 打开时显示打开对话框，并将图形重新绘制。 &#160; 3、&#160; 简单的编辑功能：双击选中，利用键盘Del 键和菜单项删除选中的图形元素 可选功能：复制、剪切、粘贴、全选 &#160; 4、&#160; 可以进行对象的放大和缩小 以鼠标所在位置为原点，对整个图像进行缩放 每一下以25%的比例进行缩放 &#160; 5、&#160; 如果在一个计算机上运行两个程序实例，那么在任何一个程序中操作在另外的程序中都可以看到相同的操作结果，也就是程序之间具有通信的功能。 &#160; 6、&#160; 新建一个文件，并提示是否对上次的操作进行保存。 &#160; 7、&#160; 具有另存为功能，并关闭当前工程，打开另存为后的工程。 &#160; 8、&#160; 可选功能：制作橡皮、一个帮助文档，一个关于对话框，对整个图像进行诸如翻转，拉伸、反色、清除全部、打印的功能。 &#160; 9、&#160; 具体的菜单项设计： a)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 文件 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; i.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 新建 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ii.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 打开 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; [...]]]></description>
			<content:encoded><![CDATA[<div align="center">项目功能需求分析</div>
<div style="MARGIN: 0cm 0cm 0pt 315pt; TEXT-INDENT: 21pt">Version 0.1 by 枫</div>
<div>&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>1、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp; </font></span></span>绘制直线、圆、矩形、多边形（可选功能：改变图形的颜色）</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span>a)<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>直线：满足正常的画直线功能，并可改变宽度和样式</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">可选功能：按信Shift时只能画出0度，45度和90度的直线</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span>b)<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>矩形/多边形/圆形：满足正常的只有边框填充区域为NULL的矩形/多边形/圆形</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt">注：多边形当鼠标拖动的时候与直线相同，但当点击左键的时候，系统首先应该判断该点与上一个点是否属于同一点，若不相同，则此时自动上前一个点，而鼠标左键点击时所在位置与上一个点间出现一条连线。当松开左键时，判断点是否与起始点重合，若不重合，则下一次点击继续画线；若重合，则绘图结束。当产生了双击消息时自动将左键当时位置与起始点连接起来</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">可选功能：用前景色画边框，背景色填充；用前景色填充</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>2、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp; </font></span></span>数据保存<span>/读取功能，能够把图形数据保存到文件中或从文件中读取（可选功能：实现动态创建）</span></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">能够实现提示保存对话框。</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">打开时显示打开对话框，并将图形重新绘制。</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>3、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp; </font></span></span>简单的编辑功能：双击选中，利用键盘Del 键和菜单项删除选中的图形元素</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">可选功能：复制、剪切、粘贴、全选</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>4、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp; </font></span></span>可以进行对象的放大和缩小</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">以鼠标<b><u>所在位置为原点</u></b>，对<b><u>整个图像</u></b>进行缩放</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">每一下以<i>25%</i>的比例进行缩放</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>5、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp; </font></span></span>如果在一个计算机上运行两个程序实例，那么在任何一个程序中操作在另外的程序中都可以看到相同的操作结果，也就是程序之间具有通信的功能。</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>6、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp; </font></span></span>新建一个文件，并提示是否对上次的操作进行保存。</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>7、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp; </font></span></span>具有另存为功能，并关闭当前工程，打开另存为后的工程。</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>8、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp; </font></span></span>可选功能：制作橡皮、一个帮助文档，一个关于对话框，对整个图像进行诸如翻转，拉伸、反色、清除全部、打印的功能。</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>9、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp; </font></span></span>具体的菜单项设计：</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span>a)<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>文件</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>新建</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>打开</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>保存</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iv.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>另存为</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>打印（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span>b)<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>编辑</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>选择（当选中此项后，不用双击鼠标即可选中对象）</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>删除选定内容</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>复制（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iv.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>剪切（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>粘贴（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vi.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>全选（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span>c)<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>查看</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>工具栏（显示，隐藏工具栏）（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>颜色栏（显示，隐藏颜色栏）（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>缩放</div>
<div style="MARGIN: 0cm 0cm 0pt 84pt; TEXT-INDENT: -21pt"><span>1.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>放大</div>
<div style="MARGIN: 0cm 0cm 0pt 84pt; TEXT-INDENT: -21pt"><span>2.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>缩小</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span>d)<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>图像（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>翻转</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>拉伸</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>反色</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iv.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>清除全部</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span>e)<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>图元（选中此中各项，与单击工具栏上按钮等同效果）</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>直线</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>矩形</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>多边形</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iv.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>圆</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>橡皮</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span>f)<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>帮助（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>帮助文档</div>
<div style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: -63pt"><span><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ii.<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span>关于</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>10、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>工具栏（各个可选功能再加入）（可选）</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">内容：直线、矩形、多边形、矩形、放大、缩小、橡皮</div>
<div style="MARGIN: 0cm 0cm 0pt 42pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span>11、<span style="FONT: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>颜色栏（可选）：模拟画图的功能</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt">=====================================================================================</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt">&nbsp;</div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt">P.S:</p>
<p>Windows小项目这周正式开工咯~~这是今天花了一节课写的项目功能需求分析~~接下来要进行类的构建,计划在今天和明天内完成!~~~第一次写这个东西,觉得还有好多没考虑到&#8230;&gt;.&lt;</p>
<p>So 先发布version 0.1吧~~^O^</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://xlp1437.me/2006/10/17/windows%e5%b0%8f%e9%a1%b9%e7%9b%ae-%e8%bf%9b%e5%ba%a65complete/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>放出这学期Windows程序设计的第一个小项目要求</title>
		<link>http://xlp1437.me/2006/10/17/%e6%94%be%e5%87%ba%e8%bf%99%e5%ad%a6%e6%9c%9fwindows%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e7%9a%84%e7%ac%ac%e4%b8%80%e4%b8%aa%e5%b0%8f%e9%a1%b9%e7%9b%ae%e8%a6%81%e6%b1%82/</link>
		<comments>http://xlp1437.me/2006/10/17/%e6%94%be%e5%87%ba%e8%bf%99%e5%ad%a6%e6%9c%9fwindows%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e7%9a%84%e7%ac%ac%e4%b8%80%e4%b8%aa%e5%b0%8f%e9%a1%b9%e7%9b%ae%e8%a6%81%e6%b1%82/#comments</comments>
		<pubDate>Tue, 17 Oct 2006 16:48:59 +0000</pubDate>
		<dc:creator>烧饼</dc:creator>
				<category><![CDATA[软件]]></category>

		<guid isPermaLink="false">http://www.4ever-memory.com/?p=39</guid>
		<description><![CDATA[项目1：编写绘图程序(35%)目标：]]></description>
			<content:encoded><![CDATA[<p>项目1：编写绘图程序(35%)<br />目标：</p>
]]></content:encoded>
			<wfw:commentRss>http://xlp1437.me/2006/10/17/%e6%94%be%e5%87%ba%e8%bf%99%e5%ad%a6%e6%9c%9fwindows%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e7%9a%84%e7%ac%ac%e4%b8%80%e4%b8%aa%e5%b0%8f%e9%a1%b9%e7%9b%ae%e8%a6%81%e6%b1%82/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

