<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
	<channel>
		<title>金麦网络</title>
		<link>http://www.kingmx.com</link>
		<copyright>Copyright (C) 2006 金麦网络-Kingmx.com All Rights Reserved.</copyright>
		<item>
			<title>在C#中操作XML的例子</title>
			<link>http://www.kingmx.com/article.php?id=15249</link>
			<pubDate>2007-4-27</pubDate>
			<description><![CDATA[这是一种很笨的方法，但可以帮助初学者了解访问XML节点的过程。&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 已知有一个XML文件（bookstore.xml）如下：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &lt;?xml&nbsp;&nbsp; version="1.0"&nbsp;&nbsp; encoding="gb2312"?&gt;&nbsp;&nbsp; 
&nbsp; &lt;bookstore&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;book&nbsp;&nbsp; genre="fantasy"&nbsp;&nbsp; ISBN="2-3631-4"&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;Oberon's&nbsp;&nbsp; Legacy&lt;/title&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;author&gt;Corets,&nbsp;&nbsp; Eva&lt;/author&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;price&gt;5.95&lt;/price&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/book&gt;&nbsp;&nbsp; 
&nbsp; &lt;/bookstore&gt;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、往&lt;bookstore&gt;节点中插入一个&lt;book&gt;节点：&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlDocument&nbsp;&nbsp; xmlDoc=new&nbsp;&nbsp; XmlDocument();&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlDoc.Load("bookstore.xml");&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNode&nbsp;&nbsp; root=xmlDoc.SelectSingleNode("bookstore");//查找&lt;bookstore&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlElement&nbsp;&nbsp; xe1=xmlDoc.CreateElement("book");//创建一个&lt;book&gt;节点&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xe1.SetAttribute("genre","李赞红");//设置该节点genre属性&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xe1.SetAttribute("ISBN","2-3631-4");//设置该节点ISBN属性&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlElement&nbsp;&nbsp; xesub1=xmlDoc.CreateElement("title");&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xesub1.InnerText="CS从入门到精通";//设置文本节点&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xe1.AppendChild(xesub1);//添加到&lt;book&gt;节点中&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlElement&nbsp;&nbsp; xesub2=xmlDoc.CreateElement("author");&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xesub2.InnerText="候捷";&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xe1.AppendChild(xesub2);&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlElement&nbsp;&nbsp; xesub3=xmlDoc.CreateElement("price");&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xesub3.InnerText="58.3";&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xe1.AppendChild(xesub3);&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; root.AppendChild(xe1);//添加到&lt;bookstore&gt;节点中&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlDoc.Save("bookstore.xml");&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; &lt;?xml&nbsp;&nbsp; version="1.0"&nbsp;&nbsp; encoding="gb2312"?&gt;&nbsp;&nbsp; 
&nbsp; &lt;bookstore&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;book&nbsp;&nbsp; genre="fantasy"&nbsp;&nbsp; ISBN="2-3631-4"&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;Oberon's&nbsp;&nbsp; Legacy&lt;/title&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;author&gt;Corets,&nbsp;&nbsp; Eva&lt;/author&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;price&gt;5.95&lt;/price&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/book&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;book&nbsp;&nbsp; genre="李赞红"&nbsp;&nbsp; ISBN="2-3631-4"&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;CS从入门到精通&lt;/title&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;author&gt;候捷&lt;/author&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;price&gt;58.3&lt;/price&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/book&gt;&nbsp;&nbsp; 
&nbsp; &lt;/bookstore&gt;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp; 2、修改节点：将genre属性值为“李赞红“的节点的genre值改为“update李赞红”，将该节点的子节点&lt;author&gt;的文本修改为“亚胜”。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList&nbsp;&nbsp; nodeList=xmlDoc.SelectSingleNode("bookstore").ChildNodes;//获取bookstore节点的所有子节点&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach(XmlNode&nbsp;&nbsp; xn&nbsp;&nbsp; in&nbsp;&nbsp; nodeList)//遍历所有子节点&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlElement&nbsp;&nbsp; xe=(XmlElement)xn;//将子节点类型转换为XmlElement类型&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(xe.GetAttribute("genre")=="李赞红")//如果genre属性值为“李赞红”&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xe.SetAttribute("genre","update李赞红");//则修改该属性为“update李赞红”&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList&nbsp;&nbsp; nls=xe.ChildNodes;//继续获取xe子节点的所有子节点&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach(XmlNode&nbsp;&nbsp; xn1&nbsp;&nbsp; in&nbsp;&nbsp; nls)//遍历&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; XmlElement&nbsp;&nbsp; xe2=(XmlElement)xn1;//转换类型&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(xe2.Name=="author")//如果找到&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; xe2.InnerText="亚胜";//则修改&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;//找到退出来就可以了&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; break;&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; xmlDoc.Save("bookstore.xml");//保存。&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; &lt;?xml&nbsp;&nbsp; version="1.0"&nbsp;&nbsp; encoding="gb2312"?&gt;&nbsp;&nbsp; 
&nbsp; &lt;bookstore&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;book&nbsp;&nbsp; genre="fantasy"&nbsp;&nbsp; ISBN="2-3631-4"&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;Oberon's&nbsp;&nbsp; Legacy&lt;/title&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;author&gt;Corets,&nbsp;&nbsp; Eva&lt;/author&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;price&gt;5.95&lt;/price&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/book&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;book&nbsp;&nbsp; genre="update李赞红"&nbsp;&nbsp; ISBN="2-3631-4"&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;CS从入门到精通&lt;/title&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;author&gt;亚胜&lt;/author&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;price&gt;58.3&lt;/price&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/book&gt;&nbsp;&nbsp; 
&nbsp; &lt;/bookstore&gt;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、删除&nbsp;&nbsp; &lt;book&nbsp;&nbsp; genre="fantasy"&nbsp;&nbsp; ISBN="2-3631-4"&gt;节点的genre属性，删除&nbsp;&nbsp; &lt;book&nbsp;&nbsp; genre="update李赞红"&nbsp;&nbsp; ISBN="2-3631-4"&gt;节点。&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; XmlNodeList&nbsp;&nbsp; xnl=xmlDoc.SelectSingleNode("bookstore").ChildNodes;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach(XmlNode&nbsp;&nbsp; xn&nbsp;&nbsp; in&nbsp;&nbsp; xnl)&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlElement&nbsp;&nbsp; xe=(XmlElement)xn;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(xe.GetAttribute("genre")=="fantasy")&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xe.RemoveAttribute("genre");//删除genre属性&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp; if(xe.GetAttribute("genre")=="update李赞红")&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xe.RemoveAll();//删除该节点的全部内容&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; xmlDoc.Save("bookstore.xml");&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; &lt;?xml&nbsp;&nbsp; version="1.0"&nbsp;&nbsp; encoding="gb2312"?&gt;&nbsp;&nbsp; 
&nbsp; &lt;bookstore&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;book&nbsp;&nbsp; ISBN="2-3631-4"&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;title&gt;Oberon's&nbsp;&nbsp; Legacy&lt;/title&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;author&gt;Corets,&nbsp;&nbsp; Eva&lt;/author&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;price&gt;5.95&lt;/price&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/book&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;book&gt;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/book&gt;&nbsp;&nbsp; 
&nbsp; &lt;/bookstore&gt;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、显示所有数据。&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNode&nbsp;&nbsp; xn=xmlDoc.SelectSingleNode("bookstore");&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList&nbsp;&nbsp; xnl=xn.ChildNodes;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach(XmlNode&nbsp;&nbsp; xnf&nbsp;&nbsp; in&nbsp;&nbsp; xnl)&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlElement&nbsp;&nbsp; xe=(XmlElement)xnf;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(xe.GetAttribute("genre"));//显示属性值&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(xe.GetAttribute("ISBN"));&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList&nbsp;&nbsp; xnf1=xe.ChildNodes;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach(XmlNode&nbsp;&nbsp; xn2&nbsp;&nbsp; in&nbsp;&nbsp; xnf1)&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(xn2.InnerText);//显示子节点点文本&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp; 
]]></description>
		</item>
		<item>
			<title>C# 日期格式转换</title>
			<link>http://www.kingmx.com/article.php?id=15245</link>
			<pubDate>2007-4-27</pubDate>
			<description><![CDATA[
有时候我们要对时间进行转换,达到不同的显示效果
　默认格式为:2005-6-6 14:33:34
　如果要换成成200506,06-2005,2005-6-6或更多的该怎么办呢
　我们要用到:DateTime.ToString的方法(String, IFormatProvider)
　
　using System;
　using System.Globalization;
　String format="D";
　DateTime date=DataTime,Now;
　Response.Write(date.ToString(format, DateTimeFormatInfo.InvariantInfo));
　结果输出
　Thursday, June 16, 2005
　
　参数format格式详细用法
　格式字符 关联属性/说明
　d ShortDatePattern
　D LongDatePattern
　f 完整日期和时间（长日期和短时间）
　F FullDateTimePattern（长日期和长时间）
　g 常规（短日期和短时间）
　G 常规（短日期和长时间）
　m、M MonthDayPattern
　r、R RFC1123Pattern
　s 使用当地时间的 SortableDateTimePattern（基于 ISO 8601）
　t ShortTimePattern
　T LongTimePattern
　u UniversalSortableDateTimePattern 用于显示通用时间的格式
　U 使用通用时间的完整日期和时间（长日期和长时间）
　y、Y YearMonthPattern
　
　下表列出了可被合并以构造自定义模式的模式。这些模式是区分大小写的；例如，识别“MM”，但不识别“mm”。如果自定义模式包含空白字符或用单引号括起来的字符，则输出字符串页也将包含这些字符。未定义为格式模式的一部分或未定义为格式字符的字符按其原义复制。
　
　格式模式 说明
　d 月中的某一天。一位数的日期没有前导零。
　dd 月中的某一天。一位数的日期有一个前导零。
　ddd 周中某天的缩写名称，在 AbbreviatedDayNames 中定义。
　dddd 周中某天的完整名称，在 DayNames 中定义。
　M 月份数字。一位数的月份没有前导零。
　MM 月份数字。一位数的月份有一个前导零。
　MMM 月份的缩写名称，在 AbbreviatedMonthNames 中定义。
　MMMM 月份的完整名称，在 MonthNames 中定义。
　y 不包含纪元的年份。如果不包含纪元的年份小于 10，则显示不具有前导零的年份。
　yy 不包含纪元的年份。如果不包含纪元的年份小于 10，则显示具有前导零的年份。
　yyyy 包括纪元的四位数的年份。
　gg 时期或纪元。如果要设置格式的日期不具有关联的时期或纪元字符串，则忽略该模式。
　h 12 小时制的小时。一位数的小时数没有前导零。
　hh 12 小时制的小时。一位数的小时数有前导零。
　H 24 小时制的小时。一位数的小时数没有前导零。
　HH 24 小时制的小时。一位数的小时数有前导零。
　m 分钟。一位数的分钟数没有前导零。
　mm 分钟。一位数的分钟数有一个前导零。
　s 秒。一位数的秒数没有前导零。
　ss 秒。一位数的秒数有一个前导零。
　f 秒的小数精度为一位。其余数字被截断。
　ff 秒的小数精度为两位。其余数字被截断。
　fff 秒的小数精度为三位。其余数字被截断。
　ffff 秒的小数精度为四位。其余数字被截断。
　fffff 秒的小数精度为五位。其余数字被截断。
　ffffff 秒的小数精度为六位。其余数字被截断。
　fffffff 秒的小数精度为七位。其余数字被截断。
　t 在 AMDesignator 或 PMDesignator 中定义的 AM/PM 指示项的第一个字符（如果存在）。
　tt 在 AMDesignator 或 PMDesignator 中定义的 AM/PM 指示项（如果存在）。
　z 时区偏移量（“+”或“-”后面仅跟小时）。一位数的小时数没有前导零。例如，太平洋标准时间是“-8”。
　zz 时区偏移量（“+”或“-”后面仅跟小时）。一位数的小时数有前导零。例如，太平洋标准时间是“-08”。
　zzz 完整时区偏移量（“+”或“-”后面跟有小时和分钟）。一位数的小时数和分钟数有前导零。例如，太平洋标准时间是“-08:00”。
　: 在 TimeSeparator 中定义的默认时间分隔符。
　/ 在 DateSeparator 中定义的默认日期分隔符。
　% c 其中 c 是格式模式（如果单独使用）。如果格式模式与原义字符或其他格式模式合并，则可以省略“%”字符。
　\ c 其中 c 是任意字符。照原义显示字符。若要显示反斜杠字符，请使用“\\”。
　
　只有上面第二个表中列出的格式模式才能用于创建自定义模式；在第一个表中列出的标准格式字符不能用于创建自定义模式。自定义模式的长度至少为两个字符；例如，
　
　DateTime.ToString( "d") 返回 DateTime 值；“d”是标准短日期模式。
　DateTime.ToString( "%d") 返回月中的某天；“%d”是自定义模式。
　DateTime.ToString( "d ") 返回后面跟有一个空白字符的月中的某天；“d”是自定义模式。
　
　比较方便的是,上面的参数可以随意组合,并且不会出错,多试试,肯定会找到你要的时间格式
　如要得到2005年06月 这样格式的时间
　可以这样写:
　date.ToString("yyyy年MM月", DateTimeFormatInfo.InvariantInfo)
　如此类推 
]]></description>
		</item>
		<item>
			<title>C#使用WIN32API来遍历文件和目录</title>
			<link>http://www.kingmx.com/article.php?id=14736</link>
			<pubDate>2006-12-15</pubDate>
			<description><![CDATA[
我们有时需要遍历某个目录下的文件和子目录，可以使用System.IO.DirectoryInfo.GetDirectories或GetFiles来获得目录下的所有的文件和子目录，当这个目录下的内容比较多时，这个操作就比较耗时间，有时我们仅仅需要知道某个目录下是否有子目录，这样的操作显然是浪费时间的。此时我们很容易想到三个Win32API函数 FindFirstFile，FindNextFile和FindClose。这三个API搭配使用就能遍历文件和子目录了，而且可以遍历的时候随时中止，避免无谓的操作。 
&nbsp;&nbsp; 
&nbsp;&nbsp;C#中可以使用foreach来遍历某个序列，遍历使用的对象必须实现 System.Collections.IEnumeable接口，而内部调用的遍历器则必须实现System.Collections.IEnumerator ， 为了使用方便，我们在使用FindFirstFile等API函数时封装为 IEnumerator，而且实际上是有条件封装的。 
&nbsp;&nbsp; 
&nbsp;&nbsp;这里很多人就会提到C#调用API的执行效率问题，认为应当用C，C++调用API才是正道，使用C#调用则有些鸡肋。但在我个人编程经历中，也有不少调用API的，经验发现其实效率问题不大，可以省略。我只是做常规的运行在PC机上面的软件，CPU通常超过1GHZ，而且无需考虑高实时性和高效率。若过于考虑效率问题会加大软件开发消耗。从工程开发管理方面看是不合理的。我应当解决比较突出的效率问题，不突出的影响不大的效率问题有时间才去解决。使用C#封装Win32API必然会降低执行效率，但是封装后使用方便快捷，综合考虑认为这是正确的。 
&nbsp;&nbsp; 
&nbsp;&nbsp;这里说一下“技术镀金”这个问题，所谓技术镀金就是开发人员在项目软件开发中过于追求技术的完美性，试图在技术上镀上一层完美的金壳，导致软件开发工作量加大，项目时间拉长，有可能导致项目的失败。我吃过“技术镀金”的苦头，现在我内心是追求完美的，但实际开发时经常有意压制追求完美的心思。 
&nbsp;&nbsp; 
&nbsp;&nbsp;现在继续探讨封装大计，本次封装重点在于实现IEnumerator,而IEnumeable只是IEnumerator的一个包装。IEnumerator实现方法 Reset ， MoveNext 和属性 Current，Reset方法用于重新设置遍历器，MoveNext用于查找下一个文件或目录，而Current返回当前文件或目录。 
&nbsp;&nbsp; 
&nbsp;&nbsp;这个遍历器还得注意FindClose的调用，必须在遍历完毕没有找到文件或子目录后调用，若不调用该API函数则会造成内存泄漏。 
&nbsp;&nbsp; 
&nbsp;&nbsp;根据上述设计，我写出如下代码，这段代码功能单一，希望有人能用得上 
&nbsp;&nbsp; 
&nbsp;&nbsp; 
&nbsp;&nbsp; 
&nbsp;&nbsp;/// &lt;summary&gt; 
&nbsp;&nbsp;/// 文件或目录遍历器,本类型为 FileDirectoryEnumerator 的一个包装 
&nbsp;&nbsp;/// &lt;/summary&gt; 
&nbsp;&nbsp;/// &lt;remarks&gt; 
&nbsp;&nbsp;/// 
&nbsp;&nbsp;/// 编写 袁永福 （ http://www.xdesigner.cn ）2006-12-8 
&nbsp;&nbsp;/// 
&nbsp;&nbsp;/// 以下代码演示使用这个文件目录遍历器 
&nbsp;&nbsp;/// 
&nbsp;&nbsp;/// FileDirectoryEnumerable e = new FileDirectoryEnumerable(); 
&nbsp;&nbsp;/// e.SearchPath = @"c:\"; 
&nbsp;&nbsp;/// e.ReturnStringType = true ; 
&nbsp;&nbsp;/// e.SearchPattern = "*.exe"; 
&nbsp;&nbsp;/// e.SearchDirectory = false ; 
&nbsp;&nbsp;/// e.SearchFile = true; 
&nbsp;&nbsp;/// foreach (object name in e) 
&nbsp;&nbsp;/// { 
&nbsp;&nbsp;/// System.Console.WriteLine(name); 
&nbsp;&nbsp;/// } 
&nbsp;&nbsp;/// System.Console.ReadLine(); 
&nbsp;&nbsp;/// 
&nbsp;&nbsp;///&lt;/remarks&gt; 
&nbsp;&nbsp;public class FileDirectoryEnumerable : System.Collections.IEnumerable 
&nbsp;&nbsp;{ 
&nbsp;&nbsp; private bool bolReturnStringType = true; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 是否以字符串方式返回查询结果,若返回true则当前对象返回为字符串, 
&nbsp;&nbsp; /// 否则返回 System.IO.FileInfo或System.IO.DirectoryInfo类型 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public bool ReturnStringType 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return bolReturnStringType; } 
&nbsp;&nbsp; set { bolReturnStringType = value; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; 
&nbsp;&nbsp; private string strSearchPattern = "*"; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 文件或目录名的通配符 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public string SearchPattern 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return strSearchPattern; } 
&nbsp;&nbsp; set { strSearchPattern = value; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; private string strSearchPath = null; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 搜索路径,必须为绝对路径 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public string SearchPath 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return strSearchPath; } 
&nbsp;&nbsp; set { strSearchPath = value; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; 
&nbsp;&nbsp; private bool bolSearchForFile = true; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 是否查找文件 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public bool SearchForFile 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return bolSearchForFile; } 
&nbsp;&nbsp; set { bolSearchForFile = value; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; private bool bolSearchForDirectory = true; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 是否查找子目录 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public bool SearchForDirectory 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return bolSearchForDirectory; } 
&nbsp;&nbsp; set { bolSearchForDirectory = value; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; 
&nbsp;&nbsp; private bool bolThrowIOException = true; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 发生IO错误时是否抛出异常 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public bool ThrowIOException 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return this.bolThrowIOException; } 
&nbsp;&nbsp; set { this.bolThrowIOException = value; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 返回内置的文件和目录遍历器 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; /// &lt;returns&gt;遍历器对象&lt;/returns&gt; 
&nbsp;&nbsp; public System.Collections.IEnumerator GetEnumerator() 
&nbsp;&nbsp; { 
&nbsp;&nbsp; FileDirectoryEnumerator e = new FileDirectoryEnumerator(); 
&nbsp;&nbsp; e.ReturnStringType = this.bolReturnStringType; 
&nbsp;&nbsp; e.SearchForDirectory = this.bolSearchForDirectory; 
&nbsp;&nbsp; e.SearchForFile = this.bolSearchForFile; 
&nbsp;&nbsp; e.SearchPath = this.strSearchPath; 
&nbsp;&nbsp; e.SearchPattern = this.strSearchPattern; 
&nbsp;&nbsp; e.ThrowIOException = this.bolThrowIOException; 
&nbsp;&nbsp; myList.Add(e); 
&nbsp;&nbsp; return e; 
&nbsp;&nbsp; } 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 关闭对象 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public void Close() 
&nbsp;&nbsp; { 
&nbsp;&nbsp; foreach (FileDirectoryEnumerator e in myList) 
&nbsp;&nbsp; { 
&nbsp;&nbsp; e.Close(); 
&nbsp;&nbsp; } 
&nbsp;&nbsp; myList.Clear(); 
&nbsp;&nbsp; }&nbsp;
&nbsp; private System.Collections.ArrayList myList = new System.Collections.ArrayList(); 
&nbsp;&nbsp; 
&nbsp;&nbsp;}//public class FileDirectoryEnumerable : System.Collections.IEnumerable 
&nbsp;&nbsp; 
&nbsp;&nbsp;/// &lt;summary&gt; 
&nbsp;&nbsp;/// 文件和目录的遍历器 
&nbsp;&nbsp;/// &lt;/summary&gt; 
&nbsp;&nbsp;/// &lt;remarks&gt;本对象为Win32API函数 FindFirstFile , FindNextFile 
&nbsp;&nbsp;/// 和 FindClose 的一个包装 
&nbsp;&nbsp;/// 
&nbsp;&nbsp;/// 以下代码演示使用了 FileDirectoryEnumerator 
&nbsp;&nbsp;/// 
&nbsp;&nbsp;/// FileDirectoryEnumerator e = new FileDirectoryEnumerator(); 
&nbsp;&nbsp;/// e.SearchPath = @"c:\"; 
&nbsp;&nbsp;/// e.Reset(); 
&nbsp;&nbsp;/// e.ReturnStringType = true ; 
&nbsp;&nbsp;/// while (e.MoveNext()) 
&nbsp;&nbsp;/// { 
&nbsp;&nbsp;/// System.Console.WriteLine 
&nbsp;&nbsp;/// ( e.LastAccessTime.ToString("yyyy-MM-dd HH:mm:ss") 
&nbsp;&nbsp;/// + " " + e.FileLength + " \t" + e.Name ); 
&nbsp;&nbsp;/// } 
&nbsp;&nbsp;/// e.Close(); 
&nbsp;&nbsp;/// System.Console.ReadLine(); 
&nbsp;&nbsp;/// 
&nbsp;&nbsp;/// 编写 袁永福 （ http://www.xdesigner.cn ）2006-12-8&lt;/remarks&gt; 
&nbsp;&nbsp;public class FileDirectoryEnumerator : System.Collections.IEnumerator 
&nbsp;&nbsp;{ 
&nbsp;&nbsp; 
&nbsp;&nbsp; #region 表示对象当前状态的数据和属性 ********************************** 
&nbsp;&nbsp; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 当前对象 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; private object objCurrentObject = null; 
&nbsp;&nbsp; 
&nbsp;&nbsp; private bool bolIsEmpty = false; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 该目录为空 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public bool IsEmpty 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return bolIsEmpty; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; private int intSearchedCount = 0; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 已找到的对象的个数 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public int SearchedCount 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return intSearchedCount; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; private bool bolIsFile = true; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 当前对象是否为文件,若为true则当前对象为文件,否则为目录 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public bool IsFile 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return bolIsFile; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; private int intLastErrorCode = 0; 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 最后一次操作的Win32错误代码 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public int LastErrorCode 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return intLastErrorCode; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 当前对象的名称 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public string Name 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get 
&nbsp;&nbsp; { 
&nbsp;&nbsp; if (this.objCurrentObject != null) 
&nbsp;&nbsp; { 
&nbsp;&nbsp; if (objCurrentObject is string) 
&nbsp;&nbsp; return (string)this.objCurrentObject; 
&nbsp;&nbsp; else 
&nbsp;&nbsp; return ((System.IO.FileSystemInfo)this.objCurrentObject).Name; 
&nbsp;&nbsp; } 
&nbsp;&nbsp; return null; 
&nbsp;&nbsp; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 当前对象属性 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public System.IO.FileAttributes Attributes 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get { return (System.IO.FileAttributes)myData.dwFileAttributes; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 当前对象创建时间 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public System.DateTime CreationTime 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get 
&nbsp;&nbsp; { 
&nbsp;&nbsp; long time = ToLong(myData.ftCreationTime_dwHighDateTime, myData.ftCreationTime_dwLowDateTime); 
&nbsp;&nbsp; System.DateTime dtm = System.DateTime.FromFileTimeUtc(time); 
&nbsp;&nbsp; return dtm.ToLocalTime(); 
&nbsp;&nbsp; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 当前对象最后访问时间 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public System.DateTime LastAccessTime 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get 
&nbsp;&nbsp; { 
&nbsp;&nbsp; long time = ToLong(myData.ftLastAccessTime_dwHighDateTime, myData.ftLastAccessTime_dwLowDateTime); 
&nbsp;&nbsp; System.DateTime dtm = System.DateTime.FromFileTimeUtc(time); 
&nbsp;&nbsp; return dtm.ToLocalTime(); 
&nbsp;&nbsp; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 当前对象最后保存时间 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public System.DateTime LastWriteTime 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get 
&nbsp;&nbsp; { 
&nbsp;&nbsp; long time = ToLong(myData.ftLastWriteTime_dwHighDateTime, myData.ftLastWriteTime_dwLowDateTime); 
&nbsp;&nbsp; System.DateTime dtm = System.DateTime.FromFileTimeUtc(time); 
&nbsp;&nbsp; return dtm.ToLocalTime(); 
&nbsp;&nbsp; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; /// &lt;summary&gt; 
&nbsp;&nbsp; /// 当前文件长度,若为当前对象为文件则返回文件长度,若当前对象为目录则返回0 
&nbsp;&nbsp; /// &lt;/summary&gt; 
&nbsp;&nbsp; public long FileLength 
&nbsp;&nbsp; { 
&nbsp;&nbsp; get 
&nbsp;&nbsp; { 
&nbsp;&nbsp; if (this.bolIsFile) 
&nbsp;&nbsp; return ToLong(myData.nFileSizeHigh, myData.nFileSizeLow); 
&nbsp;&nbsp; else 
&nbsp;&nbsp; return 0; 
&nbsp;&nbsp; } 
&nbsp;&nbsp; } 
&nbsp;&nbsp; 
&nbsp;&nbsp; #endregion 
]]></description>
		</item>
		<item>
			<title>.NET1.1开发FTP客户端</title>
			<link>http://www.kingmx.com/article.php?id=14669</link>
			<pubDate>2006-12-12</pubDate>
			<description><![CDATA[&nbsp; 前面我的一篇文章提到使用CUTEFTP的FTP引擎制作.NET的FTP上传客户端，但是这是个很郁闷的事情，首先，需要在注册表中注册这个COM，CUTEFTP的官方站提供了一段注册表写法的文章，这还好说。最关键的是，在使用这个组建的时候还需要注册产品。不会有任何人希望用户在用软件的时候却还要注册别的公司的产品先。
&nbsp;&nbsp;&nbsp; 前面之所以写采用CUTEFTP的引擎做客户端主要是为了方便，在一台已经安装CUTEFTP的PC上使用还是很方便的，但是我们还是希望开发独立的软件。

&nbsp;&nbsp;&nbsp; 实际上采用FTP进行文件传输在搞清楚FTP命令和数据连接方式后做起来也不是很难，毕竟FTP是一个公共的协议。

&nbsp;&nbsp;&nbsp; 以下是本人写的一个简单的示例，其中的功能只有上传文件，工作模式基本说明了FTP的原理，很容易从例子中推敲出其他FTP的功能。&nbsp; 在近几天的BLOG文章中将陆续推出一些资料信息。

&nbsp;&nbsp;&nbsp; 另外，.NET2.0中在System.Net名称空间下已经封装了FTP的几个类，可以直接使用，非常方面，但是考虑到客户端对.net的兼容问题，我还是觉得采用1.1的比较好，虽然费事，但也灵活。


using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Net.Sockets;

using System.IO;

&nbsp;

namespace FTPUpLoad

{

&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp; /// Main 的摘要说明。

&nbsp;&nbsp;&nbsp;&nbsp; ///

&nbsp;&nbsp;&nbsp;&nbsp; ///存在的问题

&nbsp;&nbsp;&nbsp;&nbsp; ///1.中文文件名 √

&nbsp;&nbsp;&nbsp;&nbsp; ///2.文件分批读取 √

&nbsp;&nbsp;&nbsp;&nbsp; ///3.进度显示

&nbsp;&nbsp;&nbsp;&nbsp; ///4.扩展到控件中

&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp; public class MainForm : System.Windows.Forms.Form

&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private System.Windows.Forms.TextBox msg;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private System.Windows.Forms.Button commBtn;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private System.Windows.Forms.Button pathBtn;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private System.Windows.Forms.OpenFileDialog openPath;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private System.Windows.Forms.TextBox path;

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private TcpClient tcp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private NetworkStream&nbsp;ns;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private System.Windows.Forms.Label process;

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///必需的设计器变量。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private System.ComponentModel.Container components = null;

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public MainForm()

&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; // Windows 窗体设计器支持所必需的

&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; InitializeComponent();

&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; // TODO: 在 InitializeComponent 调用后添加任何构造函数代码

&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; ///&lt;summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///清理所有正在使用的资源。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected override void Dispose( bool disposing )

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( disposing )

&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; if(components != 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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; components.Dispose();

&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; base.Dispose( disposing );

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///应用程序的主入口点。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [STAThread]

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main() 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Application.Run(new MainForm());

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #region Windows 窗体设计器生成的代码

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///设计器支持所需的方法 - 不要使用代码编辑器修改

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///此方法的内容。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void InitializeComponent()

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.msg = new System.Windows.Forms.TextBox();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.path = new System.Windows.Forms.TextBox();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.commBtn = new System.Windows.Forms.Button();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pathBtn = new System.Windows.Forms.Button();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.openPath = new System.Windows.Forms.OpenFileDialog();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.process = new System.Windows.Forms.Label();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.SuspendLayout();

&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; // msg

&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; this.msg.Location = new System.Drawing.Point(8, 152);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.msg.Multiline = true;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.msg.Name = "msg";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.msg.Size = new System.Drawing.Size(552, 192);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.msg.TabIndex = 3;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.msg.Text = "";

&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; // path

&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; this.path.Location = new System.Drawing.Point(8, 8);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.path.Name = "path";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.path.Size = new System.Drawing.Size(440, 21);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.path.TabIndex = 4;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.path.Text = "";

&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; // commBtn

&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; this.commBtn.Location = new System.Drawing.Point(232, 48);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.commBtn.Name = "commBtn";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.commBtn.TabIndex = 5;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.commBtn.Text = "Post";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.commBtn.Click += new System.EventHandler(this.commBtn_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; // pathBtn

&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; this.pathBtn.Location = new System.Drawing.Point(464, 8);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pathBtn.Name = "pathBtn";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pathBtn.TabIndex = 6;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pathBtn.Text = "浏览…";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pathBtn.Click += new System.EventHandler(this.pathBtn_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; // openPath

&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; this.openPath.FileOk += new System.ComponentModel.CancelEventHandler(this.openPath_FileOk);

&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; // process

&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; this.process.Location = new System.Drawing.Point(176, 112);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.process.Name = "process";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.process.Size = new System.Drawing.Size(248, 23);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.process.TabIndex = 7;

&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; // MainForm

&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; this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ClientSize = new System.Drawing.Size(568, 358);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Controls.Add(this.process);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Controls.Add(this.pathBtn);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Controls.Add(this.commBtn);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Controls.Add(this.path);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Controls.Add(this.msg);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Name = "MainForm";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Text = "Main";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Load += new System.EventHandler(this.MainForm_Load);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ResumeLayout(false);

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void MainForm_Load(object sender, System.EventArgs e)

&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; tcp = new TcpClient("192.168.1.88",21);

&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; WriteNetworkStream(ref ns,"USER Anonymous");

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg.Text += ReadNetworkStream(ref ns);

&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; WriteNetworkStream(ref ns,"PASS ");

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg.Text += ReadNetworkStream(ref ns);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void pathBtn_Click(object sender, System.EventArgs e)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; openPath.ShowDialog();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void openPath_FileOk(object sender, System.ComponentModel.CancelEventArgs e)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path.Text = openPath.FileName;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void commBtn_Click(object sender, System.EventArgs e)

&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; WriteNetworkStream(ref ns,"CWD /");

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg.Text+=ReadNetworkStream(ref ns);

&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; WriteNetworkStream(ref ns,"PASV");

&nbsp;

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //获取服务器PASV被动模式打开的数据连接的IP和端口信息

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string str = ReadNetworkStream(ref ns);

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg.Text+=str;

&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; WriteNetworkStreamChs(ref ns,"STOR "+FileName(path.Text.Trim()));

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //组合IP和端口

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str =str.Substring(str.IndexOf("(")+1,str.IndexOf(")")-str.IndexOf("(")-1);

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string ip = str.Split(',')[0]+"."+str.Split(',')[1]+"."+str.Split(',')[2]+"."+str.Split(',')[3];

&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; int port = int.Parse(str.Split(',')[4])*256+int.Parse(str.Split(',')[5]);

&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; FileStream fs = File.OpenRead(path.Text.Trim());

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义一个8字节数组做为缓冲区

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] b = new byte[8];

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //建立数据传输的TCP连接

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TcpClient tcp2 = new TcpClient(ip,port);

&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; NetworkStream ns2 = tcp2.GetStream();

&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; //每8字节读取文件流中数据到网络流中，并写入到基础存储设备，采用这个方式避免了由于一次性读取大数据量到内存中造成客户机内存使用过量。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(fs.Read(b,0,b.Length)&gt;0)

&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; //建立数据的TCP连接并将文件流的内容写入到网络流

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns2.Write(b,0,b.Length);&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; ns2.Flush();

&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //关闭所用的连接

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fs.Close();

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns2.Close();

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tcp2.Close();

&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; msg.Text += ReadNetworkStream(ref ns);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg.Text += ReadNetworkStream(ref ns);

&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; #region //功能函数和方法

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// ASCII编码的命令请求

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;param name="ns"&gt;命令传输网络流&lt;/param&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;param name="comm"&gt;命令字符串&lt;/param&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;returns&gt;&lt;/returns&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected string WriteNetworkStream(ref NetworkStream ns,string comm)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns = tcp.GetStream();

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] b = new byte[1024];

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b = System.Text.Encoding.ASCII.GetBytes(comm+"\r\n");

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns.Write(b,0,b.Length);

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns.Flush();

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Empty;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///中文编码方式的命令请求

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;param name="ns"&gt;命令传输网络流&lt;/param&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;param name="comm"&gt;命令字符串&lt;/param&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;returns&gt;&lt;/returns&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected string WriteNetworkStreamChs(ref NetworkStream ns,string comm) 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns = tcp.GetStream();

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] b = new byte[1024];

&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; b = System.Text.Encoding.GetEncoding("GB2312").GetBytes(comm+"\r\n");

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns.Write(b,0,b.Length);

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns.Flush();

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Empty;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///获取服务器相应字符串

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;param name="ns"&gt;命令传输网络流&lt;/param&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;returns&gt;服务器相应字符串&lt;/returns&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected string ReadNetworkStream(ref NetworkStream ns)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns = tcp.GetStream();

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] b = new byte[1024];

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns.Read(b,0,b.Length);

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ns.Flush();

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return System.Text.Encoding.ASCII.GetString(b);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///获取所选文件路径的文件名

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;/summary&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;param name="path"&gt;文件路径&lt;/param&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///&lt;returns&gt;文件名&lt;/returns&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected string FileName(string path)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return path.Substring(path.LastIndexOf("\\")+1);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

&nbsp;&nbsp;&nbsp;&nbsp; }

}

]]></description>
		</item>
		<item>
			<title>对C#委托及事件委托的理解</title>
			<link>http://www.kingmx.com/article.php?id=14585</link>
			<pubDate>2006-11-30</pubDate>
			<description><![CDATA[
委托的声明 
public delegate void MyDelegate(string str);
注
1.委托的定义和方法的定义类似，只是在前面加了一个delegate,但委托不是方法，它是一种类型。是一种特殊的类型,看成是一种新的对象类型比较好理解。用于对与该委托有相

同签名的方法调用。
2.委托相当于C++中的函数指针，但它是类型安全的。
3.委托是从System.Delegate派生，但不能象定义常规类型一样直接从System.Delegate派生，对委托的声明只能通过上面的声明格式进行定义。关键字delegate通知编译器这是一

个委托类型，从而在编译的时候对该类进行封装,对这一过程C#定义了专门的语法来处理这一过程。
4.不能从一个委托类型进行派生，因为它也是默认sealed的
5.委托即可以对静态方法进行调用也可以对实例方法进行调用。
6.每个委托类型包含一个自己的调用列表，当组合一个委托或从一个委托中删除一个委托时都将产生个新的调用列表。
7.两个不同类型的委托即使它们有相同的签名和返回值，但还是两个不同类型的委托。但其实在使用中可看作是相同的。

委托的比较

C#中对委托定义了两个操作符 == 和 !=
在以下情况下两个委托是相等的：
1.当两个委托都同时为null的时候
2.当两个委托都不为null时,下列情况下是相等的。
a.当两个委托的各自的调用列表只含有一个入口点的时候
&nbsp;&nbsp; 在下列情况下是相等的
&nbsp;&nbsp; (1) 调用同一对象的同一静态方法
&nbsp;&nbsp; (2) 调用同一对象的同一实例方法
b.当两个委托具有多个入口点时
&nbsp;&nbsp; 在下列情况下是相等的
&nbsp;&nbsp; (1)只有当它们调用列表中的调用的方法按顺序都一一对应相同的对象及对象的同一方法的时候

如上所述的两个不同类型的委托但是它们具有相同的签名和返回值时，只要满足上述条件的，即使它们类型不同，但比较的结果也是相同的。

委托的异常处理

当调用该委托的方法中发生了异常时，首先在调用该委托的方法中搜寻catch语句块。如果没有，则去该委托调用的方法中去寻找有没有catch语句块，这和调用方法发生异常的处

理是一样的。

当调用一个为null的委托即委托中列表中不存在调用方法时，将发生NullRefrenceException

委托的注意点:
当一个委托有多个入口点的时候,调用委托将依该委托的调用列表中的方法的顺序依次调用.这些方法共享一个参数集合,所以当委托有返回值的时候调用完这个委托后的返回值是最

后一个方法的返回值或是有out参数.如果该委托的参数为ref(引用类型),那么在招待第一个方法的时候如果对这个参数的值有所改变,那么这个改变将会影响到后面的方法调用.

委托的一个例子

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
&nbsp;&nbsp;&nbsp; class Program
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 创建一个委托实例，封装C类的静态方法M1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate d1 = new MyDelegate(C.M1);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d1("D1"); // M1

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 创建一个委托实例，封装C类的静态方法M2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate d2 = new MyDelegate(C.M2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d2("D2"); // M2

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 创建一个委托实例，封装C类的实例方法M3
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate d3 = new MyDelegate(new C().M3);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d3("D3"); // M3

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 从一个委托d3创建一个委托实例
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate d4 = new MyDelegate(d3);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d4("D4"); // M3

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 组合两个委托
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate d5 = d1 + d2;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d5 += d3;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d5("D5"); // M1,M2,M3

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 从组合委托中删除d3
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate d6 = d5 - d3;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d6("D6"); // M1,M2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d6 -= d3; // 虽然d6调用列表中已经没有d3了，但这样只是不可能的移除没有错误发生
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d6("D6"); // M1,M2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d6 -= d6;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //d6("D6"); 此时d6的调用列表为空，d6为null,所以引发System.NullReferenceException

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate d7 = new MyDelegate(C1.P1);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d7("D7"); // C1.P1

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyDelegate d8 = new MyDelegate(new C2().P1);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d8("D8"); // C2.P1

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; // 声明一个委托MyDelegate
&nbsp;&nbsp;&nbsp; public delegate void MyDelegate(string str);

&nbsp;&nbsp;&nbsp; public class C
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void M1(string str)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("From:C.M1:&nbsp;&nbsp; {0}", str);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void M2(string str)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("From:C.M2:&nbsp;&nbsp; {0}", str);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void M3(string str)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("From:C.M3:&nbsp;&nbsp; {0}", str);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; public class C1
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void P1(string str)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("From:C1.P1:&nbsp;&nbsp; {0}", str);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; public class C2
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void P1(string str)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("From:C2.P1:&nbsp;&nbsp; {0}", str);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; 
}

事件委托

事件概述

事件就是当对象或类状态发生改变时，对象或类发出的信息或通知。发出信息的对象或类称为"事件源",对事件进行处理的方法称为"接收者",通常事件源在发出状态改变信息时,它

并不知道由哪个事件接收者来处理.这就需要一种管理机制来协调事件源和接收者,C++中通过函数指针来完成的.在C#中事件使用委托来为触发时将调用的方法提供类型安全的封装

事件的声明

1.声明一个委托
public delegate void EventHandler(object sender, System.EventArgs e);

2.声明一个事件
public event EventHandler Changed;

3.引发一个事件
public OnChanged(EnventArgs e)
{
&nbsp;if ( Changed != null)
&nbsp;{
&nbsp; Changed(this,e);
&nbsp;}
}

4.定义事件处理程序
public MyText_OnChanged(Object sender,EventArgs e)
{
&nbsp;...
}

5.订阅事件(将事件处理程序添加到事件的调用列表中)

myText.Changed += EventHandler(MyText_OnChanged);

下面的一个小例子说明了怎样定义一个完整的事件机制:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
&nbsp;&nbsp;&nbsp; class Program
&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)
&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; MyText myText = new MyText();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将事件处理程序添加到事件的调用列表中(即事件布线)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myText.Changed += new MyText.ChangedEventHandler(myText_Changed);&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; string str = "";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (str != "quit")
&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; Console.WriteLine("please enter a string:");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str = Console.ReadLine();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myText.Text = str;
&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; // 对Change事件处理的程序
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static void myText_Changed(object sender, EventArgs e)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("text has been changed&nbsp; :{0}n" ,((MyText)sender).Text);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; }&nbsp; 

&nbsp;&nbsp;&nbsp; public class MyText
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string _text = "";

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 定义事件的委托
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public delegate void ChangedEventHandler(object sender, EventArgs e);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 定义一个事件
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public event ChangedEventHandler Changed;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 用以触发Change事件
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected virtual void OnChanged(EventArgs e)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.Changed != null)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Changed(this, e);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Text属性
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string Text
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return this._text; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set
&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; this._text = value;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 文本改变时触发Change事件
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.OnChanged(new EventArgs());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; }
}&nbsp;&nbsp; 

自己的一些浅略的理解,还请大家多多批评指正!

http://www.cnblogs.com/ktgu/archive/2006/11/28/575279.html

]]></description>
		</item>
		<item>
			<title>C#程序实现动态调用DLL的研究</title>
			<link>http://www.kingmx.com/article.php?id=14584</link>
			<pubDate>2006-11-30</pubDate>
			<description><![CDATA[
摘&nbsp;要：在《csdn开发高手》2004年第03期中的《化功大法——将DLL嵌入EXE》一文，介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件，在可执行文件运行时，自动从资源中释放出来，通过静态加载延迟实现ＤＬＬ函数的动态加载，程序退出后实现临时文件的自动删除，从而为解决“DLL Hell”提供了一种解决方案。这是一个很好的设计思想，而且该作者也用C++实现了，在Internet上也有相似的VB程序，但在某一技术论坛上提起这种设计方法时，有网友提出：“这种方法好是好，但就是启动速度太慢”。这是因为程序启动时实现DLL释放，然后再加载释放出来的DLL，这个过程会耗费一定的时间。鉴于此问题，经过思索，提出另一个设计方案：DLL作为资源文件嵌入程序，但不需进行DLL释放及其重新加载。本文就是对该设计方案的原理分析及使用C#编程来实现该设计方案。

&nbsp;

关键词：动态调用DLL，嵌入DLL，C#

&nbsp;

正&nbsp;文：

一、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DLL与应用程序

动态链接库（也称为DLL，即为“Dynamic Link Library”的缩写）是Microsoft Windows最重要的组成要素之一，打开Windows系统文件夹，你会发现文件夹中有很多DLL文件，Windows就是将一些主要的系统功能以DLL模块的形式实现。 

动态链接库是不能直接执行的，也不能接收消息，它只是一个独立的文件，其中包含能被程序或其它DLL调用来完成一定操作的函数(方法。注：C#中一般称为“方法”)，但这些函数不是执行程序本身的一部分，而是根据进程的需要按需载入，此时才能发挥作用。

DLL只有在应用程序需要时才被系统加载到进程的虚拟空间中，成为调用进程的一部分，此时该DLL也只能被该进程的线程访问，它的句柄可以被调用进程所使用，而调用进程的句柄也可以被该DLL所使用。在内存中，一个DLL只有一个实例，且它的编制与具体的编程语言和编译器都没有关系，所以可以通过DLL来实现混合语言编程。DLL函数中的代码所创建的任何对象（包括变量）都归调用它的线程或进程所有。

下面列出了当程序使用 DLL 时提供的一些优点：[1]

1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用较少的资源

当多个程序使用同一个函数库时，DLL 可以减少在磁盘和物理内存中加载的代码的重复量。这不仅可以大大影响在前台运行的程序，而且可以大大影响其他在 Windows 操作系统上运行的程序。&nbsp;

2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 推广模块式体系结构

DLL 有助于促进模块式程序的开发。这可以帮助您开发要求提供多个语言版本的大型程序或要求具有模块式体系结构的程序。模块式程序的一个示例是具有多个可以在运行时动态加载的模块的计帐程序。&nbsp;

3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 简化部署和安装

当 DLL 中的函数需要更新或修复时，部署和安装 DLL 不要求重新建立程序与该 DLL 的链接。此外，如果多个程序使用同一个 DLL，那么多个程序都将从该更新或修复中获益。当您使用定期更新或修复的第三方 DLL 时，此问题可能会更频繁地出现。

二、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DLL的调用

每种编程语言调用DLL的方法都不尽相同，在此只对用C#调用DLL的方法进行介绍。首先,您需要了解什么是托管,什么是非托管。一般可以认为：非托管代码主要是基于win 32平台开发的DLL，activeX的组件，托管代码是基于.net平台开发的。如果您想深入了解托管与非托管的关系与区别，及它们的运行机制，请您自行查找资料，本文件在此不作讨论。

(一)&nbsp;&nbsp;&nbsp;&nbsp; 调用DLL中的非托管函数一般方法

首先，应该在C#语言源程序中声明外部方法，其基本形式是：

[DLLImport(“DLL文件”)]

修饰符 extern 返回变量类型 方法名称&nbsp;（参数列表）

其中：

DLL文件：包含定义外部方法的库文件。

修饰符：&nbsp;访问修饰符，除了abstract以外在声明方法时可以使用的修饰符。

返回变量类型：在DLL文件中你需调用方法的返回变量类型。

方法名称：在DLL文件中你需调用方法的名称。

参数列表：在DLL文件中你需调用方法的列表。

注意：需要在程序声明中使用System.Runtime.InteropServices命名空间。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DllImport只能放置在方法声明上。

DLL文件必须位于程序当前目录或系统定义的查询路径中（即：系统环境变量中Path所设置的路径）。

返回变量类型、方法名称、参数列表一定要与DLL文件中的定义相一致。

&nbsp;

若要使用其它函数名，可以使用EntryPoint属性设置，如：

[DllImport("user32.dll", EntryPoint="MessageBoxA")]

static extern int MsgBox(int hWnd, string msg, string caption, int type);

其它可选的 DllImportAttribute 属性：

CharSet 指示用在入口点中的字符集，如：CharSet=CharSet.Ansi；

SetLastError 指示方法是否保留 Win32"上一错误"，如：SetLastError=true；

ExactSpelling 指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配，如：ExactSpelling=false；

PreserveSig指示方法的签名应当被保留还是被转换， 如：PreserveSig=true；

CallingConvention指示入口点的调用约定， 如：CallingConvention=CallingConvention.Winapi；

&nbsp;

此外，关于“数据封送处理”及“封送数字和逻辑标量”请参阅其它一些文章[2]。

C#例子：

1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 启动VS.NET，新建一个项目，项目名称为“Tzb”，模板为“Windows 应用程序”。

2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在“工具箱”的“ Windows 窗体”项中双击“Button”项，向“Form1”窗体中添加一个按钮。

3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 改变按钮的属性：Name为 “B1”，Text为 “用DllImport调用DLL弹出提示框”，并将按钮B1调整到适当大小，移到适当位置。

4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在类视图中双击“Form1”，打开“Form1．cs”代码视图，在“namespace Tzb”上面输入“using System.Runtime.InteropServices;”，以导入该命名空间。

5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在“Form1．cs［设计］”视图中双击按钮B1，在“B1_Click”方法上面使用关键字 static 和 extern 声明方法“MsgBox”，将 DllImport 属性附加到该方法，这里我们要使用的是“user32．dll”中的“MessageBoxA”函数，具体代码如下：





[DllImport("user32.dll", EntryPoint="MessageBoxA")] 

static extern int MsgBox(int hWnd, string msg, string caption, int type); 

然后在“B1_Click”方法体内添加如下代码，以调用方法“MsgBox”：





MsgBox(0," 这就是用 DllImport 调用 DLL 弹出的提示框哦！ "," 挑战杯 ",0x30); 

&nbsp;

6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 按“F5”运行该程序，并点击按钮B1，便弹出如下提示框：



&nbsp;

(二)&nbsp;&nbsp;&nbsp;&nbsp; 动态装载、调用DLL中的非托管函数

在上面已经说明了如何用DllImport调用DLL中的非托管函数，但是这个是全局的函数，假若DLL中的非托管函数有一个静态变量S，每次调用这个函数的时候，静态变量S就自动加1。结果，当需要重新计数时，就不能得出想要的结果。下面将用例子说明：

1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DLL的创建

1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 启动Visual C++ 6.0；

2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 新建一个“Win32 Dynamic-Link Library”工程，工程名称为“Count”；

3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在“Dll kind”选择界面中选择“A simple dll project”；

4)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开Count.cpp，添加如下代码：





// 导出函数，使用“ _stdcall ” 标准调用 

extern "C" _declspec(dllexport)int _stdcall count(int init); 





int _stdcall count(int init) 

{//count 函数，使用参数 init 初始化静态的整形变量 S ，并使 S 自加 1 后返回该值 

static int S=init; 

S++; 

return S; 

} 

5)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 按“F7”进行编译，得到Count.dll（在工程目录下的Debug文件夹中）。

&nbsp;

2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用DllImport调用DLL中的count函数

1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开项目“Tzb”，向“Form1”窗体中添加一个按钮。

2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 改变按钮的属性：Name为 “B2”，Text为 “用DllImport调用DLL中count函数”，并将按钮B1调整到适当大小，移到适当位置。

3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开“Form1．cs”代码视图，使用关键字 static 和 extern 声明方法“count”，并使其具有来自 Count.dll 的导出函数count的实现，代码如下：

&nbsp;





[DllImport("Count.dll")] 

static extern int count(int init); 

4)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在“Form1．cs［设计］”视图中双击按钮B2，在“B2_Click”方法体内添加如下代码：





