<?xml version="1.0" encoding="GBK" ?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dcterms="http://purl.org/dc/terms/">
 <channel>
  	  <title><![CDATA[ziseliuxingzh的博客]]></title>
	  <link>http://ziseliuxingzh.blog.163.com</link>
	  <description><![CDATA[I am what I am? 我就是我,是颜色不一样的烟火! 人生得意须尽欢]]></description>
	  <language>zh-CN</language>
	  <pubDate>Mon, 17 Nov 2008 13:02:18 +0800</pubDate>
	  <lastBuildDate>Mon, 17 Nov 2008 13:02:18 +0800</lastBuildDate>
	  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
	  <generator><![CDATA[NetEase Space]]></generator>
	  <managingEditor><![CDATA[ziseliuxingzh]]></managingEditor>
	  <webMaster><![CDATA[ziseliuxingzh]]></webMaster>
		  <ttl>120</ttl>
	  <image>
	  	<title><![CDATA[ziseliuxingzh的博客]]></title>
	  	<url>http://ava.blog.163.com/photo/boptUyeplerhwffNiUp6kA==/177047760351260405.jpg</url>
	  	<link>http://ziseliuxingzh.blog.163.com</link>
	  </image>
  <item>
  	<title><![CDATA[Log4Net使用]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/51120863200810179594264</link>
    <description><![CDATA[<div><P>原链接：<A href="http://toyota2006.javaeye.com/blog/255978">http://toyota2006.javaeye.com/blog/255978</A></P>
<P>Log4Net应用指南 <BR>&nbsp;&nbsp; 我们在项目开发中尤其在开发比较大的项目日志是一定少不了的，因为我们在调试程序阶段会常常用到的，特别程序被部署以后就不太可能再利用专门的调试工具了，程序维护人员可能需要有一套强大的日志系统来诊断和修复配置上的问题。 <BR>&nbsp;&nbsp; 在J2EE项目中Apache的Log4j是大家最熟悉不过的日志系统，其实Apache也提供了其的姊妹系统Log4Net，顾名思义log4net是基于．Net开发的，它拥有和log4j一样强大的记录日志的功能，它可以将日志分不同的等级，比不同的样式，将日志输出到不同的媒介在SDE开发集成环境中的日志系统也是采用Log4Net，下面对其配置,应用加以介绍。 <BR>官方网站的配置例子:<U> http://logging.apache.org/log4net/release/config-examples.html</U> <BR>一，Log4net核心组成 <BR>Log4net主要由四个部分组成，分别是Logger（记录器）, Repository（库）, Appender（附着器）以及 Layout（布局）。 <BR><BR>二，配置标签是由logger和appender组成的. <BR>Logger记录日志的分类其能够以多种方式输出日志,支持的日志输出常用的主要媒介有数据库(包括 SQLServer,Access,oracle8i,oracle9i,,DB2等等)，控制台，文件，事件日志可以用事件查看器查看和邮件等多种方式。Log4net支持多种级别的日志，优先级从高到低排列如下： <BR>FATAL &gt; ERROR &gt; WARN . INFO .&gt; DEBUG <BR>此外还有ALL（允许所有的日志请求）和OFF（拒绝所有的日志请求）这两种提出的级别。 <BR>&nbsp;&nbsp;&nbsp; Appender决定日志输出的方式appender标签有两个重要的子节点fillter和layout。 <BR>&nbsp;&nbsp;&nbsp;&nbsp; Fiter负责过滤你想要得到的日志界别或包含特出的字符串。 <BR>&nbsp;&nbsp;&nbsp;&nbsp; Layout负责日志输出的样式。 <BR><BR>三，配置 <BR>1) 创建一个.Net项目中引入log4net.dll文件. <BR>2) 项目里新建一个配置文件log4net.config,配置如下(下面就以SDE中的一本程序配置加以说明) <BR><BR><BR></P>
<DIV >
<DIV >
<DIV >Java代码 <A title=复制代码 CopyToClipboard',this);return false;" href="http://toyota2006.javaeye.com/blog/255978#"><IMG  title="Log4Net使用 - ziseliuxingzh - ziseliuxingzh的博客" alt="Log4Net使用 - ziseliuxingzh - ziseliuxingzh的博客" alt=复制代码 src="http://toyota2006.javaeye.com/images/icon_copy.gif" _counted="undefined"></A></DIV></DIV>
<OL >
<LI><SPAN><SPAN>&lt;?xml&nbsp;version=</SPAN><SPAN ><FONT color=#0000ff>"1.0"</FONT></SPAN><SPAN>&nbsp;encoding=</SPAN><SPAN ><FONT color=#0000ff>"utf-8"</FONT></SPAN><SPAN>&nbsp;?&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&lt;configuration&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&lt;configSections&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&lt;!--配置系统完全分析配置文件以收集配置信息，当遇到在&nbsp;configSections&nbsp;节中没有相应条目的配置节时引发异常。&nbsp;对于那些不是由&nbsp;System.Configuration&nbsp;类型处理的节，提供了新的包装类型&nbsp;IgnoreSection。这是为了避免配置文件分析异常。&nbsp; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>出于兼容目的，还提供了&nbsp;IgnoreSectionHandler--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&lt;section&nbsp;name=</SPAN><SPAN ><FONT color=#0000ff>"log4net"</FONT></SPAN><SPAN>&nbsp;type=</SPAN><SPAN ><FONT color=#0000ff>"System.Configuration.IgnoreSectionHandler"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&lt;/configSections&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&lt;log4net&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>RollingFileAppender将日志以回滚文件的形式写到文件中。 &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&lt;appender&nbsp;name=</SPAN><SPAN ><FONT color=#0000ff>"ApplicationLogFileAppender"</FONT></SPAN><SPAN>&nbsp;&nbsp;type=</SPAN><SPAN ><FONT color=#0000ff>"log4net.Appender.RollingFileAppender"</FONT></SPAN><SPAN>&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--输出日志文件的路径--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&lt;file&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"ApplicationLog.log"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&lt;!--输出日志文件的编码格式--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;encoding&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"Shift_JIS"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&lt;!--输出日志时自动向后追加--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;appendToFile&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"true"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&lt;!--防止多线程时不能写Log,官方说线程非安全,但实际使用时,本地测试正常,部署后有不能写日志的情况--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;lockingModel&nbsp;type=</SPAN><SPAN ><FONT color=#0000ff>"log4net.Appender.FileAppender+MinimalLock"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&lt;!--置为</SPAN><SPAN ><STRONG><FONT color=#7f0055>true</FONT></STRONG></SPAN><SPAN>,当前最新日志文件名永远为file节中的名字--&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;staticLogFileName&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"false"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--日志以大小作为备份样式，还有一种方式是Date（日期）--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;rollingStyle&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"size"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;countDirection&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"-1"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&lt;!--单个日志的最大容量,(可用的单位:KB|MB|GB)不要使用小数,否则会一直写入当前日志--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;maximumFileSize&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"1MB"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--日志最大个数,都是最新的--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;maxSizeRollBackups&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"10"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;datePattern&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>'"."yyyy-MM-dd".log"'</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layout&nbsp;type=</SPAN><SPAN ><FONT color=#0000ff>"log4net.Layout.PatternLayout"</FONT></SPAN><SPAN>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&lt;conversionPattern&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"%d{yyyy/MM/dd,HH:mm:ss.fff},[%-5level],%message%newline"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/layout&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/appender&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&lt;appender&nbsp;name=</SPAN><SPAN ><FONT color=#0000ff>"ErrorLogFileAppender"</FONT></SPAN><SPAN>&nbsp;type=</SPAN><SPAN ><FONT color=#0000ff>"log4net.Appender.RollingFileAppender"</FONT></SPAN><SPAN>&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;file&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"ErrorLog.log"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;encoding&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"Shift_JIS"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;appendToFile&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"true"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;lockingModel&nbsp;type=</SPAN><SPAN ><FONT color=#0000ff>"log4net.Appender.FileAppender+MinimalLock"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;staticLogFileName&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"false"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;rollingStyle&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"size"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;countDirection&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"-1"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;maximumFileSize&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"1MB"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;maxSizeRollBackups&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"10"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;datePattern&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>'"."yyyy-MM-dd".log"'</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layout&nbsp;type=</SPAN><SPAN ><FONT color=#0000ff>"log4net.Layout.PatternLayout"</FONT></SPAN><SPAN>&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;conversionPattern&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"%d{yyyy/MM/dd,HH:mm:ss.fff},[%-5level],%message%newline"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/layout&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/appender&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&lt;logger&nbsp;name=</SPAN><SPAN ><FONT color=#0000ff>"ApplicationLog"</FONT></SPAN><SPAN>&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;如果没有定义LEVEL的值，则缺省为DEBUG&nbsp;--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;level&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"ALL"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--定义了appender的NAME及TYPE属性,以及使用param为其指定参数后（也可以没有参数）,一个appender就建立了,你可以使用他的名字在LOGGER的&lt;appender-ref中去&nbsp;引用它,那么,引用它的LOGGER在写入日志时,就是写到了APPENDER中定义的介质中去了--&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;appender-ref&nbsp;ref=</SPAN><SPAN ><FONT color=#0000ff>"ApplicationLogFileAppender"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/logger&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&lt;logger&nbsp;name=</SPAN><SPAN ><FONT color=#0000ff>"ErrorLog"</FONT></SPAN><SPAN>&nbsp;&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;level&nbsp;value=</SPAN><SPAN ><FONT color=#0000ff>"ERROR"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;appender-ref&nbsp;ref=</SPAN><SPAN ><FONT color=#0000ff>"ErrorLogFileAppender"</FONT></SPAN><SPAN>&nbsp;/&gt; &nbsp;&nbsp;</SPAN></SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/logger&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&nbsp;&nbsp;&lt;/log4net&gt; &nbsp;&nbsp;</SPAN></LI>
<LI><SPAN>&lt;/configuration&gt;&nbsp;&nbsp;</SPAN></LI></OL></DIV></div>]]></description>
	    <author><![CDATA[ziseliuxingzh]]></author>
	    <comments>http://ziseliuxingzh.blog.163.com/blog/static/51120863200810179594264</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://ziseliuxingzh.blog.163.com/blog/static/51120863200810179594264</guid>
    <pubDate>Mon, 17 Nov 2008 09:59:04 +0800</pubDate>
    <dcterms:modified>2008-11-17T10:38:49+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Rational Rose2003安装（转）]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/5112086320081012104340660</link>
    <description><![CDATA[<div><H2>&nbsp;</H2>
<UL dir=ltr style="MARGIN-RIGHT: 0px">
<LI>的确，如果我们在生活和工作中没有激情，我们将无法体验到淋漓尽致的欢乐和痛苦。<BR>以前没有用过Rational Rose;据说可以帮助我们开发大的项目，甚至使我们的软件开发产业化或者...<BR>今天搞了一个晚上，终于安装成功了，现在把它记录下来 
</LI><LI>安装文件搜了很久，结果在一个中学的主页上找到了，当时感觉到自己真是落后呀<A href="http://2004.nj13z.cn//down_view.asp?action=download&amp;id=14">&nbsp;，现在中学的都开始涉及R_Rose</A> 
</LI><LI>下载地址：<A href="http://2004.nj13z.cn//down_view.asp?action=download&amp;id=14">http://2004.nj13z.cn//down_view.asp?action=download&amp;id=14</A>&nbsp;&nbsp;&nbsp; （右键直接下载Rational Rose 2003） 
</LI><LI>解压后开始安装的第一个问题： 我的系统是xp_sp2的，会出现 Mem_pointer_Bad 
</LI><LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 原因应该是某个函数因为安全等级问题而无法运行，只要把 ./common/SHW32.dll替换。<BR>&nbsp;&nbsp;&nbsp;&nbsp; 下载地址：&nbsp; <A href="http://www.cjsdn.net/user/download/129846/SHW32.DLL">http://www.cjsdn.net/user/download/129846/SHW32.DLL</A><BR>MicroQuill提供的文件是shw32.dll<BR>使用这个Dll之后，就不会出现MEM_BAD_POINTER的提示了。<BR>下面是MicroQuill提供的修改方法：<BR>1) extract shw32.dll from the attached zip file.<BR>2) locate the copy of shw32.dll that the affected program (the one that's <BR>giving the MEM_BAD_POINTER error) is using. Rename this file, or move it to <BR>some other directory for safe keeping. Note: this step is not strictly <BR>necessary, BUT if you experience problems with our new DLL, the first thing <BR>we're going to suggest is that you revert to your old one.<BR>3) with your old shw32.dll renamed or moved for safe keeping, install the new <BR>shw32.dll where the old one used to be. Now run your app as usual and verify <BR>that the error no longer appears.<BR>4) if after step 3 you still see the MEM_BAD_POINTER error, search your hard <BR>drives for any other occurrences of shw32.dll and replace those (using the <BR>above procedures), one at a time, until the error no longer appears.<BR>5.然后就是注册，网上好多文件的覆盖方式，我没有实践（估计可以）<BR>&nbsp;&nbsp; 我们在这里介绍一个更细的方法：<BR>5.1.安装Rose后,默认是需要许可证书的..去下载个破解的..我上传了破解文件..<A href="http://www.cnblogs.com/Files/lixianhuei/rose2003crack.rar" target=_blank>点击这里下载Rose 2003破解</A><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp; 5.2.先用破解压缩包里的 rational.exe，lmgrd.exe 覆盖到你的 \安装目录的Rartional\commen\下<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp; 5.3.然后记事本打开 license.dat, 修改里面的 SERVER yourPC ANY&nbsp; DAEMON rational "C:\Program Files\Rational\Common\rational.exe" <BR>&nbsp;&nbsp;&nbsp;&nbsp; 改成 SERVER 你的机器名 ANY&nbsp; DAEMON rational "你的安装目录\rational.exe" ,拷贝到Common目录下..(注意：耐心查找)<BR><BR>&nbsp;&nbsp;&nbsp; 5.4. 将Flexlm.cpl拷贝到C:\winnt\system32\下， 在控制面板里运行 FlexLm License Manager，&nbsp;<BR>运行后, 在 Setup 面板配置文件路径，lmgrd.exe -&gt; 你的安装目录 \Common\lmgrd.exe, 而 License File 为你改过的 license.dat ...<BR><BR><IMG height=245 hspace=5 src="http://lixianhuei.cnblogs.com/images/cnblogs_com/lixianhuei/2.gif" width=477 align=baseline><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp; 5/5.在Control面板点击Start，如果成功的话点击Status按钮将显示 你的机器名：license server UP (MASTER) 说明成功了 <BR>&nbsp;&nbsp;&nbsp;&nbsp; 失败的话重启一下FlexLm License Manager就没问题了。&nbsp;<BR><BR><IMG height=245 hspace=5 src="http://lixianhuei.cnblogs.com/images/cnblogs_com/lixianhuei/3.gif" width=477 align=baseline><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp; 5.6.如果弹出对话框License Key Administrator Wizard后, 选定Point to a Rational License Server to get my licenses，单击下一步， <BR>Server Name文本框中填写你的机器号(可能已经填好)，单击完成。 (成功的话会出现两屏的licenses)&nbsp;<BR></LI></UL></div>]]></description>
	    <author><![CDATA[ziseliuxingzh]]></author>
	    <comments>http://ziseliuxingzh.blog.163.com/blog/static/5112086320081012104340660</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://ziseliuxingzh.blog.163.com/blog/static/5112086320081012104340660</guid>
    <pubDate>Wed, 12 Nov 2008 10:43:40 +0800</pubDate>
    <dcterms:modified>2008-11-12T10:43:40+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[金融危机到底是如何产生的]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/5112086320081037235565</link>
    <description><![CDATA[<div><P>转自：<A href="http://www.amteam.org/k/strategy/2008-10/614029.html">http://www.amteam.org/k/strategy/2008-10/614029.html</A></P>
<P>&nbsp;</P>
<P>目前，很多人感觉到国际经济形势发生了巨大变化，都在问世界范围内的金融危机到底是怎么一回事？很多经济学家通过各种理论、模型，以专业的角度向大家长篇大论地讲解，可是很多人听过之后还是弄不明白金融危机到底是如何发生的。我们在这里花5分钟时间，通过《两兄弟种粮》的故事通俗地讲解一下金融危机产生的原理。</P>
<P>很久以前，地球上有一块不为人知的荒岛，后来探险家们前往世界各地探险，无意中惊奇地发现这块荒岛地域辽阔，地质肥沃，环境也还不错，这一消息传开后，人们不远万里竞相前往这块被誉为宝地的荒岛圈地、抢地。有一家哥弟俩人也结伴前往，好不容易圈占了一处肥沃的土地，与此同时，其他一起赶来到邻居、同行人也抢到了划归自己名下的一块地，就这样，这块荒岛很快就被人们瓜分完毕了。</P>
<P>两兄弟看到眼前这么大块地，激动无比。哥哥说：“弟弟，我们把地划分为两半，一半由我种植土豆，一半由你种植小麦，怎么样？”。弟弟听后说，“分成两半地可以，但是我喜欢吃土豆，不喜欢吃小麦啊”。哥哥说，“没关系，等我们各自种植丰收后，我把我收获的一半土豆给你，你把你收获的一半小麦给我，这样我们俩吃的还能够丰富一些，生活不是很好吗？”弟弟一听，觉得哥哥说得很有道理，于是就采纳了哥哥的建议。这一年，哥哥用新圈占土地的一半种上了土豆，弟弟用另一半土地种上了小麦。第一年风调雨顺，两兄弟在各地的田间辛勤劳作，土豆和小麦都丰收了，哥弟俩人按事先的约定交换了粮食，每人都有土豆和小麦，生活过得很美好。</P>
<P>可是第二年岛上的气候发生变化，不再风调雨顺了。哥哥种植的土豆受到气候变化的影响，没有了收成，但是弟弟种植的小麦基本未受到气候变化的影响，依旧有很好的收成。这时候，哥哥为自己的生计而犯愁了，但是想到弟弟种植的小麦还是有收成的，自己也不能在这块岛上挨饿，于是和弟弟商量，说自己先写一张借条，借弟弟的小麦先把生活问题解决了，等明年自己种植的土豆丰收了再多还一些土豆给弟弟。弟弟想到，都是自己的亲兄弟，不应该让哥哥饿着啊，而且哥哥一向说话算数的，所以就把自己收获的小麦分了一半给哥哥，自己手里拿了一张哥哥坚持要给他的借条，并存放到了床头的箱子底下。</P>
<P>春去秋来，转眼就到了第三年，哥哥本来是要把土豆种出来还给弟弟的，但是第三年天公还是不作美，气候条件更恶劣导致土豆颗粒无收。没有办法，哥哥只好厚着脸皮再次向弟弟借小麦，自己仍然写了一张借条给弟弟。</P>
<P>当哥哥从弟弟那里拉回小麦，走进屋子时脑子里瞬间想到：原来这一年我不忙关系也不大啊，我没有吃的时候弟弟是会借小麦给我吃的。就这样，从第四年开始，哥哥就不再用心种土豆了，心里盘算着大不了到时候打一张借条。尽管第四年气候很好，但是哥哥仍然没有用心去打理自己的田地。不过这时候哥哥也在琢磨：要是弟弟不再借给我土豆怎么办？哥哥开始为自己的生活准备后路。想到周围几年前一起到岛上来的人，哥哥就在岛上周游看了一圈，看到周围的邻居种着大豆、梨子、苹果等等，都呈现出一派丰收景象。哥哥灵机一动，对一个种苹果的邻居说：“你看我家有小麦，我弟弟种植的小麦产量更是丰盛，你能不能借些苹果给我，我给你一张借条，以后用小麦交换？”种苹果的邻居不知道两兄弟是独立经营，只知道他们家的小麦产量的确很多，想到小麦还是耐以生存的主要粮食，所以就借出了苹果，自己留下了一张哥哥写的借条。哥哥见到此笔交易做成，迅即如法炮制，结果是周围的邻居各自都收到了借条，哥哥想到即将到手的满屋子食粮，心想自己不用种粮也能够过上富足、自由的生活，心里乐开了花。</P>
<P>哥哥由此没有了种庄稼的心思，心里面打起了各种算盘。他盘算着要是明年弟弟不给小麦怎么办？这可是要用来和周围人进行交换的。这位哥哥的脑袋瓜的确异常敏捷，心里一合计，干脆就不再想种地的事情了，索性在本应用来种土豆的土地一角搭建了一个炼铁的炉窑，制造了大刀，并将第一把制作完成的大刀挂在自家门口。</P>
<P>很快第五年就到了，弟弟要来向哥哥兑现借条，取回自己多年想要的土豆了，到了哥哥家的门口，看到此处门庭若市、人来人往，走过哥哥家挂着大刀的门，继续往屋子里走，看到房屋内壁都挂着寒光闪闪的大刀，越往里走心里越是感到害怕，到了屋子大厅一看，厅里虽然小麦不多，但是其他的谷物粮食倒不少，弟弟本来是想要回土豆的，但是看到杀气逼人的大刀和其他粮食，心里想，“哥哥虽然没有土豆，但是还是有其他粮食，应该还得起”。由此作罢，弟弟也就不再向哥哥提及自己的土豆，还收到了哥哥给自己的又一张借条。以后的日子，弟弟手上的借条越来越多，哥哥的日子越来越舒服。</P>
<P>空闲下来的哥哥后来想，这样做还是不行，索性就在种土豆的地上盖起了房子，开了一家酒吧，提供了一个邻里、路人可以饮酒、喝咖啡的休闲、娱乐场所，于是，越来越多的邻居到了哥哥开设的酒吧里喝啤酒、喝咖啡、拉家常。</P>
<P>一天，前来饮酒的一位邻居喝得起兴，有些醉了，就对同桌的伙伴说：“喝酒真是享受啊，我手里的借条这么多年了，怎么就没有为我带来享受生活的机会呢？”同桌的伙伴一听，就问，“你也有借条？你的借条哪来的啊？”这位喝醉酒的邻居开口就说，“就是这位开酒吧的、这家老大借我东西之后留下的呀。”这一下关于借条的信息曝光了，大家把自己的借条拿出来一看，全是哥哥欠的。这还得了？！</P>
<P>故事发展到这一步，问题就出来了，当大家都想要把手上原本认为有价值的“借条”变成自己应当享有的“果实”的时候，事情就闹大了，放大到国际经济运营中，我们的金融危机也就发生了。最近美国爆发出的金融危机可不是一件小事，如果大家知道美国人的生活方式，就会知道，美国人贷款了就会去买车，并且还可以卖掉自己的贷款，由此带来的金融衍生品数量增大，据统计，美国1美元经过流动最后放大了22.5倍，所以格林斯潘讲了，这次危机不是一般的危机，是一场百年不遇的危机。</P>
<P>在我看来，我认为这场危机的发生是不大可能在短时间内缓和、复苏的。2008年我们国家的经济也有些过热，经济形势相对严峻，经济过热的原因是流动性过剩，或者说在市面上的流动的现金太多。有社科院专家6月份披露数据说，中国资本市场上的“热钱”（国际金融市场上迅速流动的中短期投机性资金）数额已高达1.75万亿美元，相当于12万亿人民币。我们国家金融衍生品如何，比如1块钱在市面上通过流动周转、买卖、抵押贷款等也有放大，但是这个范围大概不超过1.5。这样一算，美国是22.5倍，问题就太严重了，这样一个经济体如同被放大上百万倍的气球，一旦爆炸还能够剩下什么？美国这个经济体一旦崩溃还有什么资金？就像故事中哥哥原来那一半存有的土豆一样，早已经用完了，我们目前正好赶上了这么一个“人”，怎么办？大家在这样的条件下就必须清楚自己将遇到的困难可不小，需要提前做好应对准备。</P>
<P>希望通过以上这个故事，大家可以简单地了解一下金融危机产生的基本模型，至于应对措施，那将是一项更为系统的工程。</P></div>]]></description>
	    <author><![CDATA[ziseliuxingzh]]></author>
	    <comments>http://ziseliuxingzh.blog.163.com/blog/static/5112086320081037235565</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://ziseliuxingzh.blog.163.com/blog/static/5112086320081037235565</guid>
    <pubDate>Mon, 3 Nov 2008 19:23:05 +0800</pubDate>
    <dcterms:modified>2008-11-03T19:23:05+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[post,get method]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/51120863200810393111651</link>
    <description><![CDATA[<div><P><FONT face="Times New Roman" size=3>来源：www.netfocus.cn 焦点网</FONT><SPAN >Phontol.com</SPAN></P>
<P><FONT face="Times New Roman" size=3>&nbsp;<BR><SPAN >www.Phontol.com</SPAN><SPAN >Phontol.com</SPAN></FONT></P>
<P>在<A href="http://www.w3.org/TR/REC-html40/">HTML</A>中，<A href="http://www.w3.org/TR/REC-html40/interact/forms.html">form元素</A>用<A href="http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.1">method属性</A>来指定有两种不同的提交方法，即"get"（默认值）和"post"。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<H1>1. get和post的定义</H1>
<P><A href="http://www.w3.org/">W3C</A>的<A href="http://www.w3.org/TR/REC-html40/">HTML 4.01 specification</A>说，<A href="http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13">form元素的method属性</A>用来指定发送form的HTTP方法。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<UL>
<LI>使用get时，form的<A href="http://www.w3.org/TR/REC-html40/interact/forms.html#form-data-set">数据集</A>（形如control-name=current-value的键值对）被附加到form元素的action属性所指定的URI后面； 
</LI><LI>使用post时，form的数据集（形如control-name=current-value的键值对）被包装在请求的body中并被发送。<SPAN >Phontol.com</SPAN> </LI></UL>
<P>这可以简单地理解为，get仅仅是拼接一个URI，然后直接向服务器请求数据（需要提交给服务器的数据集包含在URI中）。<SPAN >Phontol.com</SPAN>比如：<SPAN >Phontol.com</SPAN></P>
<P>&nbsp;<SPAN >Phontol.com</SPAN></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">form&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">method</SPAN><SPAN style="COLOR: rgb(0,0,255)">="get"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;action</SPAN><SPAN style="COLOR: rgb(0,0,255)">="FormGet.aspx"</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">input&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">type</SPAN><SPAN style="COLOR: rgb(0,0,255)">="text"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;name</SPAN><SPAN style="COLOR: rgb(0,0,255)">="ProductID"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;value</SPAN><SPAN style="COLOR: rgb(0,0,255)">="1"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">/&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">input&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">type</SPAN><SPAN style="COLOR: rgb(0,0,255)">="submit"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;value</SPAN><SPAN style="COLOR: rgb(0,0,255)">="Get"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">/&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">form</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN></DIV>
<P><BR><SPAN >www.Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<P>这个form在提交的时候，会产生这样能够一个get请求：FormGet.aspx?ProductID=1。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<P>而post会把form的数据集，即ProductID=1这个键值对包装在请求的body中，发送给服务器，然后向服务器请求数据。<SPAN >Phontol.com</SPAN>对于：<SPAN >Phontol.com</SPAN></P>
<P>&nbsp;<SPAN >Phontol.com</SPAN></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">form&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">method</SPAN><SPAN style="COLOR: rgb(0,0,255)">="post"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;action</SPAN><SPAN style="COLOR: rgb(0,0,255)">="FormPost.aspx"</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">input&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">type</SPAN><SPAN style="COLOR: rgb(0,0,255)">="text"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;name</SPAN><SPAN style="COLOR: rgb(0,0,255)">="ProductID"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;value</SPAN><SPAN style="COLOR: rgb(0,0,255)">="1"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">/&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">input&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">type</SPAN><SPAN style="COLOR: rgb(0,0,255)">="submit"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;value</SPAN><SPAN style="COLOR: rgb(0,0,255)">="Get"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">/&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">form</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN></DIV>
<P><BR><SPAN >www.Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<P>这样一个form在提交时，我们将看到一个干净的URI：FormPost.aspx。<SPAN >Phontol.com</SPAN>因为数据不是拼接在URI中。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<H1>2. get和post的区别</H1>
<H2>2.1 安全性</H2>
<P>如果用get提交一个验证用户名和密码的form，一般认为是不安全的。<SPAN >Phontol.com</SPAN>因为用户名和密码将出现在URL上，进而出现在浏览器的历史记录中。<SPAN >Phontol.com</SPAN>显然，在对安全性有要求的情况下，应该使用post。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<H2>2.2 编码</H2>
<P><A href="http://www.w3.org/TR/REC-html40/">HTML 4.01 specification</A>指出，get只能向服务器发送ASCII字符，而post则可以发送整个<A href="http://www.w3.org/TR/REC-html40/references.html#ref-ISO10646">ISO10646</A>中的字符（如果同时指定<A href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-enctype">enctype</A>="multipart/form-data"的话）。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<P>注意get和post对应的enctype属性有区别。<SPAN >Phontol.com</SPAN>enctype有两个值，默认值为application/x-www-form-urlencoded，而另一个值multipart/form-data只能用于post。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<H2>2.3 提交的数据的长度</H2>
<P>HTTP specification并没有对URL长度进行限制，但是IE将请求的<A href="http://support.microsoft.com/kb/208427/en-us">URL长度限制为2083个字符</A>，从而限制了get提交的数据长度。<SPAN >Phontol.com</SPAN>测试表明如果URL超出这个限制，提交form时IE不会有任何响应。<SPAN >Phontol.com</SPAN>其它浏览器则没有URL的长度限制，因此其它浏览器能通过get提交的数据长度仅受限于服务器的设置。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<P>而对于post，因为提交的数据不在url中，所以通常可以简单地认为数据长度限制仅受限于服务器的设置。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<H2>2.4 缓存</H2>
<P>由于一个get得到的结果直接对应到一个URI，所以get的结果页面有可能被浏览器缓存。<SPAN >Phontol.com</SPAN>而post一般则不能，参考5。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<H2>2.5 引用和SEO</H2>
<P>出于和上面相同的原因，我们可以用一个URI引用一个get的结果页面，而post的结果则不能，所以必然不能被搜索引擎搜到。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<H1>3. 服务端的处理</H1>
<P>在服务端的ASP.NET程序中，对于get，我们用Request.QueryString[control-name]来取得对应的=current-value；对于post，我们用Request.Form[control-name]。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<P>我们也可以笼统地使用Request[control-name]。<SPAN >Phontol.com</SPAN>但这样做的效率不如前者。<SPAN >Phontol.com</SPAN>我们可以用下面的程序比较Request.QueryString和Request的效率：<SPAN >Phontol.com</SPAN></P>
<P>&nbsp;<SPAN >Phontol.com</SPAN></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(255,255,0)">&lt;%</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">@&nbsp;Page&nbsp;Language</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">C#</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(255,255,0)">%&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN><BR><SPAN >www.Phontol.com</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;!</SPAN><SPAN style="COLOR: rgb(255,0,255)">DOCTYPE&nbsp;html&nbsp;PUBLIC&nbsp;"-//W3C//DTD&nbsp;XHTML&nbsp;1.0&nbsp;Transitional//EN"&nbsp;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN><BR><SPAN >www.Phontol.com</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">script&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">runat</SPAN><SPAN style="COLOR: rgb(0,0,255)">="server"</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">void</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;Page_PreInit(object&nbsp;sender,&nbsp;EventArgs&nbsp;e)<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;{<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">if</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">(Request[</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">InputString</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">]&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">!=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">null</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">)<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">int</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;count&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">1000000</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DateTime&nbsp;start;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DateTime&nbsp;end;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;value&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">""</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;DateTime.Now;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">for</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">(</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">int</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">0</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">;i&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&lt;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;count;i</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">++</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">)<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;Request.QueryString[</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">InputString</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">];<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;DateTime.Now;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">double</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;requestGet&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;(end&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">-</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;start).TotalSeconds;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;DateTime.Now;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">for</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">(</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">int</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">0</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">;i&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&lt;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;count;i</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">++</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">)<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;Request[</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">InputString</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">];<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;DateTime.Now;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255); BACKGROUND-COLOR: rgb(245,245,245)">double</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;request&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;(end&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">-</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;start).TotalSeconds;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;compare.InnerHtml&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;requestGet.ToString()&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">+</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;/&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">+</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;request.ToString()&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">+</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;=&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">"</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">+</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;(requestGet&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">/</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;request).ToString();<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get.InnerHtml&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">=</SPAN><SPAN style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(245,245,245)">&nbsp;value;<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><SPAN >www.Phontol.com</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">script</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN><BR><SPAN >www.Phontol.com</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">html&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">xmlns</SPAN><SPAN style="COLOR: rgb(0,0,255)">="http://www.w3.org/1999/xhtml"</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">head</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">meta&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">http-equiv</SPAN><SPAN style="COLOR: rgb(0,0,255)">="Content-Type"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;content</SPAN><SPAN style="COLOR: rgb(0,0,255)">="text/html;&nbsp;charset=utf-8"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">/&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">title</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">Request.QueryString&nbsp;/&nbsp;Request</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">title</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">head</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">body</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">form&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">method</SPAN><SPAN style="COLOR: rgb(0,0,255)">="get"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;action</SPAN><SPAN style="COLOR: rgb(0,0,255)">="FormGet.aspx"</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">div</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">input&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">type</SPAN><SPAN style="COLOR: rgb(0,0,255)">="text"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;name</SPAN><SPAN style="COLOR: rgb(0,0,255)">="InputString"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">/&gt;&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">input&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">type</SPAN><SPAN style="COLOR: rgb(0,0,255)">="submit"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;value</SPAN><SPAN style="COLOR: rgb(0,0,255)">="Post"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">/&gt;&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">br&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">/&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get:&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">span&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">runat</SPAN><SPAN style="COLOR: rgb(0,0,255)">="server"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;id</SPAN><SPAN style="COLOR: rgb(0,0,255)">="get"</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">span</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">br&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">/&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Request.QueryString&nbsp;/&nbsp;Request:&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">span&nbsp;</SPAN><SPAN style="COLOR: rgb(255,0,0)">runat</SPAN><SPAN style="COLOR: rgb(0,0,255)">="server"</SPAN><SPAN style="COLOR: rgb(255,0,0)">&nbsp;id</SPAN><SPAN style="COLOR: rgb(0,0,255)">="compare"</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">span</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">div</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">form</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">body</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><SPAN >www.Phontol.com</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">html</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN></DIV>
<P><BR><SPAN >www.Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<P>同样的办法我们可以比较Request.Form和Request。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<P>最后得到的结果（Request.QueryString[control-name] / Request[control-name]和Request.Form[control-name] / Request[control-name]）大多数时候是小于1的。<SPAN >Phontol.com</SPAN>因此，我们因该尽量用Request.QueryString或 Request.Form来代替Request。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<H1>4. 正确地使用get和post</H1>
<P><A href="http://www.w3.org/">W3C</A>的官方建议是：当且仅当form是幂等（idempotent）的时候，使用get。<SPAN >Phontol.com</SPAN>幂等是一个数学上的术语，其<A href="http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?query=idempotent&amp;action=Search">定义</A>是：对于一个函数f : D -&gt; D，如果D中的所有x满足f (f x) = f x，那么这个函数是幂等的。<SPAN >Phontol.com</SPAN><A href="http://www.w3.org/Protocols/">HTTP specification</A>（比如<A href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">RFC 2616</A>）中，将幂等解释为：多次相同请求产生的副作用，和一次请求的副作用相同。<SPAN >Phontol.com</SPAN> <SPAN >Phontol.com</SPAN></P>
<P>打个比方，如果你提交一个form会从<A href="http:///www.google.com">Google</A>上查询一个关键词，那么我们可以认为这个form是幂等的，因为1次提交和10次提交的副作用是差不多的（10次查询可能会多消耗一些电能）；如果你提交一个form是订购一个<A href="http://www.amazon.com/Hasbro-Transformers-Ultimate-Bumblebee-Figure/dp/B000OKXRQ0">终极大黄蜂（Utimate bumblebee）</A>，那么这就不是幂等的：要是你不小心多提交了1次form的话，你可能会被老婆乱骂，你不小心又提交了10次的话，你可能就破产了——一次提交和多次提交的副作用明显不同，所以这不是幂等的。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<P>所以，一般来说，如果提交这个请求纯粹只是从服务端获取数据而不进行其他操作，并且多次提交不会有明显的副作用，应该使用get。<SPAN >Phontol.com</SPAN>比如：<SPAN >Phontol.com</SPAN></P>
<UL>
<LI>搜索引擎的查询：<A href="http://www.google.com/search?q=yandixin">http://www.google.com/search?q=yandixin</A>； 
</LI><LI>分页：ArticleList.asp?Page=1。<SPAN >Phontol.com</SPAN> </LI></UL>
<P>如果提交这个请求会产生其它操作和影响，就应该使用post。<SPAN >Phontol.com</SPAN>比如：<SPAN >Phontol.com</SPAN></P>
<UL>
<LI>修改服务器上数据库中的数据； 
</LI><LI>发送一封邮件； 
</LI><LI>删除一个文件。<SPAN >Phontol.com</SPAN> </LI></UL>
<P>另一个要考虑的因素是安全性。<SPAN >Phontol.com</SPAN>见2.1。<SPAN >Phontol.com</SPAN><SPAN >Phontol.com</SPAN></P>
<H1>5. 浏览器差异</H1>
<UL>
<LI>IE 6：URL长度限制为2083个字符；post之后，刷新页面不会自动重新post数据，会出现警告；<BR><SPAN >www.Phontol.com</SPAN><IMG alt="" src="http://www.phontol.com/topic_pic/2008/1/298_1_e0iwhg.gif" border=0>&nbsp;<BR><SPAN >www.Phontol.com</SPAN>并且，在后退的过程中有可能出现“Page has Expired”（通常是向自己post，然后后退时）：<BR><SPAN >www.Phontol.com</SPAN><IMG alt="" src="http://www.phontol.com/topic_pic/2008/1/298_2_czo5op.gif" border=0>&nbsp;<BR><SPAN >www.Phontol.com</SPAN>微软的技术支持人员<A href="http://www.thescripts.com/forum/thread314750.html">号称</A>“this is not a bug or problem specified to the ASP.NET but a security feature of the IE Browser”，并且说“You can also inform your users of this”，实在是荒唐。<SPAN >Phontol.com</SPAN>另外，<A href="http://support.microsoft.com/kb/183763">一篇KB</A>也提到这个问题，说将Response.CacheControl设为"Public"即可，经测试仅在第一次后退时有效。<SPAN >Phontol.com</SPAN> 
</LI><LI>IE 7：和IE 6相同； 
</LI><LI>Firefox 2.0.0.11：刷新页面不会自动重新post数据，会出现警告；<BR><SPAN >www.Phontol.com</SPAN><IMG alt="" src="http://www.phontol.com/topic_pic/2008/1/298_3_gke74u.gif" border=0>&nbsp; 
</LI><LI>Opera 9.24：正常（自动post数据）； 
</LI><LI>Safari 3.0.4：post之后，刷新页面、前进、后退都不会自动重新post数据，会出现警告。<SPAN >Phontol.com</SPAN><BR><SPAN >www.Phontol.com</SPAN><IMG alt="" src="http://www.phontol.com/topic_pic/2008/1/298_4_7gxvc0.gif" border=0>&nbsp; </LI></UL></div>]]></description>
	    <author><![CDATA[ziseliuxingzh]]></author>
	    <comments>http://ziseliuxingzh.blog.163.com/blog/static/51120863200810393111651</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://ziseliuxingzh.blog.163.com/blog/static/51120863200810393111651</guid>
    <pubDate>Mon, 3 Nov 2008 09:31:11 +0800</pubDate>
    <dcterms:modified>2008-11-03T09:31:11+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[To use TClientDataset as memory dataset]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/51120863200882385119280</link>
    <description><![CDATA[<div><P style="TEXT-INDENT: 2em">As you know starting from Delphi 3, Borland included TClientDataset component as a database-independent engine.</P>
<P style="TEXT-INDENT: 2em">Generally this component is used for multi-tier environments when you transfer from server application to client application your data (using TProvider).</P>
<P style="TEXT-INDENT: 2em">But today I want to show how to use standard TClientDataset component for memory-dataset without any multi-tiered application.</P>
<P style="TEXT-INDENT: 2em">On any archive you may find some third-party memory datasets:</P>
<P style="TEXT-INDENT: 2em">- TRxMemoryData from freeware RxLib/JVCL (I must say that only TMemoryTable from RX depends from BDE. TRxMemoryData don't use BDE)</P>
<P style="TEXT-INDENT: 2em">- DevExpress MemData</P>
<P style="TEXT-INDENT: 2em">- KbmMemTable</P>
<P style="TEXT-INDENT: 2em">and a lot of another components</P>
<P style="TEXT-INDENT: 2em">Also some from you use third-party database engines (Apollo/DBISAM/Halcyon/...) in mode when you don't need a real database. Exists a lot of task when real database is not required. All what you need is some temporary dataset.</P>
<P style="TEXT-INDENT: 2em">So I want to show how to use TClientDataset in such mode on small sample.</P>
<P style="TEXT-INDENT: 2em">1. you must create a TClientDataset instance. You may do it in design-time (simply drop a component on form) or in run-time (for example, in OnCreate event of your form):</P>
<P style="TEXT-INDENT: 2em">table := TClientDataset.Create(Application);</P>
<P style="TEXT-INDENT: 2em">2. you must add the field defintions:</P>
<P style="TEXT-INDENT: 2em">table.FieldDefs.Add('ID', ftInteger, 0, False);</P>
<P style="TEXT-INDENT: 2em">table.FieldDefs.Add('Status', ftString, 10, False);</P>
<P style="TEXT-INDENT: 2em">table.FieldDefs.Add('Created', ftDate, 0, False);</P>
<P style="TEXT-INDENT: 2em">table.FieldDefs.Add('Volume', ftFloat, 0, False);</P>
<P style="TEXT-INDENT: 2em">3. create a dataset with specified structure:</P>
<P style="TEXT-INDENT: 2em">table.CreateDataset</P>
<P style="TEXT-INDENT: 2em">4. open a dataset</P>
<P style="TEXT-INDENT: 2em">table.Open</P>
<P style="TEXT-INDENT: 2em">5. it's all! Now you may add/edit/delete records, change an order (sort) and any another action that is available for any dataset.</P>
<P style="TEXT-INDENT: 2em">For example, to add random values to records:</P>
<P style="TEXT-INDENT: 2em">for i := 1 to 100 do </P>
<P style="TEXT-INDENT: 2em">begin </P>
<P style="TEXT-INDENT: 2em">table.Append;</P>
<P style="TEXT-INDENT: 2em">&nbsp;table.FieldByName('ID').AsInteger := i; </P>
<P style="TEXT-INDENT: 2em">table.FieldByName('Status').AsString := 'Code'+IntToStr(i); </P>
<P style="TEXT-INDENT: 2em">table.FieldByName('Created').AsDateTime := Date();</P>
<P style="TEXT-INDENT: 2em">&nbsp;table.FieldByName('Volume').AsFloat := Random(10000); t</P>
<P style="TEXT-INDENT: 2em">able.Post; </P>
<P style="TEXT-INDENT: 2em">end;</P>
<P style="TEXT-INDENT: 2em">6. if you want to change an order for records, simply change IndexFieldNames property. For example, next command will sort your memory dataset by Created field:</P>
<P style="TEXT-INDENT: 2em">table.IndexFieldNames := 'Created';</P>
<P style="TEXT-INDENT: 2em">7. note that TClientDataset also allow to save memory dataset to file and load from file:</P>
<P style="TEXT-INDENT: 2em">table.SaveToFile('c:\mem.cds');</P>
<P style="TEXT-INDENT: 2em">table.LoadFromFile('c:\mem.cds');</P>
<P style="TEXT-INDENT: 2em">A few file formats are supported - internal cds-format and xml-format</P>
<P style="TEXT-INDENT: 2em">Of course, you may use SMImport suite for save/load too - it will work with such memory dataset without any problems. So you may expand your application and load data from MS Excel-spreadsheet or MS Access database, for example.</P>
<P style="TEXT-INDENT: 2em">So in such manner you may transfer your data between applications/computers, update record etc</P>
<P style="TEXT-INDENT: 2em">As example, you may use xml-file instead ini-file and store there any number of items without limitations on size/value types etc. Just load it to TClientDataset and navigate thru stored options as thru dataset.</P>
<P style="TEXT-INDENT: 2em">PS: of course, you may also display such memory dataset in DBGrid or print it using any report engine. Also you may export it in any file format using <A href="http://www.scalabium.com/sme">SMExport suite</A></P></div>]]></description>
	    <author><![CDATA[ziseliuxingzh]]></author>
	    <comments>http://ziseliuxingzh.blog.163.com/blog/static/51120863200882385119280</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://ziseliuxingzh.blog.163.com/blog/static/51120863200882385119280</guid>
    <pubDate>Tue, 23 Sep 2008 08:51:19 +0800</pubDate>
    <dcterms:modified>2008-09-23T09:51:43+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[XML operation]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/51120863200881812033209</link>
    <description><![CDATA[<div><P><FONT face=宋体 size=2>////////////////////////////////////////////////////////////////////////<BR>创建IXMLDOMDocument对象的三种方法：<BR><FONT color=#ff0000>(1)[方法1] 直接创建 IXMLDOMDocument&nbsp; , 例(1)</FONT><BR>&nbsp;&nbsp; uses msxml; <BR>&nbsp;&nbsp; var DOC:IXMLDOMDocument;<BR>&nbsp;&nbsp; doc := CoDOMDocument.create;<BR>&nbsp;&nbsp; .....<BR>&nbsp;&nbsp; Doc := nil;<BR>&nbsp;<FONT color=#0033ff>A)doc.load('C:\temp.xml');&nbsp; //从文件载入<BR>&nbsp;B) 动态创建</FONT><BR>&nbsp;&nbsp; var aElement,aElement2: IXMLDOMElement;&nbsp; // [ aNode:IXMLDOMNode ==&gt;&nbsp; .AppendChild() ]</FONT></P>
<P><FONT face=宋体 size=2>&nbsp;&nbsp; //加入版本信息 ‘&lt;?xml version="1.0" ?&gt; ’<BR>&nbsp;&nbsp; doc.AppendChild(doc.CreateProcessingInstruction('xml', 'version="1.0" encoding="GB2312"')); <BR>&nbsp;&nbsp;&nbsp;&nbsp; (*)因为此函数返回结果不包含 'encoding="GB2312"' 故须保存前注意.<BR>&nbsp;&nbsp; //加入根结点<BR>&nbsp;&nbsp; doc.AppendChild(doc.CreateElement('bootDocNode')); //// == aElement&nbsp; <BR>&nbsp;&nbsp; //加入子结点<BR>&nbsp;&nbsp; aElement:=IXMLDOMElement(Doc.DocumentElement.AppendChild(Doc.CreateElement('ChileNode1')));<BR>&nbsp;&nbsp; //设置接点属性<BR>&nbsp;&nbsp; aElement.SetAttribute('ID', '11');<BR>&nbsp;&nbsp; aElement.SetAttribute('Units', '元/m2');<BR>&nbsp;&nbsp; //设置结点内容<BR>&nbsp;&nbsp; aElement.AppendChild(Doc.CreateTextNode('结点内容'));<BR>&nbsp;&nbsp; //子结点添加子结点<BR>&nbsp;&nbsp; aElement2:=IXMLDOMElement(aElement.AppendChild(Doc.CreateElement('Child_ChileNode1')));</FONT></P>
<P><FONT face=宋体 size=2><FONT color=#ff3300>(2) [方法2] 直接创建 IXMLDocument ( 不是IXMLDOMDocument )</FONT><BR>&nbsp; uses XMLIntf,XMLDoc;<BR>&nbsp; var xmlDoc:IXMLDocument; aNode:IXMLNode;&nbsp; s:string; </FONT></P>
<P><FONT face=宋体 size=2>&nbsp; xmlDoc := TXMLDocument.Create(nil);<BR>&nbsp; try<BR>&nbsp;&nbsp;&nbsp; //加入版本信息 ‘&lt;?xml version="1.0" encoding="GB2312" ?&gt; ’<BR>&nbsp;&nbsp;&nbsp; xmlDoc.Active := True;&nbsp;&nbsp; xmlDoc.Version := '1.0';&nbsp; xmlDoc.Encoding :='GB2312'; <BR>&nbsp;&nbsp;&nbsp; //加入根结点<BR>&nbsp;&nbsp;&nbsp; aNode:=xmlDoc.AddChild('bootDocNode');<BR>&nbsp;&nbsp;&nbsp; //加入子结点<BR>&nbsp;&nbsp;&nbsp; aNode:=aNode.AddChild('ChileNode1');<BR>&nbsp;&nbsp;&nbsp; //设置接点属性<BR>&nbsp;&nbsp;&nbsp; aNode.SetAttribute('ID', '22');<BR>&nbsp;&nbsp;&nbsp; aNode.SetAttribute('Units', '元/m2');<BR>&nbsp;&nbsp;&nbsp; //设置结点内容<BR>&nbsp;&nbsp;&nbsp; aNode.Text := '结点内容';<BR>&nbsp;&nbsp;&nbsp; //子结点添加子结点<BR>&nbsp;&nbsp;&nbsp; aNode:=aNode.AddChild('Child_ChileNode1') ;<BR>&nbsp;&nbsp;&nbsp; aNode.Text := 'Child_ChileNod内容';<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; s := xmlDoc.XML.Text ;&nbsp; //&nbsp; .XML 返回的是 Tstrings<BR>&nbsp; finally<BR>&nbsp;&nbsp;&nbsp; xmlDoc := nil ;<BR>&nbsp; end;</FONT></P>
<P><FONT face=宋体 size=2><FONT color=#ff0000>(3)利用 XMLDataBinding</FONT><BR>&nbsp;&nbsp;&nbsp; I) 准备好XML文件，此XML文件有较强的代表性，保证程序中所用的结点及其关系都存在<BR>&nbsp;&nbsp; II)利用 file--&gt;new--&gt;XML Data Binding<BR>&nbsp; III)创建XML对象<BR>&nbsp;&nbsp; A)v:string; //XML文件内容<BR>&nbsp;&nbsp;&nbsp; Doc : IXMLBudgetDocTyp; //IXMLBudgetDocTyp是XML文件的根结点<BR>&nbsp;&nbsp;&nbsp; Doc := LoadXMLData(v).GetDocBinding('BudgetDoc', TXMLBudgetDocType) as IXMLBudgetDocType;<BR>&nbsp;&nbsp; B)Doc := LoadBudgetDoc('C:\temp.xml');<BR>&nbsp; IV) 应用<BR>&nbsp;&nbsp;&nbsp; Doc.ChildNodes.FindNode('Docfile') as IXMLDocfileType;</FONT></P>
<P><FONT face=宋体 size=2><FONT color=#ff0000>(4)利用TXMLDocument控件</FONT><BR>&nbsp;&nbsp;&nbsp; XMLDocument1.fileName:='C:\temp.xml';<BR>&nbsp;&nbsp;&nbsp; XMLDocument1.active:=true;&nbsp; // XMLDocument1 相当于 Doc</FONT></P>
<P><FONT face=宋体 size=2><FONT color=#ff0000>(5)XML对象的其他方法</FONT><BR>&nbsp;&nbsp; IXMLNodeList.FindNode(NodeName: DOMString): IXMLNode;<BR>&nbsp;&nbsp; IXMLNodeList.FindNode(NodeName, NamespaceURI: DOMString): IXMLNode;<BR>&nbsp;&nbsp; IXMLNodeList.FindNode(ChildNodeType: TGuid): IXMLNode; <BR>&nbsp;&nbsp; IXMLNodeList.FindSibling(const Node: IXMLNode; Delta: Integer): IXMLNode;<BR>&nbsp;&nbsp; IXMLNodeList.First: IXMLNode;<BR>&nbsp;&nbsp; IXMLNodeList.Last: IXMLNode;<BR>&nbsp;&nbsp; ... ...<BR>&nbsp;&nbsp;&nbsp; <BR>////////////////////////////////////////////////////////////////////////<BR>//例(1)<BR>uses msxml;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; doc:IXMLDOMDocument;<BR>&nbsp;&nbsp;&nbsp; budgetdoc:ixmlDomNode;<BR>&nbsp;&nbsp;&nbsp; Rela:IxmlDOMNode;<BR>&nbsp;&nbsp;&nbsp; rs:ixmldomnodelist;</FONT></P>
<P><FONT face=宋体 size=2>//建立或取得XML结点<BR>&nbsp; doc := CoDOMDocument.create;<BR>&nbsp; doc.load('C:\temp.xml');<BR>&nbsp; budgetDoc := doc.selectSingleNode('BudgetDoc');<BR>&nbsp; rela := budgetdoc.SelectSingleNode('Relation'); </FONT></P>
<P><FONT face=宋体 size=2>//创建XML子结点&nbsp; <BR>&nbsp; if not assigned(rela) then<BR>&nbsp; begin<BR>&nbsp;&nbsp;&nbsp; rela :=&nbsp; doc.createElement('Relation');<BR>&nbsp;&nbsp;&nbsp; rela.setAttribute('BudgetId',0);<BR>&nbsp;&nbsp;&nbsp; rela.setAttribute('name','名称');<BR>&nbsp;&nbsp;&nbsp; budgetdoc.appendChild(rela); <BR>&nbsp; end;</FONT></P>
<P><FONT face=宋体 size=2>//取子结点(序列)<BR>&nbsp; rs := rela.selectNodes('Rela[@BudgetId="2" and @TaskId="8"]');<BR>&nbsp; for i := 0 to rs.length -1 do<BR>&nbsp; begin<BR>&nbsp;&nbsp;&nbsp; s:= s + rs[i].attributes.getnameditem('NewRate').nodeValue;<BR>&nbsp; end;<BR>&nbsp; <BR>&nbsp; rela:=doc.ChildNodes.FindNode('DOMNode') as IxmlDOMNode;</FONT></P>
<P><FONT face=宋体 size=2>//移除子结点<BR>&nbsp;&nbsp;&nbsp; for i := rs.length -1 downto 1 do<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rela.removeChild(rs[i])</FONT></P>
<P><FONT face=宋体 size=2>//取父结点<BR>&nbsp;&nbsp;&nbsp; if assigned(anode.parentNode) and (Anode.parentNode.nodeName='Task') then<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result := Anode.parentNode;</FONT></P>
<P><FONT face=宋体 size=2>//取属性<BR>&nbsp; DOC.DocumentElement.Attributes['Name']<BR>&nbsp; rela.Attributes['Name']<BR>&nbsp; rs.Nodes[i].Attributes['Name']</FONT></P>
<P><FONT face=宋体 size=2>&nbsp; Ajob:ixmldomnode；jobs:ixmldomNodeList;<BR>&nbsp; jobs := Ajob.selectNodes('RCJ[@Attrib="'+AAttrib+'"]')</FONT></P></div>]]></description>
	    <author><![CDATA[ziseliuxingzh]]></author>
	    <comments>http://ziseliuxingzh.blog.163.com/blog/static/51120863200881812033209</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://ziseliuxingzh.blog.163.com/blog/static/51120863200881812033209</guid>
    <pubDate>Thu, 18 Sep 2008 13:20:33 +0800</pubDate>
    <dcterms:modified>2008-09-18T13:20:33+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[VCLHardCore——VCL窗口函数注册机制研究手记]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/51120863200881095639304</link>
    <description><![CDATA[<div><P style="TEXT-INDENT: 2em">&nbsp;VCL&nbsp; HardCore&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——VCL窗口函数注册机制研究手记，兼与MFC比较</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; By&nbsp; cheka&nbsp; <A href="mailto:cheka@yeah.net">cheka@yeah.net</A>&nbsp;&nbsp;&nbsp;&nbsp; （转载请保留此信息） </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;这个名字起的有些耸人听闻，无他意，只为吸引眼球而已，如果您对下列关键词有兴趣，希望不要错过本文：</P>
<P style="TEXT-INDENT: 2em">1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VCL可视组件在内存中的分页式管理;</P>
<P style="TEXT-INDENT: 2em">2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 让系统回调类的成员方法</P>
<P style="TEXT-INDENT: 2em">3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Delphi 中汇编指令的使用</P>
<P style="TEXT-INDENT: 2em">4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hardcore </P>
<P style="TEXT-INDENT: 2em">5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第4条是骗你的</P>
<P style="TEXT-INDENT: 2em">&nbsp;</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;我们知道Windows平台上的GUI程序都必须遵循Windows的消息响应机制，可以简单概括如下，所有的窗口控件都向系统注册自身的窗口函数，运行期间消息可被指派至特定窗口控件的窗口函数处理。对消息相应机制做这样的概括有失严密，请各位见谅，我想赶紧转向本文重点，即在利用Object Pascali或是C++这样的面向对象语言编程中，如何把一个类的成员方法向系统注册以供回调。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;在注册窗口类即调用RegisterClass函数时，我们向系统传递的是一个WindowProc 类型的函数指针</P>
<P style="TEXT-INDENT: 2em">&nbsp;WindowProc 的定义如下</P>
<P style="TEXT-INDENT: 2em">LRESULT CALLBACK WindowProc(</P>
<P style="TEXT-INDENT: 2em">&nbsp; HWND hwnd,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // handle to window</P>
<P style="TEXT-INDENT: 2em">&nbsp; UINT uMsg,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // message identifier</P>
<P style="TEXT-INDENT: 2em">&nbsp; WPARAM wParam,&nbsp; // first message parameter</P>
<P style="TEXT-INDENT: 2em">&nbsp; LPARAM lParam&nbsp;&nbsp; // second message parameter</P>
<P style="TEXT-INDENT: 2em">)；</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;如果我们有一个控件类，它拥有看似具有相同定义的成员方法TMyControl.WindowProc,可是却不能够将它的首地址作为lpfnWndProc参数传给RegisterClass，道理很简单，因为Delphi中所有类成员方法都有一个隐含的参数，也就是Self，因此无法符合标准 WindowProc 的定义。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;那么，在VCL中，控件向系统注册时究竟传递了一个什么样的窗口指针，同时通过这个指针又是如何调到各个类的事件响应方法呢？我先卖个关子，先看看MFC是怎么做的。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;在调查MFC代码之前，我作过两种猜想：</P>
<P style="TEXT-INDENT: 2em">&nbsp;一，作注册用的函数指针指向的是一个类的静态方法，</P>
<P style="TEXT-INDENT: 2em">静态方法同样不需要隐含参数 this （对应 Delphi中的 Self ,不过Object Pascal不支持静态方法）</P>
<P style="TEXT-INDENT: 2em">&nbsp;二，作注册用的函数指针指向的是一个全局函数，这当然最传统，没什么好说的。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 经过简单的跟踪，我发现MFC中，全局函数AfxWndProc是整个MFC程序处理消息的“根节点”，也就是说，所有的消息都由它指派给不同控件的消息响应函数，也就是说，所有的窗口控件向系统注册的窗口函数很可能就是 AfxWndProc （抱歉没做深入研究，如果不对请指正）。而AfxWndProc 是如何调用各个窗口类的WndProc呢？</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 哈哈，MFC用了一种很朴素的机制，相比它那么多稀奇古怪的宏来说，这种机制相当好理解：使用一个全局的Map数据结构来维护所有的窗口对象和Handle(其中Handle为键值），然后AfxWndProc根据Handle来找出唯一对应的窗口对象（使用静态函数CWnd::FromHandlePermanent(HWND hWnd) ），然后调用其WndProc，注意WndProc可是虚拟方法，因此消息能够正确到达所指定窗口类的消息响应函数并被处理。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;于是我们有理由猜想VCL也可能采用相同的机制，毕竟这种方式实现起来很简单。我确实是这么猜的，不过结论是我错了......</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;开场秀结束，好戏正式上演。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在Form1上放一个Button(缺省名为Button1),在其OnClick事件中写些代码，加上断点，F9运行，当停留在断点上时，打开Call Stack窗口（View-&gt;Debug Window-&gt;Call Stack， 或者按Ctrl-Alt-S )可看到调用顺序如下（从底往上看，stack嘛）</P>
<P style="TEXT-INDENT: 2em">&nbsp;( 如果你看到的 Stack 和这个不一致，请打开DCU 调试开关 Project-&gt;Options-&gt;Compiler-&gt;Use Debug DCUs, 这个开关如果不打开，是没法调试VCL源码的 )</P>
<P style="TEXT-INDENT: 2em">&nbsp;TForm1.Button1Click(???)</P>
<P style="TEXT-INDENT: 2em">TControl.Click</P>
<P style="TEXT-INDENT: 2em">TButton.Click</P>
<P style="TEXT-INDENT: 2em">TButton.CNCommand ((48401, 3880, 0, 3880, 0))</P>
<P style="TEXT-INDENT: 2em">TControl.WndProc ((48401, 3880, 3880, 0, 3880, 0, 3880, 0, 0, 0))</P>
<P style="TEXT-INDENT: 2em">TWinControl.WndProc ((48401, 3880, 3880, 0, 3880, 0, 3880, 0, 0, 0))</P>
<P style="TEXT-INDENT: 2em">TButtonControl.WndProc ((48401, 3880, 3880, 0, 3880, 0, 3880, 0, 0, 0))</P>
<P style="TEXT-INDENT: 2em">TControl.Perform (48401,3880,3880)</P>
<P style="TEXT-INDENT: 2em">DoControlMsg (3880,(no value))</P>
<P style="TEXT-INDENT: 2em">TWinControl.WMComman d((273, 3880, 0, 3880, 0))</P>
<P style="TEXT-INDENT: 2em">TCustomForm.WMCommand ((273, 3880, 0, 3880, 0))</P>
<P style="TEXT-INDENT: 2em">TControl.WndProc ((273, 3880, 3880, 0, 3880, 0, 3880, 0, 0, 0))</P>
<P style="TEXT-INDENT: 2em">TWinControl.WndProc((273, 3880, 3880, 0, 3880, 0, 3880, 0, 0, 0))</P>
<P style="TEXT-INDENT: 2em">TCustomForm.WndProc ((273, 3880, 3880, 0, 3880, 0, 3880, 0, 0, 0))</P>
<P style="TEXT-INDENT: 2em">TWinControl.MainWndProc ((273, 3880, 3880, 0, 3880, 0, 3880, 0, 0, 0))</P>
<P style="TEXT-INDENT: 2em">StdWndProc (3792,273,3880,3880)</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;可见 StdWndProc 看上去象是扮演了MFC中 AfxWndProc 的角色，不过我们先不谈它，如果你抑制不住好奇心，可以提前去看它的源码，在Forms.pas中，看到了么? 是不是特~~~~别有趣阿。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;实际上，VCL在RegisterClass时传递的窗口函数指针并非指向StdWndProc。那是什么呢？</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;我跟，我跟，我跟跟跟，终于在Controls.pas的TWindowControl的实现代码中</P>
<P style="TEXT-INDENT: 2em">（procedure TWinControl.CreateWnd;) 看到了RegisterClass的调用,hoho，终于找到组织了......别忙，发现了没，这时候注册的窗口函数是InitWndProc，看看它的定义，嗯，符合标准，再去瞧瞧代码都干了些什么。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;发现这句：</P>
<P style="TEXT-INDENT: 2em">SetWindowLong(HWindow, GWL_WNDPROC,Longint(CreationControl.FObjectInstance));</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我Faint，搞了半天InitWndProc初次被调用（对每一个Wincontrol来说）就把自个儿给换了，新上岗的是FObjectInstance。下面还有一小段汇编，是紧接着调用FObjectInstance的，调用的理由不奇怪，因为以后调用FObjectInstace都由系统CallBack了，但现在还得劳InitWndProc的大驾去call。调用的方式有些讲究，不过留给您看完这篇文章后自个儿琢磨去吧。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;接下来只能继续看FObjectInstance是什么东东，它定义在 TWinControl 的 Private 段，是个Pointer也就是个普通指针，当什么使都行，你跟Windows说它就是 WndProc 型指针 Windows 拿你也没辙。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FObjectInstance究竟指向何处呢，镜头移向 TWincontrol 的构造函数，这是FObjectInstance初次被赋值的地方。 多余的代码不用看，焦点放在这句上</P>
<P style="TEXT-INDENT: 2em">&nbsp;FObjectInstance := MakeObjectInstance(MainWndProc); </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以先告诉您，MakeObjectInstance是本主题最精彩之处，但是您现在只需知道FObjectInstance“指向了”MainWndProc，也就是说通过某种途径VCL把每个MainWndProc作为窗口函数注册了，先证明容易的，即 MainWndProc 具备窗口函数的功能，来看代码：</P>
<P style="TEXT-INDENT: 2em">( 省去异常处理 )</P>
<P style="TEXT-INDENT: 2em">procedure TWinControl.MainWndProc(var Message: TMessage);</P>
<P style="TEXT-INDENT: 2em">begin</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WindowProc(Message);</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FreeDeviceContexts;</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FreeMemoryContexts;</P>
<P style="TEXT-INDENT: 2em">end; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FreeDeviceContexts; 和&nbsp; FreeMemoryContexts 是保证VCL线程安全的，不在本文讨论之列，只看WindowProc(Message); 原来 MainWndProc 把消息委托给了方法 WindowProc处理，注意到 MainWndProc 不是虚拟方法，而 WindowProc 则是虚拟的，了解 Design Pattern 的朋友应该点头了，嗯，是个 Template Method ， 很自然也很经典的用法，这样一来所有的消息都能准确到达目的地，也就是说从功能上看 MainWndProc 确实可以充作窗口函数。您现在可以回顾一下MFC的 AfxWindowProc 的做法，同样是利用对象的多态性，但是两种方式有所区别。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;是不是有点乱了呢，让我们总结一下，VCL 注册窗口函数分三步： </P>
<P style="TEXT-INDENT: 2em">1.&nbsp; [ TWinControl.Create ]</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; FObjectInstance 指向了 MainWndProc</P>
<P style="TEXT-INDENT: 2em">2.&nbsp; [ TWinControl.CreateWnd ] </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; WindowClass.lpfnWndProc 值为 @InitWndProc; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; 调用Windows.RegisterClass(WindowClass)向系统注册</P>
<P style="TEXT-INDENT: 2em">3.&nbsp; [ InitWndProc 初次被Callback时 ]</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; SetWindowLong(HWindow, GWL_WNDPROC, Longint(CreationControl.FObjectInstance)) </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; 窗口函数被偷梁换柱，从此 InitWndProc 退隐江湖</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; （注意是对每个TWinControl控件来说，InitWndProc 只被调用一次） </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;前面说过，非静态的类方法是不能注册成为窗口函数的，特别是Delphi中根本没有静态类方法，那么MainWndProc 也不能有特权（当然宝兰可以为此在编译器上动点手脚，如果他们不怕成为呕像的话）。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;那么，那么，您应该意识到了，在幕后操纵一切的，正是......&nbsp; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;背景打出字幕 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;超级巨星：麦克奥布吉特因斯坦斯 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （MakeObjectInstance） </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;天空出现闪电，哦耶，主角才刚刚亮相。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;废话不说，代码伺候： </P>
<P style="TEXT-INDENT: 2em">（ 原始码在 Form.pas 中，“{}”中是原始的注释，而“ <A href="file://”/">file://”</A> 后的是我所加，您可以直接就注释代码，也可以先看我下面的评论，再回头啃code ） </P>
<P style="TEXT-INDENT: 2em">// 共占 13 Bytes</P>
<P style="TEXT-INDENT: 2em">type</P>
<P style="TEXT-INDENT: 2em">&nbsp; PObjectInstance = ^TObjectInstance;</P>
<P style="TEXT-INDENT: 2em">&nbsp; TObjectInstance = packed record</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Code: Byte;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 1 Byte</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Offset: Integer;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 4 Byte</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; case Integer of&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0: (Next: PObjectInstance);&nbsp; // 4 Byte</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1: (Method: TWndMethod);&nbsp;&nbsp; // 8 Byte&nbsp; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TWndMethod 是一个指向对象方法的指针，</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 事实上是一个指针对，包含方法指针以</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 及一个对象的指针（即Self ）</P>
<P style="TEXT-INDENT: 2em">&nbsp; end;</P>
<P style="TEXT-INDENT: 2em">&nbsp;</P>
<P style="TEXT-INDENT: 2em">// 313是满足整个TInstanceBlock的大小不超过4096的最大值</P>
<P style="TEXT-INDENT: 2em">InstanceCount = 313; </P>
<P style="TEXT-INDENT: 2em">// 共占 4079 Bytes</P>
<P style="TEXT-INDENT: 2em">type</P>
<P style="TEXT-INDENT: 2em">&nbsp; PInstanceBlock = ^TInstanceBlock;</P>
<P style="TEXT-INDENT: 2em">&nbsp; TInstanceBlock = packed record</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Next: PInstanceBlock;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 4 Bytes</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Code: array[1..2] of Byte;&nbsp;&nbsp; // 2 Bytes</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; WndProcPtr: Pointer;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 4 Bytes</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Instances: array[0..InstanceCount] of TObjectInstance; 313 * 13 = 4069</P>
<P style="TEXT-INDENT: 2em">&nbsp; end; </P>
<P style="TEXT-INDENT: 2em">function CalcJmpOffset(Src, Dest: Pointer): Longint;</P>
<P style="TEXT-INDENT: 2em">begin</P>
<P style="TEXT-INDENT: 2em">&nbsp; Result := Longint(Dest) - (Longint(Src) + 5);</P>
<P style="TEXT-INDENT: 2em">end; </P>
<P style="TEXT-INDENT: 2em">function MakeObjectInstance(Method: TWndMethod): Pointer;</P>
<P style="TEXT-INDENT: 2em">const</P>
<P style="TEXT-INDENT: 2em">&nbsp; BlockCode: array[1..2] of Byte = (</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; $59,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { POP ECX }</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; $E9);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { JMP StdWndProc }&nbsp; // 实际上只有一个JMP</P>
<P style="TEXT-INDENT: 2em">&nbsp; PageSize = 4096;</P>
<P style="TEXT-INDENT: 2em">var</P>
<P style="TEXT-INDENT: 2em">&nbsp; Block: PInstanceBlock;</P>
<P style="TEXT-INDENT: 2em">&nbsp; Instance: PObjectInstance;</P>
<P style="TEXT-INDENT: 2em">begin</P>
<P style="TEXT-INDENT: 2em">&nbsp; // InstFreeList = nil 表明一个Instance block已被占满，于是需要为一个新</P>
<P style="TEXT-INDENT: 2em">&nbsp; // Instance block分配空间，一个个Instance block通过PinstanceBlock中的</P>
<P style="TEXT-INDENT: 2em">&nbsp; // Next 指针相连，形成一个链表，其头指针为InstBlockList&nbsp; </P>
<P style="TEXT-INDENT: 2em">&nbsp; if InstFreeList = nil then</P>
<P style="TEXT-INDENT: 2em">&nbsp; begin</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; // 为Instance block分配虚拟内存，并指定这块内存为可读写并可执行</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; // PageSize 为4096。</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Block := VirtualAlloc(nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Block^.Next := InstBlockList;</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Move(BlockCode, Block^.Code, SizeOf(BlockCode));</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Block^.WndProcPtr := Pointer(CalcJmpOffset(@Block^.Code[2], @StdWndProc));&nbsp;&nbsp;&nbsp; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; // 以下代码建立一个Instance的链表</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; Instance := @Block^.Instances;</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; repeat</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Instance^.Code := $E8;&nbsp; { CALL NEAR PTR Offset }</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A href="file://算/">file://算</A>出相对 jmp StdWndProc指令的偏移量，放在$E8的后面</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Instance^.Offset := CalcJmpOffset(Instance, @Block^.Code);</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Instance^.Next := InstFreeList;</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InstFreeList := Instance;</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 必须有这步，让Instance指针移至当前instance子块的底部</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Inc(Longint(Instance), SizeOf(TObjectInstance));</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 判断一个Instance block是否已被构造完毕</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; until Longint(Instance) - Longint(Block) &gt;= SizeOf(TInstanceBlock);</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; InstBlockList := Block;</P>
<P style="TEXT-INDENT: 2em">&nbsp; end;</P>
<P style="TEXT-INDENT: 2em">&nbsp; Result := InstFreeList; </P>
<P style="TEXT-INDENT: 2em">&nbsp; Instance := InstFreeList;</P>
<P style="TEXT-INDENT: 2em">&nbsp; InstFreeList := Instance^.Next;</P>
<P style="TEXT-INDENT: 2em">&nbsp; Instance^.Method := Method;</P>
<P style="TEXT-INDENT: 2em">end; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;不要小看这区区几十行代码的能量，就是它们对 VCL 的可视组件进行了分页式管理，（代码中对两个链表进行操作，InstanceBlock 中有 ObjectInstance 的链表，而一个个InstanceBlock&nbsp; 又构成一个链表 ）一个 InstanceBlock 为一页，有4096 字节，虽然 InstanceBlock 实际使用的只有 4079 字节，不过为了 Alignment ,就加了些 padding 凑满 4096 。从代码可见每一页中可容纳 313 个所谓的ObjectInstance，如果望文生义很容易将这个 ObjectInstance 误解为对象实例，其实不然，每个ObjectInstance 其实是一小段可执行代码，而这些可执行代码不是编译期间生成的，也不是象虚拟函数那样滞后联编，而根本就是MakeObjectInstance 在运行期间“创作”的（天哪）! 也就是说，MakeObjectInstance 将所有的可视VCL组件 改造成了一页页的可执行代码区域，是不是很了不起呢。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不明白ObjectInstance所对应的代码是做什么的么？没关系，一起来看 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp; - - - - - - - - - - - &gt;&nbsp; pop ECX&nbsp;&nbsp;// 在call 之前，下一个指令地址会被压栈</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @MainWndProc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 紧接着执行pop ECX, 为何这么做呢？</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Object(即Self)&nbsp; // 前面注释中提过 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 答案在 StdWndProc 的代码中，要命哦，全是汇编，可是无限风光在险峰，硬着头皮闯一回吧。 </P>
<P style="TEXT-INDENT: 2em">果不其然，我们发现其中用到了ECX</P>
<P style="TEXT-INDENT: 2em">function StdWndProc(Window: HWND; Message, WParam: Longint;</P>
<P style="TEXT-INDENT: 2em">&nbsp; LParam: Longint): Longint; stdcall; assembler;</P>
<P style="TEXT-INDENT: 2em">asm</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XOR&nbsp;&nbsp;&nbsp;&nbsp; EAX,EAX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PUSH&nbsp;&nbsp;&nbsp; EAX</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PUSH&nbsp;&nbsp;&nbsp; LParam</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PUSH&nbsp;&nbsp;&nbsp; WParam</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PUSH&nbsp;&nbsp;&nbsp; Message</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; EDX,ESP</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; EAX,[ECX].Longint[4]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; 相当于 MOV EAX, [ECX+4]&nbsp;&nbsp; ( [ECX+4] 是什么？就是Self )</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CALL&nbsp;&nbsp;&nbsp; [ECX].Pointer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; 相当于 CALL&nbsp;&nbsp;&nbsp; [ECX] , 也就是调用 MainWndProc</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ADD&nbsp;&nbsp;&nbsp;&nbsp; ESP,12</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POP&nbsp;&nbsp;&nbsp;&nbsp; EAX</P>
<P style="TEXT-INDENT: 2em">end; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;这段汇编中在调用MainWndProc前作了些参数传递的工作，由于MainWndProc 的定义如下</P>
<P style="TEXT-INDENT: 2em">procedure TwinControl..MainWndProc(var Message: TMessage); </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根据Delphi 的约定，这种情况下隐函数Self 作为第一个参数，放入EAX 中，TMessage 结构的指针作为第二个参数，放入EDX中，而Message的指针从哪儿来呢？我们看到在连续几个 Push 之后，程序已经在堆栈中构造了一个TMessage 结构，而这时的ESP 当然就是这个结构的指针，于是将它赋给EDX 。如果您不熟悉这方面的约定，可以参考Delphi 的帮助Object Pascal Refrence -&gt; Program Control。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;现在真相大白，Windows 消息百转千折终于传进MainWndProc , 不过这一路也可谓相当精彩，MakeObject这一函数自然是居功至伟， StdWndProc 也同样是幕后英雄，让我们把 MakeObjectInstance 作出的代码和StdWndProc 连接起来，哦，堪称鬼斧神工。</P>
<P style="TEXT-INDENT: 2em">( 图片无法显示，请下载全文）</P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;就此在总结一下， FobjectInstance 被VCL 注册为窗口函数，而实际上 FObjectInstance 并不实际指向某个函数，而是指向一个ObjectInstance, 而后者我们已经知道是一系列相接的可执行代码段当中的一块，当系统需要将 FObjectInstance 当做窗口函数作为回调时，实际进入了ObjectInstance 所在的代码段，然后几番跳跃腾挪（一个call 加一个 jump ）来到StdWndProc ，StdWndProc 的主要功用在于将Self 指针压栈，并把Windows的消息包装成Delphi的TMessage 结构，如此才能成功调用到TWinControl类的成员方法 MainWndProc, 消息一旦进入MainWndProc 便可以轻车熟路一路高唱小曲来到各个对象转属的WndProc , 从此功德圆满。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P style="TEXT-INDENT: 2em">后记：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;个人感觉在这一技术上VCL 要比MFC 效率高出不少，后者每次根据窗口句柄来检索相对应的窗口对象指针颇为费时，同时MakeObject&nbsp; 的代码也相当具有参考价值，有没有想过让你自己的程序在内存中再开一堆可执行代码？&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;所有的代码是基于Delphi5的，可能与其余版本有所出入，但相信不会很大。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;整个星期六和星期天我都花在写作此文上了（连调试带写字）， 不过水平所限，难免有所错误与表达不周，但愿不至以己昏昏令人昏昏，欢迎来信探讨指教&nbsp;&nbsp; <A href="mailto:cheka@yeah.net">cheka@yeah.net</A> , thanx </P>
<P style="TEXT-INDENT: 2em"></P></div>]]></description>
	    <author><![CDATA[ziseliuxingzh]]></author>
	    <comments>http://ziseliuxingzh.blog.163.com/blog/static/51120863200881095639304</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://ziseliuxingzh.blog.163.com/blog/static/51120863200881095639304</guid>
    <pubDate>Wed, 10 Sep 2008 09:56:39 +0800</pubDate>
    <dcterms:modified>2008-09-10T10:09:38+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[sprintf用法(转)]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/51120863200872101256309</link>
    <description><![CDATA[<div><P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">printf可能是许多程序员在开始学习C语言时接触到的第二个函数（我猜第一个是main），说起来，自然是老朋友了，可是，你对这个老朋友了解多吗？你对它的那个孪生兄弟sprintf了解多吗？在将各种类型的数据构造成字符串时，sprintf的强大功能很少会让你失望。 </P>
<P style="TEXT-INDENT: 2em">由于sprintf跟printf在用法上几乎一样，只是打印的目的地不同而已，前者打印到字符串中，后者则直接在命令行上输出。这也导致sprintf比printf有用得多。所以本文着重介绍sprintf，有时也穿插着用用pritnf。</P>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">sprintf是个变参函数，定义如下：</P>
<P style="TEXT-INDENT: 2em">int sprintf( char *buffer, const char *format [, argument] ... );</P>
<P style="TEXT-INDENT: 2em">除了前两个参数类型固定外，后面可以接任意多个参数。而它的精华，显然就在第二个参数：格式化字符串上。</P>
<P style="TEXT-INDENT: 2em">printf和sprintf都使用格式化字符串来指定串的格式，在格式串内部使用一些以“%”开头的格式说明符（format specifications）来占据一个位置，在后边的变参列表中提供相应的变量，最终函数就会用相应位置的变量来替代那个说明符，产生一个调用者想要的字符串。</P>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 格式化数字字符串</P>
<P style="TEXT-INDENT: 2em">sprintf最常见的应用之一莫过于把整数打印到字符串中，所以，spritnf在大多数场合可以替代itoa。如：</P>
<P style="TEXT-INDENT: 2em">//把整数123打印成一个字符串保存在s中。 </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%d", 123);&nbsp;&nbsp; //产生"123" </P>
<P style="TEXT-INDENT: 2em">可以指定宽度，不足的左边补空格：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%8d%8d", 123, 4567); //产生："&nbsp;&nbsp;&nbsp;&nbsp;123&nbsp;&nbsp;&nbsp; 4567" </P>
<P style="TEXT-INDENT: 2em">当然也可以左对齐：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%-8d%8d", 123, 4567); //产生："123&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4567" </P>
<P style="TEXT-INDENT: 2em">也可以按照16进制打印：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%8x", 4567); //小写16进制，宽度占8个位置，右对齐 </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%-8X", 4568); //大写16进制，宽度占8个位置，左对齐 </P>
<P style="TEXT-INDENT: 2em">这样，一个整数的16进制字符串就很容易得到，但我们在打印16进制内容时，通常想要一种左边补0的等宽格式，那该怎么做呢？很简单，在表示宽度的数字前面加个0就可以了。</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%08X", 4567); //产生："000011D7" </P>
<P style="TEXT-INDENT: 2em">上面以”%d”进行的10进制打印同样也可以使用这种左边补0的方式。</P>
<P style="TEXT-INDENT: 2em">这里要注意一个符号扩展的问题：比如，假如我们想打印短整数（short）-1的内存16进制表示形式，在Win32平台上，一个short型占2个字节，所以我们自然希望用4个16进制数字来打印它：</P>
<P style="TEXT-INDENT: 2em">short si = -1; </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%04X", si); </P>
<P style="TEXT-INDENT: 2em">产生“FFFFFFFF”，怎么回事？因为spritnf是个变参函数，除了前面两个参数之外，后面的参数都不是类型安全的，函数更没有办法仅仅通过一个“%X”就能得知当初函数调用前参数压栈时被压进来的到底是个4字节的整数还是个2字节的短整数，所以采取了统一4字节的处理方式，导致参数压栈时做了符号扩展，扩展成了32位的整数-1，打印时4个位置不够了，就把32位整数-1的8位16进制都打印出来了。如果你想看si的本来面目，那么就应该让编译器做0扩展而不是符号扩展（扩展时二进制左边补0而不是补符号位）：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%04X", (unsigned short)si); </P>
<P style="TEXT-INDENT: 2em">就可以了。或者：</P>
<P style="TEXT-INDENT: 2em">unsigned short si = -1; </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%04X", si); </P>
<P style="TEXT-INDENT: 2em">sprintf和printf还可以按8进制打印整数字符串，使用”%o”。注意8进制和16进制都不会打印出负数，都是无符号的，实际上也就是变量的内部编码的直接的16进制或8进制表示。</P>
<P style="TEXT-INDENT: 2em">2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 控制浮点数打印格式</P>
<P style="TEXT-INDENT: 2em">浮点数的打印和格式控制是sprintf的又一大常用功能，浮点数使用格式符”%f”控制，默认保留小数点后6位数字，比如：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%f", 3.1415926);&nbsp;&nbsp;&nbsp; //产生"3.141593" </P>
<P style="TEXT-INDENT: 2em">但有时我们希望自己控制打印的宽度和小数位数，这时就应该使用：”%m.nf”格式，其中m表示打印的宽度，n表示小数点后的位数。比如：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%10.3f", 3.1415626);&nbsp;&nbsp; //产生："&nbsp;&nbsp;&nbsp;&nbsp; 3.142" </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%-10.3f", 3.1415626);&nbsp;//产生："3.142&nbsp;&nbsp;&nbsp;&nbsp; " </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%.3f", 3.1415626); //不指定总宽度，产生："3.142" </P>
<P style="TEXT-INDENT: 2em">注意一个问题，你猜</P>
<P style="TEXT-INDENT: 2em">int i = 100; </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%.2f", i); </P>
<P style="TEXT-INDENT: 2em">会打出什么东东来？“100.00”？对吗？自己试试就知道了，同时也试试下面这个：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%.2f", (double)i); </P>
<P style="TEXT-INDENT: 2em">第一个打出来的肯定不是正确结果，原因跟前面提到的一样，参数压栈时调用者并不知道跟i相对应的格式控制符是个”%f”。而函数执行时函数本身则并不知道当年被压入栈里的是个整数，于是可怜的保存整数i的那4个字节就被不由分说地强行作为浮点数格式来解释了，整个乱套了。</P>
<P style="TEXT-INDENT: 2em">不过，如果有人有兴趣使用手工编码一个浮点数，那么倒可以使用这种方法来检验一下你手工编排的结果是否正确。J</P>
<P style="TEXT-INDENT: 2em">字符/Ascii码对照</P>
<P style="TEXT-INDENT: 2em">我们知道，在C/C++语言中，char也是一种普通的scalable类型，除了字长之外，它与short，int，long这些类型没有本质区别，只不过被大家习惯用来表示字符和字符串而已。（或许当年该把这个类型叫做“byte”，然后现在就可以根据实际情况，使用byte或short来把char通过typedef定义出来，这样更合适些）</P>
<P style="TEXT-INDENT: 2em">于是，使用”%d”或者”%x”打印一个字符，便能得出它的10进制或16进制的ASCII码；反过来，使用”%c”打印一个整数，便可以看到它所对应的ASCII字符。以下程序段把所有可见字符的ASCII码对照表打印到屏幕上（这里采用printf，注意”#”与”%X”合用时自动为16进制数增加”0X”前缀）：</P>
<P style="TEXT-INDENT: 2em">for(int i = 32; i &lt; 127; i++) { </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; printf("[ %c ]: %3d 0x%#04X\n", i, i, i); </P>
<P style="TEXT-INDENT: 2em">} </P>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 连接字符串</P>
<P style="TEXT-INDENT: 2em">sprintf的格式控制串中既然可以插入各种东西，并最终把它们“连成一串”，自然也就能够连接字符串，从而在许多场合可以替代strcat，但sprintf能够一次连接多个字符串（自然也可以同时在它们中间插入别的内容，总之非常灵活）。比如：</P>
<P style="TEXT-INDENT: 2em">char* who = "I"; </P>
<P style="TEXT-INDENT: 2em">char* whom = "CSDN"; </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%s love %s.", who, whom); //产生："I love CSDN. " </P>
<P style="TEXT-INDENT: 2em">strcat只能连接字符串（一段以’\0’结尾的字符数组或叫做字符缓冲，null-terminated-string），但有时我们有两段字符缓冲区，他们并不是以’\0’结尾。比如许多从第三方库函数中返回的字符数组，从硬件或者网络传输中读进来的字符流，它们未必每一段字符序列后面都有个相应的’\0’来结尾。如果直接连接，不管是sprintf还是strcat肯定会导致非法内存操作，而strncat也至少要求第一个参数是个null-terminated-string，那该怎么办呢？我们自然会想起前面介绍打印整数和浮点数时可以指定宽度，字符串也一样的。比如：</P>
<P style="TEXT-INDENT: 2em">char a1[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; </P>
<P style="TEXT-INDENT: 2em">char a2[] = {'H', 'I', 'J', 'K', 'L', 'M', 'N'}; </P>
<P style="TEXT-INDENT: 2em">如果：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%s%s", a1, a2); //Don't do that! </P>
<P style="TEXT-INDENT: 2em">十有八九要出问题了。是否可以改成：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%7s%7s", a1, a2); </P>
<P style="TEXT-INDENT: 2em">也没好到哪儿去，正确的应该是：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%.7s%.7s", a1, a2);//产生："ABCDEFGHIJKLMN" </P>
<P style="TEXT-INDENT: 2em">这可以类比打印浮点数的”%m.nf”，在”%m.ns”中，m表示占用宽度（字符串长度不足时补空格，超出了则按照实际宽度打印），n才表示从相应的字符串中最多取用的字符数。通常在打印字符串时m没什么大用，还是点号后面的n用的多。自然，也可以前后都只取部分字符：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%.6s%.5s", a1, a2);//产生："ABCDEFHIJKL" </P>
<P style="TEXT-INDENT: 2em">在许多时候，我们或许还希望这些格式控制符中用以指定长度信息的数字是动态的，而不是静态指定的，因为许多时候，程序要到运行时才会清楚到底需要取字符数组中的几个字符，这种动态的宽度/精度设置功能在sprintf的实现中也被考虑到了，sprintf采用”*”来占用一个本来需要一个指定宽度或精度的常数数字的位置，同样，而实际的宽度或精度就可以和其它被打印的变量一样被提供出来，于是，上面的例子可以变成：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%.*s%.*s", 7, a1, 7, a2); </P>
<P style="TEXT-INDENT: 2em">或者：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%.*s%.*s", sizeof(a1), a1, sizeof(a2), a2); </P>
<P style="TEXT-INDENT: 2em">实际上，前面介绍的打印字符、整数、浮点数等都可以动态指定那些常量值，比如：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%-*d", 4, 'A'); //产生"65&nbsp;" </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%#0*X", 8, 128);&nbsp;&nbsp;&nbsp; //产生"0X000080"，"#"产生0X </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%*.*f", 10, 2, 3.1415926); //产生"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.14" </P>
<P style="TEXT-INDENT: 2em">4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打印地址信息</P>
<P style="TEXT-INDENT: 2em">有时调试程序时，我们可能想查看某些变量或者成员的地址，由于地址或者指针也不过是个32位的数，你完全可以使用打印无符号整数的”%u”把他们打印出来：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%u", &amp;i); </P>
<P style="TEXT-INDENT: 2em">不过通常人们还是喜欢使用16进制而不是10进制来显示一个地址：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%08X", &amp;i); </P>
<P style="TEXT-INDENT: 2em">然而，这些都是间接的方法，对于地址打印，sprintf 提供了专门的”%p”：</P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%p", &amp;i); </P>
<P style="TEXT-INDENT: 2em">我觉得它实际上就相当于： </P>
<P style="TEXT-INDENT: 2em">sprintf(s, "%0*x", 2 * sizeof(void *), &amp;i); </P>
<P style="TEXT-INDENT: 2em">5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 利用sprintf的返回值</P>
<P style="TEXT-INDENT: 2em">较少有人注意printf/sprintf函数的返回值，但有时它却是有用的，spritnf返回了本次函数调用最终打印到字符缓冲区中的字符数目。也就是说每当一次sprinf调用结束以后，你无须再调用一次strlen便已经知道了结果字符串的长度。如：</P>
<P style="TEXT-INDENT: 2em">int len = sprintf(s, "%d", i); </P>
<P style="TEXT-INDENT: 2em">对于正整数来说，len便等于整数i的10进制位数。</P>
<P style="TEXT-INDENT: 2em">下面的是个完整的例子，产生10个[0, 100)之间的随机数，并将他们打印到一个字符数组s中，以逗号分隔开。</P>
<P style="TEXT-INDENT: 2em">#include &lt;stdio.h&gt; </P>
<P style="TEXT-INDENT: 2em">#include &lt;time.h&gt; </P>
<P style="TEXT-INDENT: 2em">#include &lt;stdlib.h&gt; </P>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">int main() { </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; srand(time(0)); </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; char s[64]; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; int offset = 0; </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; 10; i++) { </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offset += sprintf(s + offset, "%d,", rand() % 100); </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; } </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; s[offset - 1] = '\n';//将最后一个逗号换成换行符。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; printf(s); </P>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp; return 0; </P>
<P style="TEXT-INDENT: 2em">} </P>
<P style="TEXT-INDENT: 2em">设想当你从数据库中取出一条记录，然后希望把他们的各个字段按照某种规则连接成一个字符串时，就可以使用这种方法，从理论上讲，他应该比不断的strcat效率高，因为strcat每次调用都需要先找到最后的那个’\0’的位置，而在上面给出的例子中，我们每次都利用sprintf返回值把这个位置直接记下来了。</P>
<P style="TEXT-INDENT: 2em">6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用sprintf的常见问题</P>
<P style="TEXT-INDENT: 2em">sprintf是个变参函数，使用时经常出问题，而且只要出问题通常就是能导致程序崩溃的内存访问错误，但好在由sprintf误用导致的问题虽然严重，却很容易找出，无非就是那么几种情况，通常用眼睛再把出错的代码多看几眼就看出来了。</P>
<P style="TEXT-INDENT: 2em">&Oslash;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 缓冲区溢出</P>
<P style="TEXT-INDENT: 2em">第一个参数的长度太短了，没的说，给个大点的地方吧。当然也可能是后面的参数的问题，建议变参对应一定要细心，而打印字符串时，尽量使用”%.ns”的形式指定最大字符数。</P>
<P style="TEXT-INDENT: 2em">&Oslash;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 忘记了第一个参数</P>
<P style="TEXT-INDENT: 2em">低级得不能再低级问题，用printf用得太惯了。//偶就常犯。：。（</P>
<P style="TEXT-INDENT: 2em">&Oslash;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 变参对应出问题</P>
<P style="TEXT-INDENT: 2em">通常是忘记了提供对应某个格式符的变参，导致以后的参数统统错位，检查检查吧。尤其是对应”*”的那些参数，都提供了吗？不要把一个整数对应一个”%s”，编译器会觉得你欺她太甚了（编译器是obj和exe的妈妈，应该是个女的，:P）。</P>
<P style="TEXT-INDENT: 2em">7.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strftime</P>
<P style="TEXT-INDENT: 2em">sprintf还有个不错的表妹：strftime，专门用于格式化时间字符串的，用法跟她表哥很像，也是一大堆格式控制符，只是毕竟小姑娘家心细，她还要调用者指定缓冲区的最大长度，可能是为了在出现问题时可以推卸责任吧。这里举个例子：</P>
<P style="TEXT-INDENT: 2em">time_t t = time(0); </P>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">//产生"YYYY-MM-DD hh:mm:ss"格式的字符串。 </P>
<P style="TEXT-INDENT: 2em">char s[32]; </P>
<P style="TEXT-INDENT: 2em">strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime(&amp;t)); </P>
<P style="TEXT-INDENT: 2em">sprintf在MFC中也能找到他的知音：CString::Format，strftime在MFC中自然也有她的同道：CTime::Format，这一对由于从面向对象哪里得到了赞助，用以写出的代码更觉优雅。</P>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">8.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 后记</P>
<P style="TEXT-INDENT: 2em">本文介绍的所有这些功能，在MSDN中都可以很容易地查到，笔者只是根据自己的使用经验，结合一些例子，把一些常用的，有用的，而可能为许多初学者所不知的用法介绍了一点，希望大家不要笑话，也希望大家批评指正。</P>
<P style="TEXT-INDENT: 2em">有人认为这种带变参的函数会引起各种问题，因而不提倡使用。但笔者本人每每还是抵挡不了它们强大功能的诱惑，在实际工作中一直在使用。实际上，C#.NET从开始就支持变参，刚发布不久的Java5.0也支持变参了。</P>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">感谢ericzhangali（另一个空间）仔细审阅了全稿，纠正了很多小错误，并提出了一些建议。也感谢laomai（老迈）阅读了全稿并给出了增删一些内容的建议。&nbsp;</P>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">①获取System时间: void GetSystemTime(LPSYSTEMTIME lpSystemTime); 下面是例子: </P>
<P style="TEXT-INDENT: 2em">#include &lt;windows.h&gt; </P>
<P style="TEXT-INDENT: 2em">#include &lt;stdio.h&gt; </P>
<P style="TEXT-INDENT: 2em">#include &lt;stdlib.h&gt; </P>
<P style="TEXT-INDENT: 2em">void main() { </P>
<P style="TEXT-INDENT: 2em">SYSTEMTIME st; //定义存放时间的结构体 </P>
<P style="TEXT-INDENT: 2em">char strTime[256]; </P>
<P style="TEXT-INDENT: 2em">int n=0; </P>
<P style="TEXT-INDENT: 2em">GetSystemTime(&amp;st); </P>
<P style="TEXT-INDENT: 2em">n = sprintf(strTime,"Year:\t%d\n",st.wYear); </P>
<P style="TEXT-INDENT: 2em">n += sprintf(strTime+n,"Month:\t%d\n",st.wMonth); </P>
<P style="TEXT-INDENT: 2em">n += sprintf(strTime+n,"Day:\t%d\n",st.wDay); </P>
<P style="TEXT-INDENT: 2em">n += sprintf(strTime+n,"Date:\t%d\n",st.wDayOfWeek); </P>
<P style="TEXT-INDENT: 2em">n += sprintf(strTime+n,"Hour:\t%d\n",st.wHour); </P>
<P style="TEXT-INDENT: 2em">n += sprintf(strTime+n,"Minute:\t%d\n",st.wMinute); </P>
<P style="TEXT-INDENT: 2em">n += sprintf(strTime+n,"Second:\t%d\n",st.wSecond); </P>
<P style="TEXT-INDENT: 2em">n += sprintf(strTime+n,"MilliSecond:\t%d\n",st.wMilliseconds); </P>
<P style="TEXT-INDENT: 2em">printf("%s",strTime); </P>
<P style="TEXT-INDENT: 2em">system("pause"); </P>
<P style="TEXT-INDENT: 2em">} </P>
<P style="TEXT-INDENT: 2em">******************************************</P>
<P style="TEXT-INDENT: 2em">&nbsp;参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输出 </P>
<P style="TEXT-INDENT: 2em">参数个数一样多, 各参数之间用","分开, 且顺序一一对应,&nbsp;&nbsp;否则将会出现意想 </P>
<P style="TEXT-INDENT: 2em">不到的错误。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;1. 格式化规定符 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;Turbo C2.0提供的格式化规定符如下: </P>
<P style="TEXT-INDENT: 2em">━━━━━━━━━━━━━━━━━━━━━━━━━━ </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;符号&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;作用 </P>
<P style="TEXT-INDENT: 2em">────────────────────────── </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;十进制有符号整数 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;十进制无符号整数 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;浮点数 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;字符串 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;单个字符 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;指针的值 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%e&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;指数形式的浮点数 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%x, %X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;无符号以十六进制表示的整数 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;无符号以八进制表示的整数 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;%g&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;自动选择合适的表示法 </P>
<P style="TEXT-INDENT: 2em">━━━━━━━━━━━━━━━━━━━━━━━━━━ </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;说明: </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;(1). 可以在"%"和字母之间插进数字表示最大场宽。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;例如:&nbsp;&nbsp;%3d&nbsp;&nbsp;&nbsp;表示输出3位整型数, 不够3位右对齐。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%9.2f 表示输出场宽为9的浮点数, 其中小数位为2, 整数位为6, </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;小数点占一位, 不够9位右对齐。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%8s&nbsp;&nbsp;&nbsp;表示输出8个字符的字符串, 不够8个字符右对齐。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;如果字符串的长度、或整型数位数超过说明的场宽, 将按其实际长度输出。 </P>
<P style="TEXT-INDENT: 2em">但对浮点数, 若整数部分位数超过了说明的整数位宽度, 将按实际整数位输出; </P>
<P style="TEXT-INDENT: 2em">若小数部分位数超过了说明的小数位宽度, 则按说明的宽度以四舍五入输出。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;另外, 若想在输出值前加一些0, 就应在场宽项前加个0。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;例如:&nbsp;&nbsp;&nbsp;%04d&nbsp;&nbsp;表示在输出一个小于4位的数值时, 将在前面补0使其总宽度 </P>
<P style="TEXT-INDENT: 2em">为4位。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;如果用浮点数表示字符或整型量的输出格式, 小数点后的数字代表最大宽度, </P>
<P style="TEXT-INDENT: 2em">小数点前的数字代表最小宽度。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;例如: %6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9,&nbsp;&nbsp;则 </P>
<P style="TEXT-INDENT: 2em">第9个字符以后的内容将被删除。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;(2). 可以在"%"和字母之间加小写字母l, 表示输出的是长型数。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;例如:&nbsp;&nbsp;&nbsp;%ld&nbsp;&nbsp;&nbsp;表示输出long整数 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%lf&nbsp;&nbsp;&nbsp;表示输出double浮点数 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;(3). 可以控制输出左对齐或右对齐, 即在"%"和字母之间加入一个"-" 号可 </P>
<P style="TEXT-INDENT: 2em">说明输出为左对齐, 否则为右对齐。 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;例如:&nbsp;&nbsp;&nbsp;%-7d&nbsp;&nbsp;表示输出7位整数左对齐 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%-10s 表示输出10个字符左对齐 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;2. 一些特殊规定字符 </P>
<P style="TEXT-INDENT: 2em">━━━━━━━━━━━━━━━━━━━━━━━━━━ </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;字符&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;作用 </P>
<P style="TEXT-INDENT: 2em">────────────────────────── </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;换行 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;清屏并换页 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;回车 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tab符 </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\xhh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;表示一个ASCII码用16进表示, </P>
<P style="TEXT-INDENT: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其中hh是1到2个16进制数 </P>
<P style="TEXT-INDENT: 2em">━━━━━━━━━━━━━━━━━━━━━━━━━━ </P>
<P style="TEXT-INDENT: 2em"></P></div>]]></description>
	    <author><![CDATA[ziseliuxingzh]]></author>
	    <comments>http://ziseliuxingzh.blog.163.com/blog/static/51120863200872101256309</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://ziseliuxingzh.blog.163.com/blog/static/51120863200872101256309</guid>
    <pubDate>Thu, 21 Aug 2008 12:12:56 +0800</pubDate>
    <dcterms:modified>2008-08-21T12:12:56+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[USB有关的编程(转)]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/511208632008721115216256</link>
    <description><![CDATA[<div><P style="TEXT-INDENT: 2em"><A href="http://www.vckbase.net/code/downcode.asp?id=2523">源代码下载</A></P>
<P style="TEXT-INDENT: 2em">　　现在USB设备却很多，因此对USB设备的查找与读写就必不可少了。但是能找到关于USB读写的资料很少。这里使用VC++示范了一些获得USB的信息的方法。</P>
<P style="TEXT-INDENT: 2em">一、枚举USB设备</P>
<P style="TEXT-INDENT: 2em">　　通过枚举USB控制器-&gt;枚举此控制器上的USB HUB-&gt;枚举HUB的各个端口-&gt;获得设备信息。</P>
<P style="TEXT-INDENT: 2em">枚举控制器：</P>
<P style="TEXT-INDENT: 2em">wsprintf(HCName, "\\\\.\\HCD%d", HCNum); hHCDev = CreateFile(HCName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);</P>
<P style="TEXT-INDENT: 2em">　　计算机上的USB主控制器以HCD1，HCD2等命名。通过控制器名称，使用CCreateFile 打开它。使用DeviceIoControl即可得到其驱动程序名，以及与它连接的HUB的名称。用CCreateFile打开HUB，获得连接信息。再枚举HUB的各个端口即可获得连接的设备信息。</P>
<P style="TEXT-INDENT: 2em">二、枚举HID设备</P>
<P style="TEXT-INDENT: 2em">　　HID设备是微软定义的标准人机接口规范。比如USB鼠标，USB游戏手柄等。不用查找具体设备的GUID，使用API HidD_GetHidGuid(&amp;guidHID)即可得到GUID。有了GUID通过API SetupDiEnumDeviceInterfaces可获得是否有设备连接。如果此类设备连接通过SetupDiGetDeviceInterfaceDetail获得它的设备路径信息。使用CCreateFile 打开它，通过HidD_GetAttributes获得其基本属性信息。使用DeviceIoControl可以获得更详细的属性。在本代码中如果计算机上插有USB游戏手柄，可获得其信息。但不知道为什么xp下却不能获得USB鼠标的信息。</P>
<P style="TEXT-INDENT: 2em">三 枚举U盘</P>
<P style="TEXT-INDENT: 2em">　　先用GetDriveType API获得设备的类型，若类型为REMOVABLE（当然有些大容量U盘可能报告为FIXED，那就需要其他方法来确定了），即可能是U盘。用CCreateFile 打开之后，再用IOCTL_STORAGE_QUERY_PROPERTY为参数的DeviceIoControl来获得其属性。</P>
<P style="TEXT-INDENT: 2em">四、结束语</P>
<P style="TEXT-INDENT: 2em">　　示例工程在winxp+xpDDK+VC6下编译通过。USB设备种类比较多，也比较特殊，不同厂商的硬件不同，控制软件也不尽相同（我想主要是ICTL码不同，也不容易查到）。使得访问USB口的设备不象串口并口那么方便。这个例程只是展示了访问的基本方法。其中还有些问题还没有解决，发出来希望大家解决之后能通知我或者发表出来。</P>
<P style="TEXT-INDENT: 2em">参考了USBPort，USBview等代码，一并致谢。</P>
<P style="TEXT-INDENT: 2em">从NTDDK\INC拷贝下列头文件<BR>devioctl.h<BR>usbdi.h<BR>usbioctl.h<BR>usb100.h<BR>hidsdi.h<BR>hidusage.h<BR>hidpi.h<BR>从NTDDK\libchk\i386拷贝hid.lib<BR>在PROJECT&nbsp;SETTING中添加hid.lib&nbsp;setupapi.lib</P>
<P style="TEXT-INDENT: 2em">联系方式：<A href="mailto:daisun1998@163.net">daisun1998@163.net</A> </P>
<P style="TEXT-INDENT: 2em">原文链接：<A href="http://www.vckbase.net/document/viewdoc/?id=1282">http://www.vckbase.net/document/viewdoc/?id=1282</A></P></div>]]></description>
	    <author><![CDATA[ziseliuxingzh]]></author>
	    <comments>http://ziseliuxingzh.blog.163.com/blog/static/511208632008721115216256</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://ziseliuxingzh.blog.163.com/blog/static/511208632008721115216256</guid>
    <pubDate>Thu, 21 Aug 2008 11:52:16 +0800</pubDate>
    <dcterms:modified>2008-08-21T12:05:31+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[日本经典动画片大合集！]]></title>	
    <link>http://ziseliuxingzh.blog.163.com/blog/static/51120863200871655645678</link>
    <description><![CDATA[<div><P style="TEXT-INDENT: 2em">
<TABLE>
<TBODY>
<TR>
<TD>
<P></P>
<P style="TEXT-INDENT: 2em">1、盔甲类 </P>
<P style="TEXT-INDENT: 2em">所谓盔甲类，是指主人公作战的时候要穿上一身铠甲，其创始人自然是车田正美大人，所以本系列的代表作必然是其大作《圣斗士》，其中的一系列为神而战的斗士，如青铜五小强、红得发紫的十二黄金圣斗士、海斗士、冥斗士等充满了魅力，早已为人们津津乐道，并且经过十几年仍长盛不衰，而最人引人注目的还有其华丽的圣衣设定以及极为精彩的战斗场面，敌我双方人物的性格也得到了恰到好处的表现。推荐指数：★★★★★ </P>
<P style="TEXT-INDENT: 2em">《天空战记》是按照佛教中八部众的形象设计出的人物，反映的也是神之间的战争，因为是小学的时候看的，所以人物的名字记不太清楚了，只有迦楼罗王连迦的形象让我记忆深刻，某些战斗的精彩程度也不亚于圣斗士，不过由于作者并不十分了解佛教，所以出场的人物并不是同一时代的，有些“关公战秦琼”的感觉，总体还是略逊圣斗士一筹。推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">《魔神坛斗士》也是一部历史悠久的动画了，讲的是火焰神、光辉神、陀神、水神、天神与尤加军队作战的故事，相信20岁以上的人对这部动画不会陌生。推荐指数：★★★ </P>
<P style="TEXT-INDENT: 2em">《钢铁神兵》也是车田正美大人的著作，融入了科幻元素，设计出了人与机械BT合体作战的模式，不过故事情节比较老套，仍然难以逃脱《圣斗士》的影子，尤其是人物造型和圣斗士简直一般不二，所以印象一般。推荐指数：★★ </P>
<P style="TEXT-INDENT: 2em">2、探案类 </P>
<P style="TEXT-INDENT: 2em">《金田一少年事件簿》“以我爷爷金田一耕助的名义起誓，凶手就是……！”金田一一（这个名字真奇怪，不过他的妹妹的名字更奇怪，叫金田一二三，他们的父母倒是省事了。）是日本名侦探金田一耕助的孙子，同时也是有名的侦探，层出不穷的巧妙杀人手段在他面前被一一破解。金田一系列漫画有着令人叹服的构思，称得上是本格派推理漫画的代表作，不少还被搬上了银幕，其动画虽然只有20多集，却部部都是经典，推理缜密，构思惊奇，非常值得一看，是探案类动漫的绝对代表作。推荐指数：★★★★★ </P>
<P style="TEXT-INDENT: 2em">《名侦探柯南》虽然也是一部相当热门的动画，其中也有不少案件构思精巧，但商业气息太过浓重，里面的破绽越来越多，所拍的剧集也太长了一些（既不如金田一善于推理，又不如金田一会见好就收），让人难免有审美疲劳，看不下去的感觉。本系列的剧场版倒是精品，建议大家去看一看。推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">《傀儡师左近》，又叫《人形草纸》，也是推理探案动画，其故事情节设计相当不错，人物造型也很唯美（毕竟是棋魂的作者画的，其功底没得说），但不论怎么看，似乎都比金田一略逊一筹，原因我至今还没找到，如果大家知道请告诉我。推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">《推理之绊》、《魔侦探洛基》，把这两部放在一起说，是因为它们严格意义上来说，不能算是探案动画，更像是以脸蛋争得支持的动画剧集，本人仅仅是作为消遣的时候看了一遍。推荐指数：★★★ </P>
<P style="TEXT-INDENT: 2em">3、闯关型 </P>
<P style="TEXT-INDENT: 2em">《幽游白书》 本动画是富坚义博真正意义上的处女作，相信大家也不会有异议。主角浦饭幽助作为灵界侦探，与同伴们一起铲除在人间为非作歹的妖怪。四个主角的形象十分饱满，而且飞影和藏马的人气早已超越幽助，作为反面角色的户愚吕弟和仙水等也深入人心，绝对算是初看动漫的人的必修课程，不过结尾部分让人有种虎头蛇尾的感觉，本人并不太喜欢。之所以称呼它为“闯关类动漫”，是因为从头到尾，本片似乎都在打擂，战胜一个又一个对手，淘汰一组又一组敌人，最终取得胜利，很像是玩闯关游戏。推荐指数：★★★★★。 </P>
<P style="TEXT-INDENT: 2em">《烈火之炎》，相信很多人并不熟悉此部动画，但是看过的人一定会说，“简直就是《幽游白书》的翻版嘛！”不错，从故事结构，情节设计，主人公性格上来说，都与《幽游白书》相差不多，过程也是在打擂闯关中度过的，如果有闲情逸致的同胞们，可以看一看。推荐指数：★★★ </P>
<P style="TEXT-INDENT: 2em">《通灵王》也算是一部闯关型代表作，其作者是武井宏之，麻苍叶是一名能够和死人沟通，利用灵魂力量战斗的通灵人。他和伙伴们一起收到邀请，参加一个世代才举办一次的通灵人大赛。故事由此而展开，动画一共60多集，而漫画则更长，建议看动画，因为漫画画到后期，连作者都已经不知道自己在写什么了。推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">《魔神英雄传》算是伴我成长的动画片之一，其幼稚程度可见一斑，不过到现在还是觉得很有意思，里面的人物也能一一道来，不论是西米可、施巴拉古大师还是虎王，都给我留下了很深的印象，战斗也是闯关升级型，算是消磨时光的片子。推荐指数：★★★ </P>
<P style="TEXT-INDENT: 2em">4、搞笑类 </P>
<P style="TEXT-INDENT: 2em">《福星小子》当然不让，我把它列在第一，相信大多数人都不会反对，这是我看的第二部漫画，当时我才初一，当我捧过书的刹那，就已经欲罢不能了。相信对日本动漫稍微有一点了解的人都会知道里面的角色。比星矢生命力更加顽强的不死花心男诸星当、可爱的外星电击少女拉姆、平时故作君子一到黑暗地带就会害怕的不成人样的面堂，老是拿难看的脸部特写吓人的错乱和尚都已经成为了经典中的经典。推荐指数：★★★★★ </P>
<P style="TEXT-INDENT: 2em">《GS美神 极乐大作战》也算是不错的搞笑类动画，从事驱魔行业的人叫做驱魔清道夫，简称GS。讲述驱魔公司老板美神令子的神奇故事。美神令子是一个凭着顶级功力纵横驱魔界并爱钱如命的女孩子。不管是谁，都无法阻碍她降妖除魔和狂赚金钱。她有两个助手，一个是心地善良的小娟，另一个则是拿着255日元的时薪且愚蠢好色的烦恼少年横岛忠夫（这人的好色程度简直可以和诸星当相媲美），情节相当搞笑。推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">《蜡笔小新》这部动画无须更多介绍，相信大家都太熟悉那个可恶小孩可恶的声音了。能够在日本连载数年而不衰，足见其魅力了。上至七八十岁的老人，下至7、8岁的小孩，都是它的观众。同时它也开辟了动画片的一个新领域，可谓独树一帜。推荐指数：★★★★★ </P>
<P style="TEXT-INDENT: 2em">《全金属狂潮》是近几年来搞笑动画的代表作，在我还没有看之前，至少有一打男生向我推荐过这部动画，于是我抱着试一试的心情看了一遍，果然算是比较经典的动画，尤其第一部更加精彩一些。推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">《忍者乱太郎》是我初中时候看过的动画，情节记不太清楚了，但当时确实给我带来了相当不错的享受，至少让我学到了一句话：“全部给我吃下去，一点都不许剩下。”这使我从小到大，几乎没有浪费过粮食。推荐指数：★★★ </P>
<P style="TEXT-INDENT: 2em">《贫穷贵公子》是森永爱的代表作，非常经典的情节设定、人物设定、狂暴笑设定，是每一个漫画迷都不应错过的精品中的精品。画风不算唯美却很有亲切感，由一个个的小故事构成而不是长篇大论，给人一种回归自己的感觉。其最经典之处就在于，让你在最失意的时候想到：原来还有比我更惨的人啊！推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">《阿拉蕾》是鸟山明另外一部代表作，与《七龙珠》整天战斗的情节不同，《阿拉蕾》充满了轻松与幽默，是休闲时候一边吃薯片一边欣赏的精品。推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">5、冒险类 </P>
<P style="TEXT-INDENT: 2em">《海贼王》 是我看过的冒险类动画首推一指的经典著作，作者尾田荣一郎可以算是日本动漫界的鬼才之一，在他的笔下，为我们展现了一幅宏大的冒险画卷。相信很多人都能够对里面的情节与人物发表一段自己的看法，我也就不班门弄斧了。在动画中，击败沙鳄鱼以前的章节都非常经典，建议大家不妨一看。推荐指数：★★★★★ </P>
<P style="TEXT-INDENT: 2em">《闪灵二人组》也是我前年看的众多动画之一，但它却给我留下了相对比较深的印象。首先是人物造型非常不错，其中的情节也有独到之处，不过结尾草率，情节也没交待清楚，我被迫只得找来漫画看，这一看不要紧，才知道动画简直是糟粕，劝大家还是看漫画的好，不过现在漫画仍未完结，要有耐心才行。推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">《死神》的故事描写15岁的少年黑崎一护因为尸魂界的死神朽木露琪亚的帮助而开发出了强大的灵力，成为拥有斩魄刀“斩月”的死神，随着故事发展黑崎一护为了营救将被处死的朽木露琪亚，而与其它几位伙伴一起勇闯尸魂界，并与超强的“护庭十三队”死神队长展开激烈战斗，然后我就没看了，动画也就出了这么多。美中不足的是朽木露琪亚实在是不怎么漂亮，而黑崎则像是众多动漫角色给拼出来的，情节越往下发展越让人感到混乱，使其在我的心里的好感打了不小的折扣。 推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">6、体育类 </P>
<P style="TEXT-INDENT: 2em">《灌篮高手》这是一部掀起篮球热潮的动画，这是一部令“I love this game”在校园广为流传的动画，这是一部一放学就让我疯狂往家跑生怕拉下一分钟的动画，这是一部体育励志类动画的颠峰，十多年来，还没有一部同类动画超过或达到它的高度。虽然动画中的回忆多了点，但它在煽情方面真是达到了炉火纯青的地步。当樱木花道输球后流下眼泪，大声喊“还有时间”的时候，任何人的眼眶都是湿湿的；当湘北战胜翔阳，5个队员在更衣室睡着的时候，激昂的音乐响起，伴随着每个人最精彩表现的瞬间，每个人都热血澎湃。这也是一部塑造了无数偶像的动画，除了两位男主角，仙道、藤真、三井都曾风靡我们中间。推荐指数：★★★★★ </P>
<P style="TEXT-INDENT: 2em">《棋魂》在黑与白中交错，胜负只在一念之间，这就是围棋的世界。对围棋毫无认识的小学生进藤光在自家的阁楼上翻到一个老旧的棋盘，而棋盘上附着一个天才棋手的灵魂，故事从此就开始了……从未想过深奥的围棋能如此通俗的用漫画讲述出来，即使是完全不懂围棋的人也能从中得到乐趣，看完之后我第一个反映就是找了本围棋入门书来看，相信和我有相同反应的人不在少数。不过佐为消失以后的十几集中，一切都变得那么乏味，让我一点都看不下去了。推荐指数：★★★★★ </P>
<P style="TEXT-INDENT: 2em">《网球王子》是最近刚刚完结的一部动画，不过好像漫画仍然在连载，就人物造型来说，本动画算是相当成功，塑造了如手冢国光、不二周助这样红得发紫的形象，龙马的那句口头禅也为人津津乐道，每个人的绝技也有独到之处，不足之处就是动画虎头蛇尾，结局也有不少人很不满意。推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">《足球小将》，一说出这个名字，简直是如雷贯耳，主角大空翼在球场上的故事令人心动，但最激动人心的还是那些热爱足球的少年们为了梦想而拚搏的过程，一句“足球，是朋友啊！”道出了整篇漫画的精髓。虽然现在看起来那些不太符合物理规则的“倒钩射门”“猛虎射门”显得有些可笑，但它当时几乎整整影响了一代人，据说现在还在出漫画，不过长大了的大空翼却一点都不可爱了，身材也越来越像相扑运动员……推荐指数：★★★★ </P>
<P style="TEXT-INDENT: 2em">7、机械类 </P>
<P style="TEXT-INDENT: 2em">《变形金刚》，本来我想把《高达》系列列在首位，但是仔细想起来，《变形金刚》才是真正算是机器人动漫之中的霸主，试想一下，有多少人没有看过《高达》，但又有几个人没有看过《变形金刚》呢？童年时候，就算是女孩子的我，也拥有一个变形金刚玩具（是一只叫“钢索”的恐龙），更不要说那些为之痴迷的男生了。它对全世界动画的影响应该是无可估量的，毫无疑问是动画史上的经典之一，是一部里程碑式的作品。这部最初由美国制作，后来由日本来制作的长篇动画，伴随了几代人的成长。即使现在，也没有小孩子会不知道变形金刚这个词。可以说，它已经让这个词进入了词典。一句“汽车人，变形！”便足以让人热血沸腾。推荐指数：★★★★★ 