MessageBox.Show(" 用 DllImport 调用 DLL 中的 count 函数， n 传入的实参为 0 ，得到的结果是： "+count(0).ToString()," 挑战杯 "); 

MessageBox.Show(" 用 DllImport 调用 DLL 中的 count 函数， n 传入的实参为 10 ，得到的结果是： "+count(10).ToString()+"n 结果可不是想要的 11 哦！！！ "," 挑战杯 "); 

MessageBox.Show(" 所得结果表明： n 用 DllImport 调用 DLL 中的非托管 n 函数是全局的、静态的函数！！！ "," 挑战杯 "); 

&nbsp;

5)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 把Count.dll复制到项目“Tzb”的binDebug文件夹中，按“F5”运行该程序，并点击按钮B2，便弹出如下三个提示框：

&nbsp;

   

第1个提示框显示的是调用“count(0)”的结果，第2个提示框显示的是调用“count(10)”的结果，由所得结果可以证明“用DllImport调用DLL中的非托管函数是全局的、静态的函数”。所以，有时候并不能达到我们目的，因此我们需要使用下面所介绍的方法：C#动态调用DLL中的函数。

&nbsp;

&nbsp;&nbsp;&nbsp; 

3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C#动态调用DLL中的函数

因为C#中使用DllImport是不能像动态load/unload assembly那样，所以只能借助API函数了。在kernel32.dll中，与动态库调用有关的函数包括[3]：

①LoadLibrary（或MFC 的AfxLoadLibrary），装载动态库。&nbsp;

②GetProcAddress，获取要引入的函数，将符号名或标识号转换为DLL内部地址。

③FreeLibrary（或MFC的AfxFreeLibrary），释放动态链接库。

它们的原型分别是：

HMODULE LoadLibrary(LPCTSTR lpFileName);

FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);

BOOL FreeLibrary(HMODULE hModule);

&nbsp;

现在，我们可以用IntPtr hModule=LoadLibrary(“Count.dll”);来获得Dll的句柄,用IntPtr farProc=GetProcAddress(hModule,”_count@4”);来获得函数的入口地址。

但是，知道函数的入口地址后，怎样调用这个函数呢？因为在C#中是没有函数指针的，没有像C++那样的函数指针调用方式来调用函数，所以我们得借助其它方法。经过研究，发现我们可以通过结合使用System.Reflection.Emit及System.Reflection.Assembly里的类和函数达到我们的目的。为了以后使用方便及实现代码的复用，我们可以编写一个类。

1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dld类的编写：

1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开项目“Tzb”，打开类视图，右击“Tzb”，选择“添加”--&gt;“类”，类名设置为“dld”，即dynamic loading dll 的每个单词的开头字母。

2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 添加所需的命名空间及声明参数传递方式枚举：





using System.Runtime.InteropServices; // 用 DllImport 需用此 命名空间 

using System.Reflection; // 使用 Assembly 类需用此 命名空间 

using System.Reflection.Emit; // 使用 ILGenerator 需用此 命名空间 

&nbsp; 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在“public class dld”上面添加如下代码声明参数传递方式枚举：





/// &lt;summary&gt; 

/// 参数传递方式枚举 ,ByValue 表示值传递 ,ByRef 表示址传递 

/// &lt;/summary&gt; 

public enum ModePass 

{ 

ByValue = 0x0001, 

ByRef = 0x0002 

} 

&nbsp;

3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 声明LoadLibrary、GetProcAddress、FreeLibrary及私有变量hModule和farProc：





/// &lt;summary&gt; 

/// 原型是 :HMODULE LoadLibrary(LPCTSTR lpFileName); 

/// &lt;/summary&gt; 

/// &lt;param name="lpFileName"&gt;DLL 文件名 &lt;/param&gt; 

/// &lt;returns&gt; 函数库模块的句柄 &lt;/returns&gt; 

[DllImport("kernel32.dll")] 

static extern IntPtr LoadLibrary(string lpFileName); 

/// &lt;summary&gt; 

/// 原型是 : FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName); 

/// &lt;/summary&gt; 

/// &lt;param name="hModule"&gt; 包含需调用函数的函数库模块的句柄 &lt;/param&gt; 

/// &lt;param name="lpProcName"&gt; 调用函数的名称 &lt;/param&gt; 

/// &lt;returns&gt; 函数指针 &lt;/returns&gt; 

[DllImport("kernel32.dll")] 

static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); 

/// &lt;summary&gt; 

/// 原型是 : BOOL FreeLibrary(HMODULE hModule); 

/// &lt;/summary&gt; 

/// &lt;param name="hModule"&gt; 需释放的函数库模块的句柄 &lt;/param&gt; 

/// &lt;returns&gt; 是否已释放指定的 Dll&lt;/returns&gt; 

[DllImport("kernel32",EntryPoint="FreeLibrary",SetLastError=true)] 

static extern bool FreeLibrary(IntPtr hModule); 

/// &lt;summary&gt; 

/// Loadlibrary 返回的函数库模块的句柄 

/// &lt;/summary&gt; 

private IntPtr hModule=IntPtr.Zero; 

/// &lt;summary&gt; 

/// GetProcAddress 返回的函数指针 

/// &lt;/summary&gt; 

private IntPtr farProc=IntPtr.Zero; 

&nbsp;

4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 添加LoadDll方法，并为了调用时方便，重载了这个方法：

&nbsp;





/// &lt;summary&gt; 

/// 装载 Dll 

/// &lt;/summary&gt; 

/// &lt;param name="lpFileName"&gt;DLL 文件名 &lt;/param&gt; 

public void LoadDll(string lpFileName) 

{ 

hModule=LoadLibrary(lpFileName); 

if(hModule==IntPtr.Zero) 

throw(new Exception(" 没有找到 :"+lpFileName+"." )); 

} 

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 若已有已装载Dll的句柄，可以使用LoadDll方法的第二个版本：





public void LoadDll(IntPtr HMODULE) 

{ 

if(HMODULE==IntPtr.Zero) 

throw(new Exception(" 所传入的函数库模块的句柄 HMODULE 为空 ." )); 

hModule=HMODULE; 

} 

&nbsp;

5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 添加LoadFun方法，并为了调用时方便，也重载了这个方法，方法的具体代码及注释如下：





/// &lt;summary&gt; 

/// 获得函数指针 

/// &lt;/summary&gt; 

/// &lt;param name="lpProcName"&gt; 调用函数的名称 &lt;/param&gt; 

public void LoadFun(string lpProcName) 

{ // 若函数库模块的句柄为空，则抛出异常 

if(hModule==IntPtr.Zero) 

throw(new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !")); 

// 取得函数指针 

farProc = GetProcAddress(hModule,lpProcName); 

// 若函数指针，则抛出异常 

if(farProc==IntPtr.Zero) 

throw(new Exception(" 没有找到 :"+lpProcName+" 这个函数的入口点 ")); 

} 

/// &lt;summary&gt; 

/// 获得函数指针 

/// &lt;/summary&gt; 

/// &lt;param name="lpFileName"&gt; 包含需调用函数的 DLL 文件名 &lt;/param&gt; 

/// &lt;param name="lpProcName"&gt; 调用函数的名称 &lt;/param&gt; 

public void LoadFun(string lpFileName,string lpProcName) 

{ // 取得函数库模块的句柄 

hModule=LoadLibrary(lpFileName); 

// 若函数库模块的句柄为空，则抛出异常 

if(hModule==IntPtr.Zero) 

throw(new Exception(" 没有找到 :"+lpFileName+"." )); 

// 取得函数指针 

farProc = GetProcAddress(hModule,lpProcName); 

// 若函数指针，则抛出异常 

if(farProc==IntPtr.Zero) 

throw(new Exception(" 没有找到 :"+lpProcName+" 这个函数的入口点 ")); 

} 

&nbsp;

6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 添加UnLoadDll及Invoke方法，Invoke方法也进行了重载：





/// &lt;summary&gt; 

/// 卸载 Dll 

/// &lt;/summary&gt; 

public void UnLoadDll() 

{ 

FreeLibrary(hModule); 

hModule=IntPtr.Zero; 

farProc=IntPtr.Zero; 

} 

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Invoke方法的第一个版本：





/// &lt;summary&gt; 

/// 调用所设定的函数 

/// &lt;/summary&gt; 

/// &lt;param name="ObjArray_Parameter"&gt; 实参 &lt;/param&gt; 

/// &lt;param name="TypeArray_ParameterType"&gt; 实参类型 &lt;/param&gt; 

/// &lt;param name="ModePassArray_Parameter"&gt; 实参传送方式 &lt;/param&gt; 

/// &lt;param name="Type_Return"&gt; 返回类型 &lt;/param&gt; 

/// &lt;returns&gt; 返回所调用函数的 object&lt;/returns&gt; 

public object Invoke(object[] ObjArray_Parameter,Type[] TypeArray_ParameterType,ModePass[] ModePassArray_Parameter,Type Type_Return) 

{ 

// 下面 3 个 if 是进行安全检查 , 若不能通过 , 则抛出异常 

if(hModule==IntPtr.Zero) 

throw(new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !")); 

if(farProc==IntPtr.Zero) 

throw(new Exception(" 函数指针为空 , 请确保已进行 LoadFun 操作 !" ) ); 

if(ObjArray_Parameter.Length!=ModePassArray_Parameter.Length) 

throw(new Exception(" 参数个数及其传递方式的个数不匹配 ." ) ); 

// 下面是创建 MyAssemblyName 对象并设置其 Name 属性 

AssemblyName MyAssemblyName = new AssemblyName(); 

MyAssemblyName.Name = "InvokeFun"; 

// 生成单模块配件 
]]></description>
		</item>
		<item>
			<title>C#数据类型变量基础</title>
			<link>http://www.kingmx.com/article.php?id=14542</link>
			<pubDate>2006-11-29</pubDate>
			<description><![CDATA[

应用任何一种程序语言需要充分了解它提供的数据类型，这样才能明白它的功能与限制。在本文中，我解释了C#数据类型的特点及详细内容，以帮助开发者进一步掌握这门语言的用途。

在C#中可以定义两种变量类型：值类型和引用类型。值类型存储实际值，而引用类型则为对存储在内存中某处的值的引用。值类型在堆栈上分配，大多数程序语言都能应用它。引用类型在堆上分配，通常代表类实例。在C#代码中还可以定义自己的值和引用类型。

所有值和引用类型都由一个名为object的基本类发展而来。在C#中还可以通过隐性转换（不会造成数据丢失）或显性转换（可能造成数据丢失或降低精确度）来改变数据类型。

预定义C#值类型


sbyte：存储8位带符号整数。sbyte中的s代表带符号(signed)，意味着变量可为正值或负值。sbyte变量的最小可能值为-128，最大可能值为127。 
byte：存储8位无符号整数。与sbyte变量不同，byte变量不带符号，并且只能存储正数值。byte变量的最小可能值为0，最大可能值为225。 
short：存储16带符号整数。short变量的最小可能值为32768，最大可能值为32767。 
int：存储32位带符号整数。int变量的最小可能值为-2147483648，最大可能值为2147683647。 
uint：存储32位无符号整数。unit中的u代表无符号。uint变量的最小可能值为0，最大可能值为4294967295。 
long：存储64位带符号整数。long变量的最小可能值为-9223372036845775808，最大可能值为9223372036845775807。 
ulong：存储64位无符号整数。ulong中的u代表无符号。ulong变量的最小可能值为0，最大可能值为18446744073709551615。 
char：存储16位Unicode字符。Char变量的最小可能值为值为0的Unicode字符，最大可能值为值为655535的Unicode字符。 
float：存储32位还符号浮点值。float变量的值介于±1.5 x 10-45到±3.4 x 1038之间。 
double：存储64位带符号浮点值。double变量的值介于±5.0 x 10-324到 ±1.7 x 10308之间。 
decimal：存储128位带符号浮点值。decimal类型变量适用于金融计算。decimal类型变量的值介于±1.0 x 10-28到±7.9 x 1028之间。 
bool：存储两个可能值——真或假——中的一个。应用bool类型变量是C#与C和C++不同的一个地方。在C和C++中，整数值0与假同义，而任何非零值与真同义。但在C#中，这些类型不再同义。你不能将一个整数变量转换成一个等同的bool值。如果你需要应用一个表示真或假条件的变量，应使用bool变量而非int变量。 

预定义C#引用类型


string：表示一个Unicode字符串。用它可轻松操作并分配字符串。字符串不可变，也就是说它一旦建立就不能修改。因此当你试图修改一个字符串，如将它与另一个字符串连接时，会建立一个新字符串对象来存储新生成的字符串。 
object：表示一个通用类型。在C#中，所有的预定义和用户定义的类型都由object类型或System.Object类发展而来。 

总结

正确应用合适的数据类型可帮助开发者充分利用程序语言的功能，但对那些以前应用别的程序语言的开发者而言，转换到C#可能要一段时间。欲了解与每种类型有关的更多信息，请访问微软网站。

Irina Medvinskaya自1996年开始涉足技术领域。她获得佩斯大学的MBA学位，现在任花旗集团的项目经理。
]]></description>
		</item>
		<item>
			<title>c#远程获取网页内容</title>
			<link>http://www.kingmx.com/article.php?id=14495</link>
			<pubDate>2006-11-28</pubDate>
			<description><![CDATA[

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;

namespace thief
{
&nbsp;&nbsp;&nbsp; class Program
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)
&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; try {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebClient MyWebClient = new WebClient();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyWebClient.Credentials = CredentialCache.DefaultCredentials;//获取或设置用于对向Internet资源的请求进行身份验证的网络凭据。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Byte[] pageData = MyWebClient.DownloadData("http://www.163.com");//从指定网站下载数据

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string pageHtml = Encoding.Default.GetString(pageData);&nbsp; //如果获取网站页面采用的是GB2312，则使用这句&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; //string pageHtml = Encoding.UTF8.GetString(pageData); //如果获取网站页面采用的是UTF-8，则使用这句

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(pageHtml);//在控制台输入获取的内容

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (StreamWriter sw = new StreamWriter("c:\test\ouput.html"))//将获取的内容写入文本
&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; sw.Write(pageHtml);
&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; Console.ReadLine(); //让控制台暂停,否则一闪而过了&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; catch(WebException webEx) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(webEx.Message.ToString());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; }
}

注：内容转自菩提树下的杨过的博客

]]></description>
		</item>
		<item>
			<title>c#远程获取网页内容</title>
			<link>http://www.kingmx.com/article.php?id=14494</link>
			<pubDate>2006-11-28</pubDate>
			<description><![CDATA[]]></description>
		</item>
		<item>
			<title>用C#访问ACCESS数据库问题</title>
			<link>http://www.kingmx.com/article.php?id=14374</link>
			<pubDate>2006-11-23</pubDate>
			<description><![CDATA[

最近这个项目中用到是ACCESS的数据库，开始没有使用密码进行连接：
String connectionString = "Provider=Microsoft.Jet.OleDb.4.0;Data Source=";
connectionString += @"c:datadbdb.mdb";
OleDbConnection con = new OleDbConnection(connectionString);
con.Open();
是没有任何问题。

为了要使数据库安全一点，不能被用户直接打开编辑，所以想到给Access数据库设置个密码：从菜单“工具”-&gt;"安全"-&gt;"设置数据库密码"，这样设置后就不能正常访问这个数据库了，在连接字符串中加上User ID与Password字段还是不行。最后在"工具"-&gt;"安全"-&gt;"用户与组的账户"设置好密码，直接不用更改连接字符串就可以连接了。这样处理后，用户打开时提示需要输入密码，也就达到了保护Access库的目的。 
http://www.cnblogs.com/wanlang/archive/2006/11/22/568690.html

]]></description>
		</item>
		<item>
			<title>在C#中应用哈希表(Hashtable)</title>
			<link>http://www.kingmx.com/article.php?id=13170</link>
			<pubDate>2006-10-30</pubDate>
			<description><![CDATA[
	
一.哈希表(Hashtable)简述
在.NET Framework中，Hashtable是System.Collections命名空间提供的一个容器，用于处理和表现类似key/value的键值对，其中key通常可用来快速查找，同时key是区分大小写；value用于存储对应于key的值。Hashtable中key/value键值对均为object类型，所以Hashtable可以支持任何类型的key/value键值对.
二.哈希表的简单操作
在哈希表中添加一个key/value键值对：HashtableObject.Add(key,value);
在哈希表中去除某个key/value键值对：HashtableObject.Remove(key);
从哈希表中移除所有元素： HashtableObject.Clear(); 
判断哈希表是否包含特定键key： HashtableObject.Contains(key);
下面控制台程序将包含以上所有操作：
using System;
using System.Collections; //使用Hashtable时，必须引入这个命名空间
class hashtable
{
public static void Main()
{
Hashtable ht=new Hashtable(); //创建一个Hashtable实例
ht.Add(&quot;E&quot;,&quot;e&quot;);//添加key/value键值对
ht.Add(&quot;A&quot;,&quot;a&quot;);
ht.Add(&quot;C&quot;,&quot;c&quot;);
ht.Add(&quot;B&quot;,&quot;b&quot;);
string s=(string)ht[&quot;A&quot;];
if(ht.Contains(&quot;E&quot;)) //判断哈希表是否包含特定键,其返回值为true或false
Console.WriteLine(&quot;the E key:exist&quot;);
ht.Remove(&quot;C&quot;);//移除一个key/value键值对
Console.WriteLine(ht[&quot;A&quot;]);//此处输出a
ht.Clear();//移除所有元素
Console.WriteLine(ht[&quot;A&quot;]); //此处将不会有任何输出
}
}
三,遍历哈希表
遍历哈希表需要用到DictionaryEntry Object，代码如下：
for(DictionaryEntry de in ht) //ht为一个Hashtable实例
{
Console.WriteLine(de.Key);//de.Key对应于key/value键值对key
Console.WriteLine(de.Value);//de.Key对应于key/value键值对value
}
四,对哈希表进行排序
对哈希表进行排序在这里的定义是对key/value键值对中的key按一定规则重新排列，但是实际上这个定义是不能实现的，因为我们无法直接在Hashtable进行对key进行重新排列，如果需要Hashtable提供某种规则的输出，可以采用一种变通的做法：
ArrayList akeys=new ArrayList(ht.Keys); //别忘了导入System.Collections
akeys.Sort(); //按字母顺序进行排序
for(string skey in akeys)
{
Console.Write(skey + &quot;:&quot;);
Console.WriteLine(ht[skey]);//排序后输出
}
&nbsp;
一,哈希表(Hashtable)简述
&nbsp; 在.NET Framework中，Hashtable是System.Collections命名空间提供的一个容器，用于处理和表现类似key/value的键值对，其中key通常可用来快速查找，同时key是区分大小写；value用于存储对应于key的值。Hashtable中key/value键值对均为object类型，所以Hashtable可以支持任何类型的key/value键值对.
&nbsp;
二,哈希表的简单操作
&nbsp;在哈希表中添加一个key/value键值对：HashtableObject.Add(key,value);
&nbsp;在哈希表中去除某个key/value键值对：HashtableObject.Remove(key);
&nbsp;从哈希表中移除所有元素：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HashtableObject.Clear(); 
&nbsp;判断哈希表是否包含特定键key：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HashtableObject.Contains(key);
&nbsp;下面控制台程序将包含以上所有操作：
using System;
using System.Collections; //使用Hashtable时，必须引入这个命名空间
class hashtable
{
&nbsp; public static void Main()
&nbsp; {
&nbsp; Hashtable ht=new Hashtable(); //创建一个Hashtable实例
&nbsp; ht.Add(&quot;E&quot;,&quot;e&quot;);//添加key/value键值对
&nbsp; ht.Add(&quot;A&quot;,&quot;a&quot;);
&nbsp; ht.Add(&quot;C&quot;,&quot;c&quot;);
&nbsp; ht.Add(&quot;B&quot;,&quot;b&quot;);

	
	
	]]></description>
		</item>
		<item>
			<title>用C++品尝Vista美味：界面的毛玻璃效果</title>
			<link>http://www.kingmx.com/article.php?id=13169</link>
			<pubDate>2006-10-30</pubDate>
			<description><![CDATA[简介
　　本文将演示在基于Windows Vista的普通Windows应用程序及对话框程序中，如何利用C++来生成Aero毛玻璃效果，此处使用的是Beta 2版本的Vista及Windows SDK，也许在后续的版本中，一些API在细节上会有所变化。另外，文中没有使用MFC，全部例子用WTL 7.5生成，其可在http://wtl.sourceforge.net/下载得到，虽然此处使用的是Visual C++ 2003，但Visual C++ 2005也类似。
　　Aero主题及毛玻璃效果，是随同Vista&quot;桌面窗口管理（DWM）&quot;而来的新特性，也是微软市场推广的一个重心，在应用程序中集成毛玻璃效果，当打开Aero主题时，程序看上去会显得非常与众不同--很酷，对吧。 
　　Aero主题中的毛玻璃效果
　　当以Aero为主题时，Vista会根据计算机显卡进行判断是否开启毛玻璃效果，此时桌面由DWM进行绘制，而DWM使用一个composition进程来渲染桌面，其会在顶层窗口的非客户区自动使用Aero主题元素（有点类似于Windows XP）。话又说回来，也不是总会添加这些毛玻璃效果的，如果计算机运行于&quot;电池模式&quot;，或用户决定关闭透明效果，那么非客户区就不会有毛玻璃效果了，如下图所示。



　　如果在控制面板的可视效果中打开了透明玻璃效果，那非客户区看上去就像下图这样：



　　请留意，记事本的边框呈现绿色调，这是墙纸透过来的颜色，并且也可以透过标题栏看到桌面的一些图标。
　　我们在编写代码的时候，关键只须留意composition是否打开，而不是设置了什么毛玻璃效果，因为DWM会处理毛玻璃效果绘制的部分。
　　项目开始
　　第一个示例程序是不带视窗口、工具条、状态条的SDI应用程序，在运行完WTL AppWizard之后，第一件事就是设置stdafx.h中的#define，以便利用Vista的新特性。Vista的Windows版本为6，且Vista中IE的版本为7，设置完成后应像下面这样：

#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#define _WIN32_IE 0x0700

　　接下来包含ATL与WTL的头文件：

#define _WTL_NO_WTYPES // 不要在WTL头文件中定义CRect/CPoint/CSize
#include &lt;atlbase.h&gt;
#include &lt;atltypes.h&gt;//共享的CRect/CPoint/CSize
#include &lt;atlapp.h&gt;
extern CAppModule _Module;
#include &lt;atlwin.h&gt;
#include &lt;atlframe.h&gt;
#include &lt;atlmisc.h&gt;
#include &lt;atlcrack.h&gt;
#include &lt;atltheme.h&gt;// XP/Vista主题支持
#include &lt;dwmapi.h&gt;// DWM API

　　如果修改完成之后就编译，将会从atltheme.h中得到4个错误。例如，以下是不会编译通过的CTheme::GetThemeTextMetrics()代码：

HRESULT GetThemeTextMetrics(..., PTEXTMETRICW pTextMetric)
{
　ATLASSERT(m_hTheme != NULL);
　//注意：因为uxtheme.h头文件，所以转换为PTEXTMETRIC。
　//替换掉PTEXTMETRICW是不对的
　return ::GetThemeTextMetrics(m_hTheme, ..., (PTEXTMETRIC) pTextMetric);
}

　　在GetThemeTextMetrics() API中的转换，是对Platform SDK的uxtheme.h中错误的修正，然而，Windows SDK却没有这个错误，所以这个转换导致了一个错误，可删除函数中的这个转换，其他三个也同样。 
添加边框的毛玻璃效果
　　通过把毛玻璃效果从非客户区扩展到客户区，就可完成添加程序的毛玻璃效果，这个API是DwmExtendFrameIntoClientArea()。DwmExtendFrameIntoClientArea()接受两个参数：我们框架窗口的HWND和一个用于说明毛玻璃效果扩展到窗口四周多远的MARGINS结构。可在OnCreate()中调用这个API：

LRESULT CMainFrame::OnCreate(LPCREATESTRUCT lpcs)
{
　//在底部添加玻璃效果
　MARGINS mar = {0};
　mar.cyBottomHeight = 100;
　DwmExtendFrameIntoClientArea ( m_hWnd, &amp;mar );
　return 0;
}

　　但如果运行程序，看不到有任何变化：



　　这是因为毛玻璃效果依赖于窗口的透明度，为显示出玻璃效果，区域中像素（在本例中为客户区底部的100像素）的alpha值必须设置为0。最简单的方法是用一个黑画刷来绘制这个区域，它会把像素的颜色值（红、绿、蓝和alpha）设为0，可在OnEraseBkgnd()中完成：

BOOL CMainFrame::OnEraseBkgnd ( HDC hdc )
{
　CDCHandle dc = hdc;
　CRect rcClient;
　GetClientRect(rcClient);
　dc.FillSolidRect(rcClient, RGB(0,0,0));
　return true;
}

　　修改之后，框架窗口看起来像这样：



　　底部的100像素现在是毛玻璃效果了。
　　在毛玻璃区域添加文本
　　在窗口中添加毛玻璃效果是比较简单的部分，但要把自己的界面元素（UI）添加到毛玻璃之上，就有点难度了。因为必须一直保持像素的alpha值，所以就要用到那些可以理解并适当设置alpha的绘图API。坏消息是，GDI函数差不多全部不理会alpha--唯一剩下的API则为带有SRCCOPY光栅操作的BilBlt()函数了，因此，程序必须使用GDI+或主题API来进行绘图，这些API都是时刻不忘alpha的。
　　在Vista中，有关毛玻璃的效果一般用在表示程序状态的区域（取代了通用控件中的状态栏），例如，Windows Media Player 11就在窗口底部的毛玻璃区域显示播放控制与当前歌曲信息：

　　以下，将演示怎样在毛玻璃区域上绘制文本，并怎样在文本上添加发光效果，以便文本在任何背景上都方便阅读。
使用正确的字体
　　Vista已经彻底放弃使用MS Sans Serif与Tahoma字体，转而把Segoe UI作为默认的UI字体。我们的程序也应该使用Segoe UI字体，所以，将会在基于当前主题的情况下创建一个字体。如果主题被禁用（如用户正在使用Windows经典颜色方案），那我们就使用SystemParametersInfo() API。
　　首先，需要在CMainFrame中添加主题支持，这一点非常简单，因为WTL已经有一个用于处理主题的类：CThemeImpl。我们可把CThemeImpl添加到继承列表，并把消息链接至CThemeImpl，以便在当前主题改变时，程序可以得到相应的通知。

class CMainFrame :
public CFrameWindowImpl&lt;CMainFrame&gt;,
public CMessageFilter,
public CThemeImpl&lt;CMainFrame&gt;
{
　// ...
　BEGIN_MSG_MAP(CMainFrame)
　　CHAIN_MSG_MAP(CThemeImpl&lt;CMainFrame&gt;)
　　// ...
　END_MSG_MAP()
　protected:
　　CFont m_font; //用于绘制文本的字体
};

　　在CMainFrame的构造函数中，我们调用了CThemeImpl::SetThemeClassList()，其指定了我们正在使用哪一个主题的窗口类。对一般窗口来说（即不是普通控件的窗口），名称为&quot;globals&quot;。

CMainFrame::CMainFrame()
{
　SetThemeClassList ( L&quot;globals&quot; );
}

　　最后，在OnCreate()中，从主题中读取字体信息，并创建一个字体自用：

LRESULT CMainFrame::OnCreate ( LPCREATESTRUCT lpcs )
{
　// ...
　//决定在文本中使用哪一种字体
　LOGFONT lf = {0};
　if ( !IsThemeNull() )
　　GetThemeSysFont ( TMT_MSGBOXFONT, &amp;lf );
　else
　{
　　NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS) };
　　SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS),&amp;ncm, false );
　　lf = ncm.lfMessageFont;
　}
　m_font.CreateFontIndirect ( &amp;lf );
　return 0;
}

　　绘制文本
　　在毛玻璃效果上绘制文本涉及以下步骤：
　　·创建一个用于双缓冲绘制的内存DC。
　　·创建一个32位色深的DIB，并选入DC。
　　·用DrawThemeTextEx()把文本绘制在内存中的DIB上。
　　·用BitBit()把文本复制到屏幕。
　　因为我们的绘制代码将会因为composition是否打开而有所不同，所以需要在绘制期间检查composition状态。检查状态的API为DwmIsCompositionEnabled()，如果API执行失败，在返回值中就不会指示出打开状态，但CMainFrame中有一个包装好的函数IsCompositionEnabled()，非常易于使用：

bool CMainFrame::IsCompositionEnabled() const
{
　HRESULT hr;
　BOOL bEnabled;
　hr = DwmIsCompositionEnabled(&amp;bEnabled);
　return SUCCEEDED(hr) &amp;&amp; bEnabled;
}

　　现在，让我们再检查一遍OnEraseBkgnd()，看看每个步骤是否都完成了。这个程序是一个时钟程序，所以先用GetTimeFormat()获取当前时间：

BOOL CMainFrame::OnEraseBkgnd(HDC hdc)
{
　CDCHandle dc = hdc;
　CRect rcClient, rcText;
　GetClientRect ( rcClient );
　dc.FillSolidRect ( rcClient, RGB(0,0,0) );
　rcText = rcClient;
　rcText.top = rcText.bottom - 100;
　
　//获取当前时间
　TCHAR szTime[64];
　GetTimeFormat(LOCALE_USER_DEFAULT,0,NULL,NULL,szTime,_countof(szTime));
　……
}

　　如果composition打开，我们就进行合成绘制步骤，先设置好一个内存DC：

if ( IsCompositionEnabled() )
{
　//设置一个我们将绘制的内存DC和位图
　CDC dcMem;
　CBitmap bmp;
　BITMAPINFO dib = {0};
　dcMem.CreateCompatibleDC ( dc );

　　接下来，填充BITMAPINFO结构以得到一个32位色深位图，且与毛玻璃区域的高宽相同。此处需重点留意的是，位图高度（即BITMAPINFOHEADER的biHeight成员）为负数，这是因为通常情况下BMP是按照从下至上的顺序存储在内存中的，但DrawThemeTextEx()需要的位图顺序是从上至下，所以要把高度设为负数。

dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dib.bmiHeader.biWidth = rcText.Width();
dib.bmiHeader.biHeight = -rcText.Height();
dib.bmiHeader.biPlanes = 1;
dib.bmiHeader.biBitCount = 32;
dib.bmiHeader.biCompression = BI_RGB;
bmp.CreateDIBSection (dc,&amp;dib,DIB_RGB_COLORS,NULL,NULL,0);

　　现在，我们的图形对象就创建好了，可以开始绘制文本了。

//设置好DC
dcMem.SelectBitmap ( bmp );
dcMem.SelectFont ( m_font );
//绘制文本
DTTOPTS dto = { sizeof(DTTOPTS) };
const UINT uFormat = DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_NOPREFIX;
CRect rcText2 = rcText;
dto.dwFlags = DTT_COMPOSITED|DTT_GLOWSIZE;
dto.iGlowSize = 10;
rcText2 -= rcText2.TopLeft(); //相同的rect，但左上角为(0,0)
DrawThemeTextEx ( m_hTheme, dcMem, 0, 0, CT2CW(szTime), -1,
uFormat, rcText2, &amp;dto );

　　DTTOPTS结构控制了文本怎样被绘制，在标志中我们指明了要绘制&quot;合成文本&quot;，并让文本有一个发光效果。最后，把内存中的位图贴到屏幕上：

　//将文本绘制到屏幕上。
　BitBlt ( dc, rcText.left, rcText.top, rcText.Width(), rcText.Height(), dcMem, 0, 0, SRCCOPY );
} // end if (IsCompositionEnabled())

　　如果composition未打开，我们用GDI函数绘制文本：

else
{
　const UINT uFormat = DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_NOPREFIX;
　//设置好DC
　dc.SetTextColor ( RGB(255,255,255) );
　dc.SelectFont ( m_font );
　dc.SetBkMode ( TRANSPARENT );
　//绘制文本
　dc.DrawText ( szTime, -1, rcText, uFormat );
}
return true; //我们绘制了整个背景
}

　　下面就是&quot;合成文本&quot;的模样：



　　为演示发光效果，下面是同一背景上的一段文本，但没有发光效果： 



处理composition相关的通知
　　当DWM的composition状态打开或关闭时，系统会向所有顶层窗口广播一个WM_DWMCOMPOSITIONCHANGED消息；如果composition为打开，需要再次调用DwmExtendFrameIntoClientArea()以告之DWM，我们窗口的哪一部分应为毛玻璃效果：

LRESULT CMainFrame::OnCompositionChanged(...)
{
　if ( IsCompositionEnabled() )
　{
　　MARGINS mar = {0};
　　mar.cyBottomHeight = 100;
　　DwmExtendFrameIntoClientArea ( m_hWnd, &amp;mar );
　}
　return 0;
}

　　在对话框程序中应用毛玻璃效果
　　在对话框程序中添加毛玻璃效果的过程，与上面框架窗口的例子非常相似，但需要对代码作一些轻微的改动。在示例对话框程序中为顶层窗口添加了毛玻璃效果，下面，相对前一例子作了修改或添加的代码，将以黑体字标出。

　　设置对话框
　　如之前一样，要告之CThemeImpl我们要使用哪个窗口类主题，并调用DwmExtendFrameIntoClientArea()为窗口边框添加毛玻璃效果。

CMainDlg::CMainDlg()
{
　SetThemeClassList ( L&quot;globals&quot; );
}
BOOL CMainDlg::OnInitDialog ( HWND hwndFocus, LPARAM lParam )
{
　//删除了向导生成的某些初始化代码
　//为顶层窗口添加毛玻璃效果
　if ( IsCompositionEnabled() )
　{
　　MARGINS mar = {0};
　　mar.cyTopHeight = 150;
　　DwmExtendFrameIntoClientArea ( m_hWnd, &amp;mar );
　}

　　接下来，构建文本字体。注意，我们需要显式调用OpenThemeData()，而为什么在前面的框架窗口例子中不需要调用呢，因为CThemeImpl在它的WM_CREATE处理程序中已调用了。反观对话框取而代之接收WM_INITDIALOG，而CThemeImpl未处理WM_INITDIALOG，所以就需要我们自己调用OpenThemeData()了。另外，在代码中也把字体设置得更大，只是为了演示更大字体的发光效果。 

//决定使用哪一种字体
LOGFONT lf = {0};
OpenThemeData();
if ( !IsThemeNull() )
　GetThemeSysFont ( TMT_MSGBOXFONT, &amp;lf );
else
{
　NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS) };
　SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS),&amp;ncm, false );
　lf = ncm.lfMessageFont;
}
lf.lfHeight *= 3;
m_font.CreateFontIndirect ( &amp;lf );

　　对话框的顶层窗口上有一个大的静态文本控件，也就是我们要绘制时间的地方。代码设置了控件的owner-draw风格，因此，我们可把所有的文本绘制代码都放在OnDrawItem()中：

//设置静态文本控件的owner-draw
m_wndTimeLabel.Attach ( GetDlgItem(IDC_CLOCK) );
m_wndTimeLabel.ModifyStyle ( SS_TYPEMASK, SS_OWNERDRAW );

　　最后，调用EnableThemeDialogTexture()以便对话框背景使用当前主题来绘制。

//其他初始化代码
EnableThemeDialogTexture ( ETDT_ENABLE );
//设置计时器的时间间隔为1秒，以在每个秒钟内都能更新时钟
SetTimer ( 1, 1000 );
return TRUE;
}

　　打开毛玻璃效果
　　如前面一样，我们需要用黑色画刷来填充毛玻璃区域，以便营造一种透视效果。因为内置的对话框窗口处理过程会响应WM_ERASEBKGND消息，来处理诸如非矩形或半透明控件，所以，我们需要在OnPaint()而不是OnEraseBkgnd()中做绘图。

void CMainDlg::OnPaint ( HDC hdc )
{
　CPaintDC dc(m_hWnd);
　CRect rcGlassArea;
　if ( IsCompositionEnabled() )
　{
　　GetClientRect ( rcGlassArea );
　　rcGlassArea.bottom = 150;
　　dc.FillSolidRect(rcGlassArea, RGB(0,0,0));
　}
}

　　绘制文本
　　在OnTimer()中，获取当前时间，并以此设置静态控件的文本：

void CMainDlg::OnTimer ( UINT uID, TIMERPROC pProc )
{
　//获取当前时间
　TCHAR szTime[64];
　GetTimeFormat ( LOCALE_USER_DEFAULT, 0, NULL, NULL,szTime, _countof(szTime) );
　m_wndTimeLabel.SetWindowText ( szTime )
}

　　SetWindowText()函数会使静态控件重绘，导致OnDrawItem()函数的调用。OnDrawItem()函数中的代码与前面框架窗口例子中的类似，在此不再赘述，以下是程序外观：



在毛玻璃效果上绘制图形 
区域中进行绘图需要用到可识别alpha的API，如GDI+函数。下面的例子用到GDI+中的Image类在对话框的左上角绘制了一个Logo，如图示：



　　这个Logo是从与exe文件在同一目录的mylogo.png文件中读取的，请注意，因为使用了GDI+绘制Logo，所以Logo周围的透明度已被保留，并且看上去显示得很正确。
　　使整个窗口毛玻璃化
　　我们还可以让整个窗口看上去都像块毛玻璃，以下有一段简短代码，只需把MARGINS结构的第一个成员设为 -1就行了：

MARGINS mar = {-1};
DwmExtendFrameIntoClientArea ( m_hWnd, &amp;mar );

　　如果在我们的对话框程序中加入这段代码，那么程序最终将看上去像这样：



　　留意观察，4个按钮上的文本颜色显示不正确，并且每个按钮外围都有一个不透明的矩形。通常来说，透明性与子窗口不会配合得非常好，如果想要一个全为毛玻璃效果的对话框，那么控件部分就需要以一个不透明的背景来绘制，如&quot;Windows Mobility Center&quot;程序：



　　结论
　　在程序中添加毛玻璃效果可使程序在视觉上显得非常与众不同，而且能提供一个比通用控件中状态栏更好的状态显示区域，本文主要是起到一个抛砖引玉的作用，也有助于大家在使用本地C++添加毛玻璃效果时，对DWM API有一个初步的了解]]></description>
		</item>
		<item>
			<title>使用C#开发SmartPhone程序入门</title>
			<link>http://www.kingmx.com/article.php?id=13039</link>
			<pubDate>2006-10-26</pubDate>
			<description><![CDATA[
介绍
　　本文的目的是引导SmartPhone编程的初学者进入SmartPhone世界，以及学会如何使用C#编写SmartPhone程序。本文首先介绍了什么是SmartPhone，以及SmartPhone的一些特性和用于编程的API。为了更好地掌握如何使用C#编写SmartPhone程序，在本文还提供了一个使用C#编写的简单的SmartPhone程序的例子，读者可以通过这个例子快速地掌握如何使用C#为SmartPhone编写程序。
　　近来，移动这个新兴的领域正在受到许多移动设备的使用者和一些世界级的公司的关注和追捧。现在移动设备使用了先进的信息访问和获取技术，用户可以通过移动设备访问到世界的任何角落，因此，可以毫不夸张地说，先进的移动设备将使人们如虎添翼。 
　　就象任何其它技术的快速发展一样，移动设备也在迅猛地发展。可以肯定地说，移动设备将创造一个新世界，无论是平民还是富翁，移动设备都将成为他们的好帮手。也许在不远的将来，它还会以其它的形式出现，到那时，移动设备将成为你生活的一部分。
　　真是太棒了，开发人员除了可以做手头的工作…事实上，他们完全可以进入一个另人激动、充满了刺激的世界，在这个世界中，颠覆了传统的桌面和Web开发。在这个世界中，有新的技术、新的挑战、新的机会，当然，更重要的是，有新的挣钱方法…$Money$。
　　移动设备的发展
　　移动设备发展到今天已经变得丰富多彩，现在我们有各种各样的移动设备可以选择，如手持设备，Pocket PC，PDA等等。现在移动设备正在试图利用手机已被全球的人们普遍使用的优势迅猛发展。
　　今天的移动电话市场已经有多种多样的型号可供选择。目前，手机市场已经被使用Symbion操作系统的Nokia、索尼和三星等公司垄断。
　　就象当年的Web浏览器市场一样，Microsoft在移动世界中也是姗姗来迟。今天的Microsoft已经拥有了自己的用于移动设备的操作，它就是Microsoft Windows Mobile2003，还有更为强大的WinCE4.2。那些使用Microsoft操作系统的手机正在蚕食市场份额，并且有越来越多的开发人员也转向了Microsoft阵营。
　　按着Microsoft的一贯做法，Microsoft在推出相应的手机和操作系统后，在第一时间就为开发人员提供了相应的支持，包括可以使用现有的语言为Microsoft的手机开发软件。由于目前Microsoft主推.net framework，因此，使.net framework可以在手机上运行就变得非常必要。由于考虑到了手机的硬件环境，Microsoft推出了一个.net framework的精简版，这就是Microsoft .NET Compact Framework，这个framework是PC机上的.net framework的一个子集。
　　特性
　　在Microsoft的SmartPhone上拥有丰富的软件，用户可以通过声音、文字以及Internet（如GSM、GPRS、SMS、PPTP、蓝牙等）进行相互通讯。
　　以下是Microsoft SmartPhone所安装的软件列表




Pocket 浏览器

这个浏览器比WAP浏览器强大得多，它完全可以取代手机中的IE5。这个浏览器可以支持HTML3.2、XML、XSL、cHTML、WAP1.2.1、WML脚本、Active脚本、ActiveX、SSL、JPEG、GIF等。


Pocket Outlook

这个工具和PC机上的Outlook类似，它除了可以管理联系人、写日记、任务管理和记录音频，还可以发送和接收邮件。


MSN Messenger

一个聊天客户端，和PC机上的MSN Messenger类似。


Microsoft ActiveSync

使客户端和服务器同步


Windows Media Player

一个媒体播放器，可播放MP3、WMA和AVI。


Voice Notes 

一个录音软件。


Games 

一些小游戏。


File Management Utilities

文件和任务管理，类似于windows的文件管理器。


Wireless Modem 

可以通过USB、IR和COM连接Internet。


MMS Client

接收MMS信息。


Camera 

一个视频采集软件，可以录制和捕捉视频。

　　SmartPhone的外观
　　图1是微软建议的移动设备的标准外观和控制面板。






图1 标准的SmartPhone界面

　　在这个控制面版上有两个Soft键、一个Home键、一个Back键和五个方向键，下面是十个数字键以及"*"和"#" 键。Microsoft强烈建议使用这个按键结构。在这些键中，所有的控制键（如Soft和Home键等）是必须的。然而，这些设备并不是由Microsoft制造的，而是由大大小小的移动设备生产商所制造，因此，这些设备的外观和结构可能和Microsoft所推荐的这个设备有一些出入。
　　最近，Microsoft发布了Windows Mobile 2003的第二版，开发人员可以选择以下的开发工具为Windows Mobile开发软件，这些软件有基于Win32的，也有基于Microsoft .NET Compact Framework的。
　　1、 Embedded VC++ 4.0 
　　2、 Visual Studio .NET - C#, VB.NET

　　一个简单的Hello World程序
　　现在让我们进入主题，开发一个简单的Hello World程序。编写这个程序最先要做的就是下载可以运行在Visual Studio2003中的SmartPhone2003开发包。在安装完这个开发包后，SmartPhone的开发环境和一个SmartPhone模拟器已经被安装到了你的机器上。
　　在安装完SDK后，启动Visual Studio，在工程模板中选择Smart Device应用程序，给它起一个名字，然后点击OK，现在，你将看到如图2的欢迎界面。






图2 Smart Phone的欢迎界面

&lt;&gt; 





选择SmartPhone和Windows Application后，点击OK按钮。现在，你将看到如图3所示的开发界面。






图3 SmartPhone的开发界面

　　在右侧的工具栏上，你可以看到一个控件面版，在这个面版上有一些我们熟悉的控件，但这些控件是不可用的，这是因为SmartPhone并不支持这些控件。
　　现在，我们已经可以开发SmartPhone应用程序了。我们首先应该考虑到，通常手机只用一只手操作，因此，应用程序的导航键应该容易操作。在手机上的"Soft"键通常充当导航键。如果你仔细观察Visual Studio，你就可以注意到Visual Studio已经为我们建立了一个默认的菜单控件。Visual Studio建议我们使用这个MainMenu控件，这个菜单最终将成为导航键来控制我们的SmartPhone应用程序。
　　现在，让我们按图4所示建立一个菜单结构：






图4 SmartPhone菜单

　　双击"Say Hello"菜单可以写执行代码：




private void menuItem2_Click(object sender,System.EventArgs e)
{
　MessageBox.Show("Hello Logu!");
}

　　下面是 "Exit"菜单的代码：




private void menuItem3_Click(object sender, System.EventArgs e)
{
　this.Close();
}

　　现在按F5运行程序，将会弹出一个如图5的对话框，这个弹出的对话框可以让你选择使用哪一个设备运行这个程序，我们选择"Smartphone 2003 Emulator（Virtual Radio）(Default)"，然后点击"Deploy"






图5 选择运行设备对话框

　　现在模拟器已经启动，界面如图6所示。我们的应用程序已经被安装在模拟器上了，在上面出现了一个提示，并且左下角出现一个"OK"。






图6 模拟器

　　单击"OK"运行我们的程序。
　　现在我们的.NET程序已经运行了。在应用程序被运行后，单击"My Menu"中的"Say Hello"，你将看到如图7所示的信息框。现在，你还可以选择SmartPhone设备，并这个程序直接发布到这个设备上。由于打包和发布并不属于本文的内容，因此，在这里不再讨论。 






图7 程序运行界面

　　SmartPhone所支持的API
　　以下是SmartPhone所支持的API列表
　　· ActiveSync API 
　　· Bluetooth（蓝牙）API 
　　· CE Messaging API 
　　· Device Management（设备管理） API 
　　· Home Screen API 
　　· Object Exchange (OBEX) 
　　· Pocket Outlook Object Model (POOM) 
　　· Speech Recognizer 
　　　o Telephony - TAPI 
　　　o Accessing the SIM card 
　　　o P/Invoke to native SIM Toolkit APIs 
　　· RAPI - Remote API to connect to the desktops programmatically 
　　· GAPI - To develop Mobile games（用于开发游戏的API） 
　　· Vibrate API 
　　· Voice Recorder Controls （用于录音的API） 
]]></description>
		</item>
		<item>
			<title>为C程序员准备的0x10个最佳问题</title>
			<link>http://www.kingmx.com/article.php?id=12977</link>
			<pubDate>2006-10-24</pubDate>
			<description><![CDATA[

整个测试遵循以下的约定：

u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 假定在所有的程序中必须的头文件都已经被正确包含。

考虑如下的数据类型：

u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char 为1个字节

u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int 为4个字节

u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long int 为4个字节

u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float 为4个字节

u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double 为个8字节

u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long double 为 8个字节

u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指针为4个字节





1. Consider the following program: 


#include&lt;setjmp.h&gt; 


static jmp_buf&nbsp; buf; 




main() 


{ 


&nbsp; volatile&nbsp; int b; 


&nbsp; b =3; 




&nbsp; if(setjmp(buf)!=0)&nbsp; 


&nbsp; { 


&nbsp;&nbsp;&nbsp; printf("%d ", b);&nbsp; 


&nbsp;&nbsp;&nbsp; exit(0); 


&nbsp; } 


&nbsp; b=5; 


&nbsp; longjmp(buf , 1); 


} 


The output for this program is: &nbsp;
(a) 3
(b) 5
(c) 0
(d) None of the above 


2. Consider the following program: 


main() 


{ 


&nbsp;&nbsp; struct node 


&nbsp;&nbsp; { 


&nbsp;&nbsp;&nbsp;&nbsp; int a; 


&nbsp;&nbsp;&nbsp;&nbsp; int b; 


&nbsp;&nbsp;&nbsp;&nbsp; int c;&nbsp;&nbsp;&nbsp;&nbsp; 


&nbsp;&nbsp; }; 


&nbsp;&nbsp; struct node&nbsp; s= { 3, 5,6 }; 


&nbsp;&nbsp; struct node *pt = &amp;s; 


&nbsp;&nbsp; printf("%d" ,&nbsp; *(int*)pt); 


} 


The output for this program is: 
(a) 3
(b) 5
(c) 6
(d) 7 


3. Consider the following code segment: 


int&nbsp; foo ( int x , int&nbsp; n) 


{ 


&nbsp; int val; 


&nbsp; val =1; 


&nbsp; 


&nbsp; if (n&gt;0) 


&nbsp; { 


&nbsp;&nbsp;&nbsp; if (n%2 == 1)&nbsp; val = val *x; 


&nbsp;&nbsp;&nbsp; 


&nbsp;&nbsp;&nbsp; val = val * foo(x*x , n/2); 


&nbsp; } 


&nbsp; return val; 


} 


What function of x and n is compute by this code segment?&nbsp; &nbsp; 


(a) x^n
(b) x*n
(c) n^x
(d) None of the above 


4. Consider the following program: 


main() 


{ 


&nbsp; int&nbsp; a[5] = {1,2,3,4,5}; 


&nbsp; int *ptr =&nbsp; (int*)(&amp;a+1); 




&nbsp; printf("%d %d" , *(a+1), *(ptr-1) ); 




} 


The output for this program is: 
(a) 2 2
(b) 2 1
(c) 2 5
(d) None of the above 


5. Consider the following program: 


void foo(int [][3] );&nbsp;&nbsp;&nbsp;&nbsp; 




main() 


{ 


&nbsp; int a [3][3]= { { 1,2,3} , { 4,5,6},{7,8,9}}; 


&nbsp; foo(a); 


&nbsp; printf("%d" , a[2][1]); 


} 




void foo( int b[][3]) 


{ 


&nbsp; ++ b; 


&nbsp; b[1][1] =9; 


} 


The output for this program is: 
(a) 8
(b) 9
(c) 7
(d) None of the above 


6. Consider the following program: 


main() 


{ 


&nbsp; int a, b,c, d; 


&nbsp; a=3; 


&nbsp; b=5; 


&nbsp; c=a,b; 


&nbsp; d=(a,b); 




&nbsp; printf("c=%d" ,c); 


&nbsp; printf("d=%d" ,d); 




} 


The output for this program is: 
(a) c=3 d=3
(b) c=5 d=3
(c) c=3 d=5
(d) c=5 d=5 


7. Consider the following program: 


main() 


{ 


&nbsp; int a[][3] = { 1,2,3 ,4,5,6}; 


&nbsp; int (*ptr)[3] =a; 




&nbsp; printf("%d %d "&nbsp; ,(*ptr)[1], (*ptr)[2] ); 




&nbsp; ++ptr; 


&nbsp; printf("%d %d"&nbsp; ,(*ptr)[1], (*ptr)[2] ); 


} 


The output for this program is: 
(a) 2 3 5 6
(b) 2 3 4 5
(c) 4 5 0 0
(d) None of the above 


8. Consider following function 


int *f1(void) 


{ 


&nbsp; int x =10; 


&nbsp; return(&amp;x); 


} 




int *f2(void) 


{ 


&nbsp; int*ptr; 


&nbsp; *ptr =10; 


&nbsp; return ptr; 


} 




int *f3(void) 


{ 


&nbsp; int *ptr; 


&nbsp; ptr=(int*) malloc(sizeof(int)); 


&nbsp; return ptr; 


} 


Which of the above three functions are likely to cause problem with pointers 
(a) Only f3
(b) Only f1 and f3
(c) Only f1 and f2
(d) f1 , f2 ,f3 


9. Consider the following program: 


main() 


{ 


&nbsp; int i=3; 


&nbsp; int j; 




&nbsp; j = sizeof(++i+ ++i); 




&nbsp; printf("i=%d j=%d", i ,j); 


} 


The output for this program is:
(a) i=4 j=2
(b) i=3 j=2
(c) i=3 j=4
(d) i=3 j=6 


10. Consider the following program: 


void f1(int *, int); 


void f2(int *, int); 


void(*p[2]) ( int *, int); 




main() 


{ 


&nbsp; int a; 


&nbsp; int b; 




&nbsp; p[0] = f1; 


&nbsp; p[1] = f2; 


&nbsp; a=3; 


&nbsp; b=5; 




&nbsp; p[0](&amp;a , b); 


&nbsp; printf("%dt %dt" , a ,b); 




&nbsp; p[1](&amp;a , b); 


&nbsp; printf("%dt %dt" , a ,b); 


} 




void f1( int* p , int q) 


{ 


&nbsp; int tmp; 


&nbsp; tmp =*p; 


&nbsp; *p = q; 


&nbsp; q= tmp; 


} 




void f2( int* p , int q) 


{ 


&nbsp; int tmp; 


&nbsp; tmp =*p; 


&nbsp; *p = q; 


&nbsp; q= tmp; 


}&nbsp; 


The output for this program is: 
(a) 5 5 5 5
(b) 3 5 3 5
(c) 5 3 5 3
(d) 3 3 3 3 


11. Consider the following program: 


void e(int );&nbsp;&nbsp; 




main() 


{ 


&nbsp; int a; 


&nbsp; a=3; 


&nbsp; e(a); 


} 




void e(int n) 


{ 


&nbsp; if(n&gt;0) 


&nbsp; { 


&nbsp;&nbsp;&nbsp; e(--n); 


&nbsp;&nbsp;&nbsp; printf("%d" , n); 


&nbsp; &nbsp;&nbsp;e(--n); 


&nbsp; } 


} 


The output for this program is: 
(a) 0 1 2 0
(b) 0 1 2 1
(c) 1 2 0 1
(d) 0 2 1 1 


12. Consider following declaration 


typedef int (*test) ( float * , float*) 


test tmp; 


type of tmp is 
(a) Pointer to function of having two arguments that is pointer to float
(b) int
(c) Pointer to function having two argument that is pointer to float and return int
(d) None of the above 


13. Consider the following program: 


main() 


{ 


&nbsp; char *p; 


&nbsp; char buf[10] ={ 1,2,3,4,5,6,9,8}; 


&nbsp; p = (buf+1)[5]; 


&nbsp; printf("%d" , p); 


} 


The output for this program is: 
(a) 5
(b) 6
(c) 9
(d) None of the above 


14. Consider the following program: 


Void f(char**); 




main() 


{ 


&nbsp; char * argv[] = { "ab" ,"cd" , "ef" ,"gh", "ij" ,"kl" }; 


&nbsp; f( argv ); 


} 




void f( char **p ) 


{ 


&nbsp; char* t; 




&nbsp; t= (p+= sizeof(int))[-1]; 




&nbsp; printf( "%s" , t); 


} 


The output for this program is: 
(a) ab
(b) cd
(c) ef
(d) gh 


15. Consider the following program: 


#include&lt;stdarg.h&gt; 


int ripple ( int , ...); 




main() 


{ 


&nbsp; int num; 


&nbsp; num = ripple ( 3, 5,7); 


&nbsp; printf( " %d" , num); 


} 




int ripple (int n, ...) 


{ 


&nbsp; int i , j; 


&nbsp; int k;&nbsp; 


&nbsp; va_list p; 




&nbsp; k= 0; 


&nbsp; j = 1; 


&nbsp; va_start( p , n);&nbsp;&nbsp;&nbsp;&nbsp; 




&nbsp; for (; j&lt;n;&nbsp; ++j) 


&nbsp; { 


&nbsp;&nbsp;&nbsp; i =&nbsp; va_arg( p , int); 


&nbsp;&nbsp;&nbsp; for (; i;&nbsp;&nbsp;&nbsp; i &amp;=i-1&nbsp; ) 


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++k; 


&nbsp; } 


&nbsp; return k; 


} 


The output for this program is: 
(a) 7
(b) 6
(c) 5
(d) 3 


16. Consider the following program: 


int counter (int i) 


{ 


&nbsp; static int count =0; 


&nbsp; count = count +i; 


&nbsp; return (count ); 


} 


main() 


{ 


&nbsp; int i , j; 




&nbsp; for (i=0; i &lt;=5; i++) 


&nbsp;&nbsp;&nbsp; j = counter(i); 


} 


The value of j at the end of the execution of the this program is:
(a) 10
(b) 15
(c) 6
(d) 7 





]]></description>
		</item>
		<item>
			<title>了解C++异常处理的系统开支</title>
			<link>http://www.kingmx.com/article.php?id=12237</link>
			<pubDate>2006-10-21</pubDate>
			<description><![CDATA[
为了在运行时处理异常，程序要记录大量的信息。无论执行到什么地方，程序都必须能够识别出如果在此处抛出异常的话，将要被释放哪一个对象;程序必须知道每一个入口点，以便从try块中退出;对于每一个try块，他们都必须跟踪与其相关的catch子句以及这些catch子句能够捕获的异常类型。这种信息的记录不是没有代价的。确保程序满足异常规格不需要运行时的比较(runtime comparisons)，而且当异常被抛出时也不用额外的开销来释放相关的对象和匹配正确的catch字句。但是异常处理确是有代价的，即使你没有使用try，throw或catch关键字，你同样得付出一些代价。
　　让我们先从你不使用任何异常处理特性也要付出的代价谈起。你需要空间建立数据结构来跟踪对象是否被完全构造(constructed)(参加条款10)，你也需要系统时间保持这些数据结构不断更新。这些开销一般不是很大，但是当采用不支持异常的方法编译的程序一般比支持异常的程序运行速度更快所占空间也更小。
　　在理论上，你不能对此进行选择:C++编译器必须支持异常，也就是说，当你不用异常处理时你不能让编译器生产商消除这方面的开销，因为程序一般由多个独立生成的目标文件(object files)组成，只有一个目标文件不进行异常处理并不能代表其他目标文件不进行异常处理。而且即使组成可执行文件的目标文件都不进行异常处理，那么还有它们所连接的程序库呢?如果程序的任何部分使用了异常，其它部分必须也支持异常。否则在运行时程序就不可能提供正确的异常处理。
　　不过这只是理论，实际上大部分支持异常的编译器生产商都允许你自由控制是否在生成的代码里包含进支持异常的内容。如果你知道你程序的任何部分都不使用try，throw或catch，并且你也知道所连接的程序库也没有使用try，throw或catch，你就可以采用不支持异常处理的方法进行编译，这可以缩小程序的尺寸和提高速度，否则你就得为一个不需要的特性而付出代价。随着时间的推移，使用异处理的程序库开始变得普遍了，上面这种方法将逐渐不能使用，但是根据目前的软件开发情况来看，如果你已经决定不使用任何的异常特性，那么采用不支持异常的方法编译程序是一个性能优化的合理方法。同样这对于想避开异常的程序库来说也是一个性能优化的好方法，这能保证异常不会从客户端程序传递进程序库里，不过同时这样做也会妨碍客户端程序重定义程序库中声明的虚拟函数，并不允许有在客户端定义的回调函数。
　　使用异常处理的第二个开销来自于try块，无论何时使用它，也就是无论何时你想能够捕获异常，那你都得为此付出代价。不同的编译器实现try块的方法不同，所以编译器与编译器间的开销也不一样。粗略地估计，如果你使用try块，代码的尺寸将增加5%-10%并且运行速度也同比例减慢。这还是假设程序没有抛出异常，我这里讨论的只是在程序里使用try块的开销。为了减少开销，你应该避免使用无用的try块。
　　编译器为异常规格生成的代码与它们为try块生成的代码一样多，所以一个异常规格一般花掉与tyr块一样多的系统开销。什么?你说你认为异常规格只是一个规格而已，你认为它们不会产生代码?那么好，现在你应该对此有新的认识了。
　　现在我们来到了问题的核心部分，看看抛出异常的开销。事实上我们不用太关心这个问题，因为异常是很少见的，这种事件的发生往往被描述为exceptional(异常的，罕见的)。80-20规则(参见条款16)告诉我们这样的事件不会对整个程序的性能造成太大的影响。但是我知道你仍旧好奇地想知道如果抛出一个异常到底会有多大的开销，答案是这可能会比较大。与一个正常的函数返回相比，通过抛出异常从函数里返回可能会慢三个数量级。这个开销很大。但是仅仅当你抛出异常时才会有这个开销，一般不会发生。但是如果你用异常表示一个比较普遍的状况，例如完成对数据结构的遍历或结束一个循环，那你必须重新予以考虑。
　　不过请等一下，你问我是怎么知道这些事情的呢?如果说支持异常对于大多数编译器来说是一个较新的特性，如果说不同的编译器异常方法也不同，那么我如何能说程序的尺寸将增大5%-10%，它的速度也同比例减慢，而且如果有大量的异常被抛出，程序运行速度会呈数量级的减慢呢?答案是令人惊恐的:一些传闻和一些基准测试(benchmarks)(参见条款23)。事实是大部分人包括编译器生产商在异常处理方面几乎没有什么经验，所以尽管我们知道异常确实会带来开销，却很难预测出开销的准确数量。
　　谨慎的方法是对本条款所叙述的开销有了解，但是不深究具体的数量。(即定性不定量 译者注)不论异常处理的开销有多大我们都得坚持只有必须付出时才付出的原则。为了使你的异常开销最小化，只要可能尽量就采用不支持异常的方法编译程序，把使用try块和异常规格限制在你确实需要它们的地方，并且只有在确为异常的情况下(exceptional)才抛出异常。如果你在性能上仍旧有问题，总体评估一下你的软件以决定异常支持是否是一个起作用的因素。如果是，那就考虑选择其它的编译器，能在C++异常处理方面具有更高实现效率的编译器。
]]></description>
		</item>
		<item>
			<title>C++启蒙之注释符号</title>
			<link>http://www.kingmx.com/article.php?id=12238</link>
			<pubDate>2006-10-21</pubDate>
			<description><![CDATA[
在我们的程序变得更复杂之前，我们先看看C++是如何处理注释的。注释可以帮助人们阅读程序。在典型情况下，它们用于总结算法、表明变量的目的或澄清其它一些模糊的代码片段。注释不会增加可执行程序的大小。编译器会忽略所有注释。
　　在C++中有两种类型的注释：单行注释和成对注释。单行注释以双斜线（//）开头。同一行中斜线右侧的所有内容都是注释，会被编译器略过。
　　另一个分隔符是注释符号对（/* */），它继承自C语言。这种注释以/*开始，以*/结尾。编译器把/*和*/之间的部分都作为注释来处理：

#include &lt;iostream&gt;
/* 简单的main函数： 读入两个数字并输出结果 */
int main()
{
　// 提示用户输入数字
　std::cout &lt;&lt; &quot;Enter two numbers:&quot; &lt;&lt; std::endl;
　int v1, v2; // 初始化了的
　std::cin &gt;&gt; v1 &gt;&gt; v2; // 读取输入
　return 0;
}

　　注释符号对可以放置在允许输入tab、空格或新行的任何地方。注释符号对可以跨越程序的多个行，但是不是必须这样做的。当注释符号对没有跨越多个行，通常表明内部行是多行注释的一部分。我们的样式是每行以星号开始，因此表明整个范围都是多行注释的部分。
　　典型情况下程序包含多种注释形式。注释符号对通常用做多行解释，而双斜线注释倾向于半行或单行注释。
　　程序中混合了太多的注释可能使代码混乱。通常在要解释的代码上方放置注释。
　　随着代码的改变，注释也应该保持更新。程序员希望注释是精确的，并且很相信它们，即使其它形式的系统文档过期了。不正确的注释比没有注释还有糟糕，因为它会误导随后的阅读者。
　　注释符号对不能嵌套
　　以/*开始的注释通常以*/结束。其结果是一个注释符号对不能出现在另一个之中。这类程序错误导致的编译器错误消息可能难以理解。例如，在你的系统上编译下面的程序：

#include &lt;iostream&gt;
/*
* 注释符号对 /* */ 不能嵌套。
* &quot;不能嵌套&quot; 会被认为是源代码的一部分
*/
int main()
{
　return 0;
}

　　当你注释一大段程序的时候，看起来把注释符号对放在你希望临时略过的部分是最容易的。问题是如果那段代码已经有了注释符号对，那么新插入的注释将过早地终止。临时忽略一段代码的更好的办法是使用编辑器在希望忽略的代码的每一行前面插入单行注释。使用这种方法的时候，你就不必担心自己注释的代码是否包含注释符号对。
]]></description>
		</item>
		<item>
			<title>C#操作xml文件入门</title>
			<link>http://www.kingmx.com/article.php?id=12239</link>
			<pubDate>2006-10-21</pubDate>
			<description><![CDATA[
已知有一个XML文件（bookstore.xml）如下：
&lt;?xml version=&quot;1.0&quot; encoding=&quot;gb2312&quot;?&gt;
&lt;bookstore&gt;
&lt;book genre=&quot;fantasy&quot; ISBN=&quot;2-3631-4&quot;&gt;
&lt;title&gt;Oberon's Legacy&lt;/title&gt;
&lt;author&gt;Corets, Eva&lt;/author&gt;
&lt;price&gt;5.95&lt;/price&gt;
&lt;/book&gt;
&lt;/bookstore&gt;
1、往&lt;bookstore&gt;节点中插入一个&lt;book&gt;节点：
XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load(&quot;bookstore.xml&quot;);
XmlNode root=xmlDoc.SelectSingleNode(&quot;bookstore&quot;);//查找&lt;bookstore&gt;
XmlElement xe1=xmlDoc.CreateElement(&quot;book&quot;);//创建一个&lt;book&gt;节点
xe1.SetAttribute(&quot;genre&quot;,&quot;李赞红&quot;);//设置该节点genre属性
xe1.SetAttribute(&quot;ISBN&quot;,&quot;2-3631-4&quot;);//设置该节点ISBN属性
XmlElement xesub1=xmlDoc.CreateElement(&quot;title&quot;);
xesub1.InnerText=&quot;CS从入门到精通&quot;;//设置文本节点
xe1.AppendChild(xesub1);//添加到&lt;book&gt;节点中
XmlElement xesub2=xmlDoc.CreateElement(&quot;author&quot;);
xesub2.InnerText=&quot;候捷&quot;;
xe1.AppendChild(xesub2);
XmlElement xesub3=xmlDoc.CreateElement(&quot;price&quot;);
xesub3.InnerText=&quot;58.3&quot;;
xe1.AppendChild(xesub3);
root.AppendChild(xe1);//添加到&lt;bookstore&gt;节点中
xmlDoc.Save(&quot;bookstore.xml&quot;);
//================
结果为：
&lt;?xml version=&quot;1.0&quot; encoding=&quot;gb2312&quot;?&gt;
&lt;bookstore&gt;
&lt;book genre=&quot;fantasy&quot; ISBN=&quot;2-3631-4&quot;&gt;
&lt;title&gt;Oberon's Legacy&lt;/title&gt;
&lt;author&gt;Corets, Eva&lt;/author&gt;
&lt;price&gt;5.95&lt;/price&gt;
&lt;/book&gt;
&lt;book genre=&quot;李赞红&quot; ISBN=&quot;2-3631-4&quot;&gt;
&lt;title&gt;CS从入门到精通&lt;/title&gt;
&lt;author&gt;候捷&lt;/author&gt;
&lt;price&gt;58.3&lt;/price&gt;
&lt;/book&gt;
&lt;/bookstore&gt;
2、修改节点：将genre属性值为“李赞红“的节点的genre值改为“update李赞红”，将该节点的子节点&lt;author&gt;的文本修改为“亚胜”。
XmlNodeList nodeList=xmlDoc.SelectSingleNode(&quot;bookstore&quot;).ChildNodes;//获取bookstore节点的所有子节点
foreach(XmlNode xn in nodeList)//遍历所有子节点
{
XmlElement xe=(XmlElement)xn;//将子节点类型转换为XmlElement类型
if(xe.GetAttribute(&quot;genre&quot;)==&quot;李赞红&quot;)//如果genre属性值为“李赞红”
{
xe.SetAttribute(&quot;genre&quot;,&quot;update李赞红&quot;);//则修改该属性为“update李赞红”
XmlNodeList nls=xe.ChildNodes;//继续获取xe子节点的所有子节点
foreach(XmlNode xn1 in nls)//遍历
{
XmlElement xe2=(XmlElement)xn1;//转换类型
if(xe2.Name==&quot;author&quot;)//如果找到
{
xe2.InnerText=&quot;亚胜&quot;;//则修改
break;//找到退出来就可以了
}
}
break;
}
}
xmlDoc.Save(&quot;bookstore.xml&quot;);//保存。
//=================
最后结果为：
&lt;?xml version=&quot;1.0&quot; encoding=&quot;gb2312&quot;?&gt;
&lt;bookstore&gt;
&lt;book genre=&quot;fantasy&quot; ISBN=&quot;2-3631-4&quot;&gt;
&lt;title&gt;Oberon's Legacy&lt;/title&gt;
&lt;author&gt;Corets, Eva&lt;/author&gt;
&lt;price&gt;5.95&lt;/price&gt;
&lt;/book&gt;
&lt;book genre=&quot;update李赞红&quot; ISBN=&quot;2-3631-4&quot;&gt;
&lt;title&gt;CS从入门到精通&lt;/title&gt;
&lt;author&gt;亚胜&lt;/author&gt;
&lt;price&gt;58.3&lt;/price&gt;
&lt;/book&gt;
&lt;/bookstore&gt;
3、删除 &lt;book genre=&quot;fantasy&quot; ISBN=&quot;2-3631-4&quot;&gt;节点的genre属性，删除 &lt;book genre=&quot;update李赞红&quot; ISBN=&quot;2-3631-4&quot;&gt;节点。
XmlNodeList xnl=xmlDoc.SelectSingleNode(&quot;bookstore&quot;).ChildNodes;
foreach(XmlNode xn in xnl)
{
XmlElement xe=(XmlElement)xn;
if(xe.GetAttribute(&quot;genre&quot;)==&quot;fantasy&quot;)
{
xe.RemoveAttribute(&quot;genre&quot;);//删除genre属性
}
else if(xe.GetAttribute(&quot;genre&quot;)==&quot;update李赞红&quot;)
{
xe.RemoveAll();//删除该节点的全部内容
}
}
xmlDoc.Save(&quot;bookstore.xml&quot;);
//====================
最后结果为：
&lt;?xml version=&quot;1.0&quot; encoding=&quot;gb2312&quot;?&gt;
&lt;bookstore&gt;
&lt;book ISBN=&quot;2-3631-4&quot;&gt;
&lt;title&gt;Oberon's Legacy&lt;/title&gt;
&lt;author&gt;Corets, Eva&lt;/author&gt;
&lt;price&gt;5.95&lt;/price&gt;
&lt;/book&gt;
&l