﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-在浩淼的天空下,留下生活的足迹-随笔分类-技术点滴</title><link>http://www.cnitblog.com/flyinggoal/category/4261.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 26 Sep 2011 14:44:23 GMT</lastBuildDate><pubDate>Mon, 26 Sep 2011 14:44:23 GMT</pubDate><ttl>60</ttl><item><title>黑莓通讯录·地址簿导入导出、批量添加、删除、修改操作方法(转载)</title><link>http://www.cnitblog.com/flyinggoal/archive/2011/07/13/74675.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Wed, 13 Jul 2011 13:26:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2011/07/13/74675.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/74675.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2011/07/13/74675.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/74675.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/74675.html</trackback:ping><description><![CDATA[<div><span style="font-size: 18px; word-wrap: break-word; line-height: normal;"><strong><div>http://apps.hi.baidu.com/share/detail/33234560</div><br />准备工作：</strong></span>&nbsp;<br />&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;1、正确安装了桌面管理器<br />&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;2、安装了OFFIC办公软件<br />&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;3、当然还得需要你的爱机、一条数据线，以及简单编辑EXCEL的能力。<br /><br /><span style="font-size: 24px; color: red; word-wrap: break-word; line-height: normal;">一、将手机通讯录导出</span>&nbsp;<br /><br />DM连接手机，选择&#8220;同步&#8221;<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/cd2bf11b8a7025adae5133e6.jpg" style="word-wrap: break-word; line-height: normal; cursor: pointer;" height="312" width="600"  alt="" /><br />选&#8220;配置&#8221;<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/f7d2c2fab6372b89b58f31e6.jpg" style="word-wrap: break-word; line-height: normal;" height="430" width="469"  alt="" />&nbsp;<br />选&#8220;配置同步&#8221;<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/de4bb354898828483b2935e6.jpg" style="word-wrap: break-word; line-height: normal;" height="433" width="467"  alt="" />&nbsp;<br />勾选&#8220;地址簿&#8221;<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/fe2acf1f254ff5a2e1fe0be6.jpg" style="word-wrap: break-word; line-height: normal; cursor: pointer;" height="439" width="600"  alt="" /><br />选择&#8220;ASCII导入程序/导出程序&#8221;，然后&#8220;下一步&#8221;<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/18ca33f31dafa39c0b46e0e6.jpg" style="word-wrap: break-word; line-height: normal; cursor: pointer;" height="401" width="600"  alt="" /><br />选择&#8220;单项同步 自&nbsp;&nbsp;手持设备&#8221;，然后&#8220;下一步&#8221;<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/50ed12f5c1984172bd3109e6.jpg" style="word-wrap: break-word; line-height: normal; cursor: pointer;" height="402" width="600"  alt="" /><br />&nbsp; &nbsp;&nbsp; &nbsp; 这里一定要注意第二和第三个选项的区别，一个是&#8220;自手持设备&#8221;，另一个是&#8220;至手持设备&#8221;，而且黄色箭头方向非常明显，这里我们是要把手机里的数据导出来，所以选第二个选项；编辑完成后，我们还需要来到这一步骤，选择第三个选项将编辑好的地址簿导回去。<br />接下来来到如下界面：<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/8a3aa6259f57843735a80fe6.jpg" style="word-wrap: break-word; line-height: normal; cursor: pointer;" height="405" width="600"  alt="" /><br />&nbsp; &nbsp;&nbsp; &nbsp;如图，选项里的东西可以不动，用默认；下面的&#8220;ASCII导入程序/导出程序连接器的数据库文件&#8221;需要指定一个路径及文件。这时我们<span style="font-size: 24px; color: red; word-wrap: break-word; line-height: normal;">需要新建一个EXCEL文件并为这个文件取一个名字，再将扩展名改为 .CSV</span>，确定后，在上图所示的界面中点击浏览，找到刚才所新建的CSV文件，比如我是在D盘根目录下建立了一个111.CSV的文件，那么选择后效果如下图：<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/d6f5636011ce86888cb10de6.jpg" style="word-wrap: break-word; line-height: normal; cursor: pointer;" height="406" width="600"  alt="" /><br />点击&#8220;下一步&#8221;，再点&#8220;完成&#8221;，到此已经完成了地址簿导出的设置，完成后返回到如下界面并点击OK：<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/5e6c61dfaad71344485403e6.jpg" style="word-wrap: break-word; line-height: normal; cursor: pointer;" height="426" width="600"  alt="" /><br />&nbsp; &nbsp;&nbsp; &nbsp; 点击后返回到&#8220;配置&#8221;对话框，将&#8220;同步管理器数据&#8221;勾选，点击&#8220;立即同步&#8221;，就会把手机里的通讯路导出到建立的那个CSV的文件里了<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/6082cd1f706cb334f724e4e6.jpg" style="word-wrap: break-word; line-height: normal;" height="471" width="512"  alt="" />&nbsp;<br />&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;导出过程中会遇到一些弹窗或报错，不理会，直到同步完成。<br /><br /><br /><span style="font-size: 24px; color: red; word-wrap: break-word; line-height: normal;">二、编辑地址簿</span>&nbsp;<br /><br />&nbsp; &nbsp;&nbsp; &nbsp; 我们现在得到的是一个CSV的通讯录文件，目前大多数网页邮箱导出通讯录和OUTLOOK导出的通讯录都是CSV格式的，所以非常有利于编辑。<br />将CSV文件打开，就可以进行编辑了：<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/e775f4136032d174dc5401e6.jpg" style="word-wrap: break-word; line-height: normal; cursor: pointer;" height="260" width="600"  alt="" /><br />打 开后电话号码一列可能显示成科学计数法，不要慌，把那一列拉宽就显示正常了;或者将号码这一列修改单元格格式，改为数值（注意不要显示小数点后位数）。部 分号码为+86开头的需要自行修改座机或小灵通，前面区号的&#8220;0&#8221;是显示不出来的，可以采用文本方式重新输入，即前面加英文输入法状态下的单引号(&#8217;)， 例：输入&#8217;01012345678，这样在单元格内就可以可以正确显示区号了，而且后续将这个数据导回手机，号码也是显示正确的。名称填写，表中分了三 列，即First Name，Middle Name和Last  Name，建议只用一列，不要将姓和名字分开写，虽然可以在手机里相应设置可以正确显示，但在拨打和接听电话的时候，名称显示可能出现不可预期的错误。另 外，你还可以在Company  Name里写入相应的人的公司或者备注，这样便于区分用户。其他项目根据个人喜好及需要自行填写。建议将通讯录另作备份保存。<br /><br /><br /><br /><span style="font-size: 24px; color: red; word-wrap: break-word; line-height: normal;">三、地址簿导回手机</span>&nbsp;<br /><br />&nbsp; &nbsp;&nbsp; &nbsp; 重复之前的步骤至&#8220;同步选项&#8221;里，选择&#8220;至 手持设备&#8221;，这里要勾选&#8220;替换目标应用程序理的所有数据&#8221;，不然导回后你将每个人都有两条通讯录。<br />当然，你也可以选择导回之前先吧手机里的地址簿清空，方法就是使用DM的备份与恢复功能，进入&#8220;高级&#8221;，将右边一栏理的&#8220;Address book-all&#8221;清除即可。<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/23903623f6328e19935807e6.jpg" style="word-wrap: break-word; line-height: normal; cursor: pointer;" height="405" width="600"  alt="" /><br />继续 继续 继续，最后执行同步，地址簿就导回到手机里面了，看下效果吧。<br /><br />加了公司名字或备注的将会在名字下方显示<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/b790694ebf3e095eb2de05e6.jpg" style="word-wrap: break-word; line-height: normal;" height="259" width="340"  alt="" /><br />如果有两个或更多号码的，也将保存到同一人的条目下，当拨打电话的时候会提示选择呼叫哪个号码。<br /><img src="http://hiphotos.baidu.com/glaivelee/pic/item/f89cee099cb844d5d0581be6.jpg" style="word-wrap: break-word; line-height: normal;" height="258" width="341"  alt="" /><br /><br />至此，完整得操作完成，以后你可以随时导入导出修改添加删除地址簿里的条目了。<br /><br /><p><span style="font-size: 24px; color: blue; word-wrap: break-word; line-height: normal;">提醒：一次操作完成后，记得把设置同步里的条目取消，以免哪次不小心执行同步了而造成地址簿的误操作</span> <br /></p></div><img src ="http://www.cnitblog.com/flyinggoal/aggbug/74675.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2011-07-13 21:26 <a href="http://www.cnitblog.com/flyinggoal/archive/2011/07/13/74675.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习英语发音的视频链接，有兴趣的兄弟可以参考</title><link>http://www.cnitblog.com/flyinggoal/archive/2008/05/11/43602.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Sun, 11 May 2008 09:26:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2008/05/11/43602.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/43602.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2008/05/11/43602.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/43602.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/43602.html</trackback:ping><description><![CDATA[&lt;embed src="<a href="http://player.youku.com/player.php/sid/XMTUyMTIwOA==/v.swf">http://player.youku.com/player.php/sid/XMTUyMTIwOA==/v.swf</a>" quality="high" width="480" height="400" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;<br><br><br>里面主要讲述元音音标和辅音音标的发音方式，感觉挺有帮助的。<br><br>以前英语没学好，没有听老师的话，发音太滥了<img height=20 src="http://www.cnitblog.com/Emoticons/QQ/02.gif" width=20 border=0><br><br><br>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/43602.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2008-05-11 17:26 <a href="http://www.cnitblog.com/flyinggoal/archive/2008/05/11/43602.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个有关字节序的实验</title><link>http://www.cnitblog.com/flyinggoal/archive/2007/10/15/34855.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Sun, 14 Oct 2007 16:23:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2007/10/15/34855.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/34855.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2007/10/15/34855.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/34855.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/34855.html</trackback:ping><description><![CDATA[<p>引言：&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Big endian machine: It thinks the <strong>first</strong> byte it reads is the biggest.<br>&nbsp;&nbsp;&nbsp; Little endian machine: Thinks the <strong>first</strong> byte it reads is the littlest.<br><br><br>字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序，通常有小端、大端两种字节顺序。小端字节序指低字节数据存放在内存低地址处，高字节数据存放在内存高地址处；大端字节序是高字节数据存放在低地址处，低字节数据存放在高地址处。基于X86平台的PC机是小端字节序的，而有的嵌入式平台则是大端字节序的。因而对int、uint16、uint32等多于1字节类型的数据，在这些嵌入式平台上应该变换其存储顺序。通常我们认为，在空中传输的字节的顺序即网络字节序为标准顺序，考虑到与协议的一致以及与同类其它平台产品的互通，在程序中发数据包时，将主机字节序转换为网络字节序，收数据包处将网络字节序转换为主机字节序。 <br><br>在本LINUX的书里介绍到INTEL的CPU使用的小端字节序&nbsp;其他比MOTOROLA&nbsp; <br>68000系列CPU使用的是大端字节序&nbsp;如果不转换&nbsp;将数据通过网络发出时&nbsp;比如MOTOROLA发一个16位数据：0X1234&nbsp;传送到INTEL时&nbsp; <br>就被INTEL解释为0X3412&nbsp;也就是4660成了13330&nbsp;所以有时候需要一些函数来进行大小端字节序的转换<br>&nbsp;<br>前段时间，一直不是很明白字节序影响数据的粒度以及这个概念，今天刚好有时间，索性测试一下：<br><br>采用VC在windows XP，Intel cpu上进行测试小端对齐(Little endian )<br>&nbsp;<br>{<br>&nbsp;/*测试字节序以及有关字节序能够影响的最小颗粒（字节还是四个bit）*/<br>&nbsp;int iNum = 0;<br>&nbsp;typedef struct sInt{<br>&nbsp;&nbsp;char cSingle1;<br>&nbsp;&nbsp;char cSingle2;<br>&nbsp;&nbsp;char cSingle3;<br>&nbsp;&nbsp;char cSingle4;<br>&nbsp;}sInt;</p>
<p>&nbsp;sInt sIntSon = {0};<br>&nbsp;sIntSon.cSingle1 = 0x01;<br>&nbsp;sIntSon.cSingle2 = 0x02;<br>&nbsp;sIntSon.cSingle3 = 0x03;<br>&nbsp;sIntSon.cSingle4 = 0x04;</p>
<p>&nbsp;memcpy(&amp;iNum,&amp;sIntSon,sizeof(sIntSon));<br>&nbsp;<br>&nbsp;printf("\n output int 's four char number\n");<br>&nbsp;printf("\n first = 0x%x, second = 0x%x , third = 0x%x , forth = 0x%x , iNum = 0x%x\n",<br>&nbsp;&nbsp;sIntSon.cSingle1,sIntSon.cSingle2,sIntSon.cSingle3,sIntSon.cSingle4,iNum);&nbsp;<br>&nbsp;}<br><br>运行结果：<br><br>&nbsp;output int 's four char number</p>
<p>&nbsp;first = 0x1, second = 0x2 , third = 0x3 , forth = 0x4 , iNum = 0x4030201<br>Press any key to continue<br><br>分析：<br><br>1。结构体中子节是升序存放，经过内存拷贝后，int 中四个字节升序，刚好验证 Little endian 方式</p>
2。同时，字节内的顺序不变，说明字节序影响的粒度为字节
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/34855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2007-10-15 00:23 <a href="http://www.cnitblog.com/flyinggoal/archive/2007/10/15/34855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>运行时栈空间的使用</title><link>http://www.cnitblog.com/flyinggoal/archive/2007/08/26/32451.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Sun, 26 Aug 2007 06:12:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2007/08/26/32451.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/32451.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2007/08/26/32451.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/32451.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/32451.html</trackback:ping><description><![CDATA[<p align=center><font face=宋体 color=#000000 size=+2><strong>第六章 运行时的存储空间</strong></font></p>
<div align=left>
<ul>
    <li><font face=宋体 color=#000000 size=+1>运行时存储空间的结构和分配</font>
    <li><font face=宋体 color=#000000 size=+1>过程活动记录AR</font>
    <li><font face=宋体 color=#000000 size=+1>运行时变量的访问</font> </li>
</ul>
<p align=center><strong><font face=宋体 color=#000000 size=+2>运行时的存储空间结构</font></strong></p>
<div align=left>
<ul>
    <li><strong><font face=宋体 color=#000000 size=+1>要保存的信息：</font></strong><br><font face=宋体 color=#000000 size=+1>目标代码；数据；库函数代码；<br>过程活动的控制信息等</font>
    <li><strong><font face=宋体 color=#000000 size=+1>运行时的存储空间结构：</font></strong><br><img height=193 src="http://softlab.jlu.edu.cn/temp/compile/assets/6.2.gif" width=318> <br></li>
</ul>
</div>
<p align=center><strong><font face=宋体 color=#000000 size=+2>运行时静态区的分配</font></strong></p>
<div align=left>
<ul>
    <li><font face=宋体 color=#000000 size=+1>存储对象的存储位置在程序的整个生命周期是固定的</font>
    <li><font face=宋体 color=#000000 size=+1><strong>分配对象：</strong></font><br><font face=宋体 color=#000000 size=+1>全程变量 常量 信息表</font>
    <li><font face=宋体 color=#000000 size=+1><strong>分配方法：</strong></font><br><font face=宋体 color=#000000 size=+1>块地址法：(DataArea,Offset)<br>变址模式：(Register,Offset)</font><br></li>
</ul>
</div>
<p align=center><strong><font face=宋体 color=#000000 size=+2>栈区的存储分配</font></strong></p>
<div align=left>
<ul>
    <li><font face=宋体 color=#000000 size=+1><strong>存在递归调用</strong></font>
    <li><font face=宋体 color=#000000 size=+1><strong>存储对象：</strong></font><br><font face=宋体 color=#000000 size=+1>过程中被声明的形参、局部变量 临时变量</font>
    <li><font face=宋体 color=#000000 size=+1><strong>分配方法：</strong></font><br><font face=宋体 color=#000000 size=+1>对每个被调用过程分配一段存储空间，sp存放当前过程空间的开始地址；对变量X：（Level，off),则其存放地址为off[sp]。过程结束时自动释放空间；</font>
    <li><font face=宋体 color=#000000 size=+1><strong>不能存储：</strong></font><br><font face=宋体 color=#000000 size=+1>值的生命周期长于过程的变量；<br>动态申请空间的变量；</font><br></li>
</ul>
</div>
<p align=center><strong><font face=宋体 color=#000000 size=+2>堆区的存储分配</font></strong></p>
<div align=left>
<ul>
    <li><strong><font face=宋体 color=#000000 size=+1>可随时分配和释放空间</font></strong>
    <li><strong><font face=宋体 color=#000000 size=+1>存储对象：</font></strong><br><font face=宋体 color=#000000 size=+1>动态申请空间的变量的值</font>
    <li><strong><font face=宋体 color=#000000 size=+1>释放空间方法：</font></strong><br><font face=宋体 color=#000000 size=+1>显示释放：<br>隐式释放：单指针释放;计数释放法;标记释放法</font>
    <li><strong><font face=宋体 color=#000000 size=+1>分配空间方法：</font></strong><br><font face=宋体 color=#000000 size=+1>最佳符合法；首次优先法；循环首次优先法</font><br></li>
</ul>
</div>
</div>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/32451.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2007-08-26 14:12 <a href="http://www.cnitblog.com/flyinggoal/archive/2007/08/26/32451.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>delphi 如何操作ini文件来配置一些系统属性</title><link>http://www.cnitblog.com/flyinggoal/archive/2007/04/22/26028.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Sun, 22 Apr 2007 11:46:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2007/04/22/26028.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/26028.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2007/04/22/26028.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/26028.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/26028.html</trackback:ping><description><![CDATA[<span class=t18>INI 文件在系统配置及应用程序参数保存与设置方面，具有很重要的作用，所以可视化的编程一族，如 VB、VC、VFP、Delphi 等都提供了读写 INI 文件的方法，其中Delphi中操作 INI 文件，最为简洁，这是因为Delphi3提供了一个 TInifile 类，使我们可以非常灵活的处理 INI 文件。 <br><br>一、有必要了解 INI 文件的结构：<br>;注释 <br>[小节名] <br>关键字=值<br>...<br>INI文件允许有多个小节，每个小节又允许有多个关键字，&#8220;=&#8221;后面是该关键字的值。 <br>值的类型有三种：字符串、整型数值和布尔值。其中字符串存贮在INI文件中时没有引号，布尔真值用1表示，布尔假值用0表示。<br>注释以分号&#8220;;&#8221;开头。<br><br>二、定义 <br>1、在Interface的Uses节增加IniFiles；<br>2、在Var变量定义部分增加一行：<br>myinifile:Tinifile; <br>然后，就可以对变量myinifile进行创建、打开、读取、写入等操作了。 <br><br>三、打开INI文件<br>myinifile:=Tinifile.create('program.ini');<br>上面这一行语句将会为变量myinifile与具体的文件program.ini建立联系，然后，就可以通过变量myinifile，来读写program.ini文件中的关键字的值了。 <br><br>值得注意的是，如果括号中的文件名没有指明路径的话，那么这个Program.ini文件会存储在Windows目录中 <br><br>把Program.ini文件存储在应用程序当前目录中的方法是：为其指定完整的路径及文件名。下面的两条语句可以完成这个功能：<br>Filename:=ExtractFilePath(Paramstr (0))+'program.ini'; myinifile:=Tinifile.Create(filename); <br><br>四、读取关键字的值<br>针对INI文件支持的字符串、整型数值、布尔值三种数据类型，TINIfiles类提供了三种不同的对象方法来读取INI文件中关键字的值。 <br><br>假设已定义变量vs、vi、vb分别为string、integer、boolean类型。<br>vs:=myinifile.Readstring ('小节名','关键字',缺省值); <br>vi:=myinifile.Readinteger ('小节名','关键字',缺省值);<br>vb:=myinifile.Readbool ('小节名','关键字',缺省值); <br>其中缺省值为该INI文件不存在该关键字时返回的缺省值。 <br><br>五、写入INI文件<br>同样的，TInifile类也提供了三种不同的对象方法，向INI文件写入字符串、整型数及布尔类型的关键字。 <br>myinifile.writestring('小节名','关键字',变量或字符串值); <br>myinifile.writeinteger('小节名','关键字',变量或整型数值); <br>myinifile.writebool('小节名','关键字',变量或True或False); <br>当这个INI文件不存在时，上面的语句还会自动创建该INI文件。 <br><br>六、删除关键字 <br>除了可用写入方法增加一个关键字，Tinifile类还提供了一个删除关键字的对象方法： <br>myinifile.DeleteKey('小节名','关键字'); <br><br>七、小节操作 <br>增加一个小节可用写入的方法来完成，删除一个小节可用下面的对象方法： <br>myinifile.EraseSection('小节名'); <br>另外Tinifile类还提供了三种对象方法来对小节进行操作： <br>myinifile.readsection('小节名' TStrings变量);可将指定小节中的所有关键字名读取至一个字符串列表变量中；<br>myinifile.readsections(TStrings变量);可将INI文件中所有小节名读取至一个字符串列表变量中去。<br>myinifile.readsectionvalues('小节名',TStrings变量);可将INI文件中指定小节的所有行（包括关键字、=、值）读取至一个字符串列表变量中去。<br><br>八、释放 <br>在适当的位置用下面的语句释放myinifile： <br>myinifile.distory; <br></span>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/26028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2007-04-22 19:46 <a href="http://www.cnitblog.com/flyinggoal/archive/2007/04/22/26028.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>经常需要关注的的几个SQL优化方向（摘抄）</title><link>http://www.cnitblog.com/flyinggoal/archive/2007/04/17/25829.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Tue, 17 Apr 2007 09:00:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2007/04/17/25829.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/25829.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2007/04/17/25829.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/25829.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/25829.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 查询sql优化文章时，发现这个介绍的不错&nbsp;&nbsp;<a href='http://www.cnitblog.com/flyinggoal/archive/2007/04/17/25829.html'>阅读全文</a><img src ="http://www.cnitblog.com/flyinggoal/aggbug/25829.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2007-04-17 17:00 <a href="http://www.cnitblog.com/flyinggoal/archive/2007/04/17/25829.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天看一公司招聘要求：socket i/o几种模型，不知道！！在网上搜索到了，好资料，暂存</title><link>http://www.cnitblog.com/flyinggoal/archive/2007/03/21/24387.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Wed, 21 Mar 2007 13:52:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2007/03/21/24387.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/24387.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2007/03/21/24387.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/24387.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/24387.html</trackback:ping><description><![CDATA[
		<p>本文简单介绍了当前Windows支持的各种Socket I/O模型，如果你发现其中存在什么错误请务必赐教。</p>
		<p>
				<font size="3">    一：select模型<br />    二：WSAAsyncSelect模型<br />    三：WSAEventSelect模型<br />    四：Overlapped I/O 事件通知模型<br />    五：Overlapped I/O 完成例程模型<br />    六：IOCP模型</font>
		</p>
		<p>    老陈有一个在外地工作的女儿，不能经常回来，老陈和她通过信件联系。他们的信会被邮递员投递到他们的信箱里。<br />    这和Socket模型非常类似。下面我就以老陈接收信件为例讲解Socket I/O模型~~~</p>
		<p>
				<font size="3">一：select模型</font>
		</p>
		<p>老陈非常想看到女儿的信。以至于他每隔10分钟就下楼检查信箱，看是否有女儿的信~~~~~<br />在这种情况下，“下楼检查信箱”然后回到楼上耽误了老陈太多的时间，以至于老陈无法做其他工作。<br />select模型和老陈的这种情况非常相似：周而复始地去检查......如果有数据......接收/发送.......</p>
		<p>使用线程来select应该是通用的做法：<br />procedure TListenThread.Execute;<br />var<br />  addr     : TSockAddrIn;<br />  fd_read  : TFDSet;<br />  timeout  : TTimeVal;<br />  ASock,<br />  MainSock : TSocket;<br />  len, i   : Integer;<br />begin<br />  MainSock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );<br />  addr.sin_family := AF_INET;<br />  addr.sin_port := htons(5678);<br />  addr.sin_addr.S_addr := htonl(INADDR_ANY);<br />  bind( MainSock, @addr, sizeof(addr) );<br />  listen( MainSock, 5 );</p>
		<p>  while (not Terminated) do<br />  begin<br />    FD_ZERO( fd_read );<br />    FD_SET( MainSock, fd_read );<br />    timeout.tv_sec  := 0;<br />    timeout.tv_usec := 500;<br />    if select( 0, @fd_read, nil, nil, @timeout ) &gt; 0 then //至少有1个等待Accept的connection<br />    begin<br />      if FD_ISSET( MainSock, fd_read ) then<br />      begin<br />        for i:=0 to fd_read.fd_count-1 do //注意，fd_count &lt;= 64，也就是说select只能同时管理最多64个连接<br />        begin<br />          len := sizeof(addr);<br />          ASock := accept( MainSock, addr, len );<br />          if ASock &lt;&gt; INVALID_SOCKET then<br />             ....//为ASock创建一个新的线程，在新的线程中再不停地select<br />        end; <br />      end; <br />    end; <br />  end; //while (not self.Terminated)</p>
		<p>  shutdown( MainSock, SD_BOTH );<br />  closesocket( MainSock );<br />end;</p>
		<p>
				<font size="3">二：WSAAsyncSelect模型</font>
		</p>
		<p>后来，老陈使用了微软公司的新式信箱。这种信箱非常先进，一旦信箱里有新的信件，盖茨就会给老陈打电话：喂，大爷，你有新的信件了！从此，老陈再也不必频繁上下楼检查信箱了，牙也不疼了，你瞅准了，蓝天......不是，微软~~~~~~~~<br />微软提供的WSAAsyncSelect模型就是这个意思。</p>
		<p>WSAAsyncSelect模型是Windows下最简单易用的一种Socket I/O模型。使用这种模型时，Windows会把网络事件以消息的形势通知应用程序。<br />首先定义一个消息标示常量：<br />const WM_SOCKET = WM_USER + 55;<br />再在主Form的private域添加一个处理此消息的函数声明：<br />private<br />  procedure WMSocket(var Msg: TMessage); message WM_SOCKET;<br />然后就可以使用WSAAsyncSelect了：<br />var<br />  addr  : TSockAddr;<br />  sock  : TSocket;</p>
		<p>  sock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );<br />  addr.sin_family := AF_INET;<br />  addr.sin_port := htons(5678);<br />  addr.sin_addr.S_addr := htonl(INADDR_ANY);<br />  bind( m_sock, @addr, sizeof(SOCKADDR) );</p>
		<p>  WSAAsyncSelect( m_sock, Handle, WM_SOCKET, FD_ACCEPT or FD_CLOSE );</p>
		<p>  listen( m_sock, 5 );<br />  ....</p>
		<p>应用程序可以对收到WM_SOCKET消息进行分析，判断是哪一个socket产生了网络事件以及事件类型：</p>
		<p>procedure TfmMain.WMSocket(var Msg: TMessage);<br />var<br />  sock    : TSocket;<br />  addr    : TSockAddrIn;<br />  addrlen : Integer;<br />  buf     : Array [0..4095] of Char;<br />begin<br />  //Msg的WParam是产生了网络事件的socket句柄，LParam则包含了事件类型<br />  case WSAGetSelectEvent( Msg.LParam ) of<br />    FD_ACCEPT :<br />    begin<br />      addrlen := sizeof(addr);<br />      sock := accept( Msg.WParam, addr, addrlen );<br />      if sock &lt;&gt; INVALID_SOCKET then<br />         WSAAsyncSelect( sock, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE );<br />    end;</p>
		<p>    FD_CLOSE : closesocket( Msg.WParam );<br />    FD_READ  : recv( Msg.WParam, buf[0], 4096, 0 );<br />    FD_WRITE : ;<br />  end;  <br />end;</p>
		<p>
				<font size="3">三：WSAEventSelect模型</font>
		</p>
		<p>后来，微软的信箱非常畅销，购买微软信箱的人以百万计数......以至于盖茨每天24小时给客户打电话，累得腰酸背痛，喝蚁力神都不好使~~~~~~<br />微软改进了他们的信箱：在客户的家中添加一个附加装置，这个装置会监视客户的信箱，每当新的信件来临，此装置会发出“新信件到达”声，提醒老陈去收信。盖茨终于可以睡觉了。</p>
		<p>同样要使用线程：<br />procedure TListenThread.Execute;<br />var<br />  hEvent : WSAEvent;<br />  ret    : Integer;<br />  ne     : TWSANetworkEvents;<br />  sock   : TSocket;<br />  adr    : TSockAddrIn;<br />  sMsg   : String;<br />  Index,<br />  EventTotal : DWORD;<br />  EventArray : Array [0..WSA_MAXIMUM_WAIT_EVENTS-1] of WSAEVENT;<br />begin<br />  ...socket...bind...<br />  hEvent := WSACreateEvent();<br />  WSAEventSelect( ListenSock, hEvent, FD_ACCEPT or FD_CLOSE );<br />  ...listen...</p>
		<p>  while ( not Terminated ) do<br />  begin<br />    Index := WSAWaitForMultipleEvents( EventTotal, @EventArray[0], FALSE, WSA_INFINITE, FALSE );<br />    FillChar( ne, sizeof(ne), 0 );<br />    WSAEnumNetworkEvents( SockArray[Index-WSA_WAIT_EVENT_0],  EventArray[Index-WSA_WAIT_EVENT_0], @ne );</p>
		<p>    if ( ne.lNetworkEvents and FD_ACCEPT ) &gt; 0 then<br />    begin<br />      if ne.iErrorCode[FD_ACCEPT_BIT] &lt;&gt; 0 then<br />         continue;</p>
		<p>      ret := sizeof(adr);<br />      sock := accept( SockArray[Index-WSA_WAIT_EVENT_0], adr, ret );<br />      if EventTotal &gt; WSA_MAXIMUM_WAIT_EVENTS-1 then//这里WSA_MAXIMUM_WAIT_EVENTS同样是64<br />      begin<br />        closesocket( sock );<br />        continue;<br />      end;</p>
		<p>      hEvent := WSACreateEvent();<br />      WSAEventSelect( sock, hEvent, FD_READ or FD_WRITE or FD_CLOSE );<br />      SockArray[EventTotal] := sock;<br />      EventArray[EventTotal] := hEvent;<br />      Inc( EventTotal );<br />    end;</p>
		<p>    if ( ne.lNetworkEvents and FD_READ ) &gt; 0 then<br />    begin<br />      if ne.iErrorCode[FD_READ_BIT] &lt;&gt; 0 then<br />         continue;<br />      FillChar( RecvBuf[0], PACK_SIZE_RECEIVE, 0 );<br />      ret := recv( SockArray[Index-WSA_WAIT_EVENT_0], RecvBuf[0], PACK_SIZE_RECEIVE, 0 );<br />      ......<br />    end;<br />  end;<br />end;<br /></p>
		<p>
				<font size="3">四：Overlapped I/O 事件通知模型</font>
		</p>
		<p>后来，微软通过调查发现，老陈不喜欢上下楼收发信件，因为上下楼其实很浪费时间。于是微软再次改进他们的信箱。新式的信箱采用了更为先进的技术，只要用户告诉微软自己的家在几楼几号，新式信箱会把信件直接传送到用户的家中，然后告诉用户，你的信件已经放到你的家中了！老陈很高兴，因为他不必再亲自收发信件了！</p>
		<p>Overlapped I/O 事件通知模型和WSAEventSelect模型在实现上非常相似，主要区别在“Overlapped”，Overlapped模型是让应用程序使用重叠数据结构(WSAOVERLAPPED)，一次投递一个或多个Winsock I/O请求。这些提交的请求完成后，应用程序会收到通知。什么意思呢？就是说，如果你想从socket上接收数据，只需要告诉系统，由系统为你接收数据，而你需要做的只是为系统提供一个缓冲区~~~~~<br />Listen线程和WSAEventSelect模型一模一样，Recv/Send线程则完全不同：<br />procedure TOverlapThread.Execute;<br />var<br />  dwTemp : DWORD;<br />  ret    : Integer;<br />  Index  : DWORD;<br />begin<br />  ......</p>
		<p>  while ( not Terminated ) do<br />  begin<br />    Index := WSAWaitForMultipleEvents( FLinks.Count, @FLinks.Events[0], FALSE, RECV_TIME_OUT, FALSE );<br />    Dec( Index, WSA_WAIT_EVENT_0 );<br />    if Index &gt; WSA_MAXIMUM_WAIT_EVENTS-1 then //超时或者其他错误<br />       continue;</p>
		<p>    WSAResetEvent( FLinks.Events[Index] );<br />    WSAGetOverlappedResult( FLinks.Sockets[Index], FLinks.pOverlaps[Index], @dwTemp, FALSE, FLinks.pdwFlags[Index]^ );</p>
		<p>    if dwTemp = 0 then //连接已经关闭<br />    begin<br />      ......<br />      continue;<br />    end else<br />    begin<br />      fmMain.ListBox1.Items.Add( FLinks.pBufs[Index]^.buf );<br />    end;</p>
		<p>    //初始化缓冲区<br />    FLinks.pdwFlags[Index]^ := 0;<br />    FillChar( FLinks.pOverlaps[Index]^, sizeof(WSAOVERLAPPED), 0 );<br />    FLinks.pOverlaps[Index]^.hEvent := FLinks.Events[Index];<br />    FillChar( FLinks.pBufs[Index]^.buf^, BUFFER_SIZE, 0 );</p>
		<p>    //递一个接收数据请求<br />    WSARecv( FLinks.Sockets[Index], FLinks.pBufs[Index], 1, FLinks.pdwRecvd[Index]^, FLinks.pdwFlags[Index]^, FLinks.pOverlaps[Index], nil );<br />  end;<br />end;</p>
		<p>
				<font size="3">五：Overlapped I/O 完成例程模型</font>
		</p>
		<p>老陈接收到新的信件后，一般的程序是：打开信封----掏出信纸----阅读信件----回复信件......为了进一步减轻用户负担，微软又开发了一种新的技术：用户只要告诉微软对信件的操作步骤，微软信箱将按照这些步骤去处理信件，不再需要用户亲自拆信/阅读/回复了！老陈终于过上了小资生活！</p>
		<p>Overlapped I/O 完成例程要求用户提供一个回调函数，发生新的网络事件的时候系统将执行这个函数：<br />procedure WorkerRoutine( const dwError, cbTransferred : DWORD; const<br />          lpOverlapped : LPWSAOVERLAPPED; const dwFlags : DWORD ); stdcall;<br />然后告诉系统用WorkerRoutine函数处理接收到的数据：<br />WSARecv( m_socket, @FBuf, 1, dwTemp, dwFlag, @m_overlap, WorkerRoutine );<br />然后......没有什么然后了，系统什么都给你做了！微软真实体贴！<br />while ( not Terminated ) do//这就是一个Recv/Send线程要做的事情......什么都不用做啊！！！<br />begin<br />  if SleepEx( RECV_TIME_OUT, True ) = WAIT_IO_COMPLETION then //<br />  begin<br />    ;<br />  end else<br />  begin<br />    continue;<br />  end;<br />end;</p>
		<p>
				<font size="3">六：IOCP模型</font>
		</p>
		<p>微软信箱似乎很完美，老陈也很满意。但是在一些大公司情况却完全不同！这些大公司有数以万计的信箱，每秒钟都有数以百计的信件需要处理，以至于微软信箱经常因超负荷运转而崩溃！需要重新启动！微软不得不使出杀手锏......<br />微软给每个大公司派了一名名叫“Completion Port”的超级机器人，让这个机器人去处理那些信件！</p>
		<p>“Windows NT小组注意到这些应用程序的性能没有预料的那么高。特别的，处理很多同时的客户请求意味着很多线程并发地运行在系统中。因为所有这些线程都是可运行的[没有被挂起和等待发生什么事]，Microsoft意识到NT内核花费了太多的时间来转换运行线程的上下文[Context]，线程就没有得到很多CPU时间来做它们的工作。大家可能也都感觉到并行模型的瓶颈在于它为每一个客户请求都创建了一个新线程。创建线程比起创建进程开销要小，但也远不是没有开销的。我们不妨设想一下：如果事先开好N个线程，让它们在那hold[堵塞]，然后可以将所有用户的请求都投递到一个消息队列中去。然后那N个线程逐一从消息队列中去取出消息并加以处理。就可以避免针对每一个用户请求都开线程。不仅减少了线程的资源，也提高了线程的利用率。理论上很不错，你想我等泛泛之辈都能想出来的问题，Microsoft又怎会没有考虑到呢?”-----摘自nonocast的《理解I/O Completion Port》</p>
		<p>先看一下IOCP模型的实现：</p>
		<p>//创建一个完成端口<br />FCompletPort := CreateIoCompletionPort( INVALID_HANDLE_VALUE, 0,0,0 );</p>
		<p>//接受远程连接，并把这个连接的socket句柄绑定到刚才创建的IOCP上<br />AConnect := accept( FListenSock, addr, len);<br />CreateIoCompletionPort( AConnect, FCompletPort, nil, 0 );</p>
		<p>//创建CPU数*2 + 2个线程<br />for i:=1 to si.dwNumberOfProcessors*2+2 do<br />begin<br />  AThread := TRecvSendThread.Create( false );<br />  AThread.CompletPort := FCompletPort;//告诉这个线程，你要去这个IOCP去访问数据<br />end;</p>
		<p>OK，就这么简单，我们要做的就是建立一个IOCP，把远程连接的socket句柄绑定到刚才创建的IOCP上，最后创建n个线程，并告诉这n个线程到这个IOCP上去访问数据就可以了。</p>
		<p>再看一下TRecvSendThread线程都干些什么：</p>
		<p>procedure TRecvSendThread.Execute;<br />var<br />  ......<br />begin<br />  while (not self.Terminated) do<br />  begin<br />    //查询IOCP状态（数据读写操作是否完成）<br />    GetQueuedCompletionStatus( CompletPort, BytesTransd, CompletKey, POVERLAPPED(pPerIoDat), TIME_OUT );</p>
		<p>    if BytesTransd &lt;&gt; 0  then<br />       ....;//数据读写操作完成</p>
		<p>    //再投递一个读数据请求<br />    WSARecv( CompletKey, @(pPerIoDat^.BufData), 1, BytesRecv, Flags, @(pPerIoDat^.Overlap), nil );<br />  end;<br />end;</p>
		<p>读写线程只是简单地检查IOCP是否完成了我们投递的读写操作，如果完成了则再投递一个新的读写请求。<br />应该注意到，我们创建的所有TRecvSendThread都在访问同一个IOCP（因为我们只创建了一个IOCP），并且我们没有使用临界区！难道不会产生冲突吗？不用考虑同步问题吗？<br />呵呵，这正是IOCP的奥妙所在。IOCP不是一个普通的对象，不需要考虑线程安全问题。它会自动调配访问它的线程：如果某个socket上有一个线程A正在访问，那么线程B的访问请求会被分配到另外一个socket。这一切都是由系统自动调配的，我们无需过问。</p>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/24387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2007-03-21 21:52 <a href="http://www.cnitblog.com/flyinggoal/archive/2007/03/21/24387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Delphi编程技巧集锦（摘抄）---看这个挺有用，在此记录一份</title><link>http://www.cnitblog.com/flyinggoal/archive/2007/03/19/24266.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Mon, 19 Mar 2007 03:25:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2007/03/19/24266.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/24266.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2007/03/19/24266.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/24266.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/24266.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cnitblog.com/flyinggoal/archive/2007/03/19/24266.html'>阅读全文</a><img src ="http://www.cnitblog.com/flyinggoal/aggbug/24266.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2007-03-19 11:25 <a href="http://www.cnitblog.com/flyinggoal/archive/2007/03/19/24266.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天被这个BDE错误搞了半天，不过终于好了，分享一下</title><link>http://www.cnitblog.com/flyinggoal/archive/2007/03/12/23918.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Mon, 12 Mar 2007 08:11:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2007/03/12/23918.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/23918.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2007/03/12/23918.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/23918.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/23918.html</trackback:ping><description><![CDATA[今天正编译程序时，突然就报了这个错误出来，重启电脑都没用，多亏网上高手指教，先把解决方案列于下，供受此累得朋友查阅，自己也留底供查找：<br />"Shared memory conflict ($210D)<br />Problem: The BDE is trying to use a location in memory that is already in use by the operating system or another application.<br />Solution:<br />1) Close all BDE applications.<br />2) Find the program BDEADMIN.EXE. This is usually in a directory somewhere under "\Program Files\Borland...".<br />3) Run BDEADMIN.EXE and click on the Configuration tab. <br />4) There should be an item in the treeview on the left side called "Configuration". If it's not expanded, expand it.<br />5) Next, expand the System entry below it. Under System, select INIT.<br />6) In the right-side window, find the entry called "SHAREDMEMLOCATION". Change this value to 5BDE.<br />7) Next, click on the word "Object" in the main window's menu bar, and select Apply.<br />8) Answer "OK" to the confirmation to "Save all edits...".<br /><br />Other values that may also help solve this issue on NT or Windows 2000 are: 1000, 7000, and 7F00. If none of these values resolve the issue, you may try 2000, 3000, 4000, etc. or any values in between the specified ranges below for each operating system:<br />    Windows 95/98: SHAREDMEMLOCATION = 9000 to FFFF<br />    Windows NT/2000: SHAREDMEMLOCATION = 1000 to 7F00<br />It has also been reported by some users that removing or disabling the driver for a sound card on Windows NT can resolve the issue as well, but normally just "relocating" the BDE's memory pool using the SHAREDMEMLOCATION setting will suffice.<img src ="http://www.cnitblog.com/flyinggoal/aggbug/23918.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2007-03-12 16:11 <a href="http://www.cnitblog.com/flyinggoal/archive/2007/03/12/23918.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>delphi中一个关于Tsession的使用问题（摘录）</title><link>http://www.cnitblog.com/flyinggoal/archive/2007/03/08/23741.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Thu, 08 Mar 2007 04:48:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2007/03/08/23741.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/23741.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2007/03/08/23741.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/23741.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/23741.html</trackback:ping><description><![CDATA[
		<table cellspacing="2" cellpadding="1" width="100%" border="0">
				<tbody>
						<tr>
								<td align="middle" height="35">
										<span class="title">
												<strong>关于TSession控件</strong>
										</span>
								</td>
						</tr>
						<tr>
								<td align="middle">2005-09-06 13:43:42 </td>
						</tr>
						<tr>
								<td class="font04">
										<div align="center">
										</div>
								</td>
						</tr>
						<tr>
								<td class="content">TSession是全局性的部件，在应用程序运行时，它自动地建立，在设计阶段和运行过程中它是一个不可见的部件. <br /><br /><br />TSession部件主要有下列属性：<br /><br /><br />Database属性：是TSession中可以进行连接的所有数据库的数据库名字列表，这些数据库的名字常常是实际数据库的别名，包括数据库的路径、用户名、用户登录口令等参数。<br /><br /><br />DatabaseCount属性：是TSession中可以进行连接的所有数据库的数量，它是一个整数。<br /><br /><br />KeepCounnections属性：是一个布尔型属性，用它说明应用程序是否保持与一个非活动数据库的连接。因为对于一个数据库，当该数据库中没有相应的数据集部件(TTable或TQuery)被打开时，该数据库将自动地变成非活动的数据库。缺省情况下，KeePcounnections的值是True，就是说应用程序总是保持着与数据库的连接，即使数据库变成了非活动的数据库时，也是如此。如果将KeepConnections属性设置成False，那么当数据库由活动状态变成非活动状态时，应用程序与该数据库的连接也随之中断。<br /><br /><br />NetFileDir属性：说明BDE网络控制文件的路径名。<br /><br /><br />PrivateDir属性：说明存取临时文件的路径名。　<br /><br /><br />TSession部件的方法：　<br /><br /><br />TSession部件中的大部分方法是用于向用户提供与应用程序相连接的数据库的信息，如数据库的名字及别名，数据库中的表名以及数据库引擎BDE的有关参数等，在设计数据库应用程序时，想要获取有关数据库的信息，调用TSession部件的下列方法，将会大大简化程序的设计。<br /><br /><br />GetAliasNames方法：调用该方法，我们可以获得数据库引擎BDE中定义的数据库别名。<br /><br /><br />GetAliasParams方法：该方法主要用于获取我们在BDE中定义数据库别名时所说明的参数值，如BDE所在的目录路径以及实际名称等。<br /><br /><br />GetDatabaseNames 方法：调用该方法可以帮助我们获得当前应用程序可以进行连接的所有数据库的名字，数据库的名字是用户使用BDE工具定义的实际数据库的别名。<br /><br /><br />GetDriverNames方法：数据库引擎BDE可以与多种数据库管理系统相连接，如客户/服务器数据库管理系统Oracle、Sybase以及本地数据库管理系统dBASE,Paradox等，BDE与每一种数据库管理系统进行连接时，都有相应的驱动程序，而且这些驱动程序都可以选择地安装。通过调用GetDriverNames方法。我们可以获得当前BDE安装的数据库驱动程序的名字。<br /><br /><br />GetDriverParams方法：BDE的数据库驱动程序中包含着多个参数，如支持的民族语言、DBMS的版本号、文件块大小等，对于服务器上的DBMS，还有数据库服务器的名字等等。<br /><br /><br />GetTableNames方法：因为每一个数据库都是由多个数据库表组成的，我们通过说明数据库名，然后调用GetTableNames方法，便可以获得该数据库中全部的数据库表的名字。<br /><br /><br />上述这些方法在调用时都需要一个字符串列表作为参数，而且都返回一个字符串列表的值。<br /><br /><br />TSession部件还有一个叫DropConnections的方法用于控制应用程序与数据库的连接，当调用DropConnections方法时，应用程序与所有的数据库的连接将会切断。　<br /></td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/23741.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2007-03-08 12:48 <a href="http://www.cnitblog.com/flyinggoal/archive/2007/03/08/23741.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sqlserver锁机制（摘抄）</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/12/22/20963.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Fri, 22 Dec 2006 03:23:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/12/22/20963.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/20963.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/12/22/20963.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/20963.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/20963.html</trackback:ping><description><![CDATA[通常我们在进行数据库的新增、修改、删除、查询的时候如果我们面对的不是多个用户也及时单机处理的时候，一般我们基本上不需要考虑数据库的表锁定以及死锁之类情况，但是如果我们面对的是多用户的并行处理的网络环境的时候我们对表锁定的问题就需要较为仔细的分析和考虑，否则他给我们带来的麻烦就不言而喻了，下面就把我的在这件事情上遇到的问题以及解决办法同大家一起分享。 <br />　　<br />　　也是在我的开发过程当中有这样的事情： <br />　　<br />　　两个用户同时保存新增的数据，我们的程序开始是这样处理 <br />　　cn.BeginTrans <br />　　cn.Execute "insert into tableA ....." <br />　　Set rs = cn.Execute("select count(*) from tableA where ...") <br />　　If rs.RecordCount &gt; 0 Then <br />　　'表A 的字段A不能从复 <br />　　cn.RollbackTrans <br />　　Else <br />　　cn.CommitTrans <br />　　End If <br />　　<br />　　当SQL SERVER 在执行INSERT　命令时如果我们不添加任何参数时　数据库默认申请一个 IX 锁 给表A这时候我们来分析上面的程序，当第一个用户执行 cn.Execute "insert into tableA ....." Connection <br />　　向数据库申请了一个 IX 锁 给表A ,与此同时当第二个用户执行 cn.Execute "insert into tableA ....." Connection 也向数据库也成功地申请了一个 IX 锁 给表A ,但是当执行 <br />　　Set rs = cn.Execute("select count(*) from tableA where ...") <br />　　这一句的时候就会有问题产生，我们假设第一个用户先一步执行 ，由于SELECT命令需要向数据库申请一个 <br />　　S 锁给表A，但是由于这时候表A已经存在一个IX锁并且属于另外一个连接因此他只好在此等候。紧接着第二个 <br />　　用户也执行 <br />　　Set rs = cn.Execute("select count(*) from tableA where ...") <br />　　他也会向数据库申请一个S 锁给表A ，这时候数据就会自动结束较晚申请IX锁的连接同时回滚这个事务 <br />　　这样子对于我们的应用来说就是一个很大的失败。 <br />　　<br />　　解决的办法一,设置数据参数让我们可以读取没有提交的数据、 <br />　　<br />　　cn.BeginTrans <br />　　cn.Execute "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED " <br />　　cn.Execute "insert into tableA ....." <br />　　Set rs = cn.Execute("select count(*) from tableA where ...") <br />　　If rs.RecordCount &gt; 0 Then <br />　　'表A 的字段A不能从复 <br />　　cn.RollbackTrans <br />　　Else <br />　　cn.CommitTrans <br />　　End If <br />　　cn.Execute "SET TRANSACTION ISOLATION LEVEL READ COMMITTED " <br />　　<br />　　解决的办法二,设置INSERT 命令 参数 with (tablock) 、 <br />　　<br />　　cn.BeginTrans <br />　　cn.Execute "insert into tableA with (tablock) ....." <br />　　Set rs = cn.Execute("select count(*) from tableA where ...") <br />　　If rs.RecordCount &gt; 0 Then <br />　　'表A 的字段A不能从复 <br />　　cn.RollbackTrans <br />　　Else <br />　　cn.CommitTrans <br />　　End If <br />　　<br />　　解决的办法三,增加一个没有用Lock 表、 <br />　　<br />　　cn.BeginTrans <br />　　cn.Execute "update tmpLockTable set FieldLock=1" <br />　　cn.Execute "insert into tableA with (tablock) ....." <br />　　Set rs = cn.Execute("select count(*) from tableA where ...") <br />　　If rs.RecordCount &gt; 0 Then <br />　　'表A 的字段A不能从复 <br />　　cn.RollbackTrans <br />　　Else <br />　　cn.CommitTrans <br />　　End If <img src ="http://www.cnitblog.com/flyinggoal/aggbug/20963.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-12-22 11:23 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/12/22/20963.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>delphi中字符使用技巧---在制作dll时临阵磨枪</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/11/24/19561.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Fri, 24 Nov 2006 02:25:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/11/24/19561.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/19561.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/11/24/19561.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/19561.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/19561.html</trackback:ping><description><![CDATA[
		<h4 class="TextColor1" id="subjcns!48D04C7AA0250ECD!207" style="MARGIN-BOTTOM: 0px">Delphi中的字符串</h4>
		<div id="msgcns!48D04C7AA0250ECD!207">
				<div>
						<font face="宋体, Simsun">来自Jenry的blog   </font>
						<a href="http://dev.csdn.net/user/Jenry">
								<font face="宋体, Simsun" color="#4d99d3">http://dev.csdn.net/user/Jenry</font>
						</a>
				</div>
				<div>
						<font face="宋体, Simsun" color="#4d99d3">
						</font> </div>
				<div>
						<font face="宋体, Simsun" size="2">一：各种字符串 <br />　　字符串是Object Pascal所有数据类型中最有用的类型。许多函数以字符串为传递参数。由于在Delphi中字符串的定义和使用有各种方式，包括Pascal中典型的字符串（String），Delphi支持的长字符串（ANSIString），类似于C语言的字符数组（Array of Char），指向字符的指针(Pchar)等。下面的文章就跟谈谈这些类型在定义和应用中的区别和注意事项。 <br />1． 传统的Pascal字符串 <br />　　在Pascal中，典型的字符串是一定长度的字符序列。每一字符串有一设定的长度（缺省值为255），下面是一个例子： <br />Var <br />Address:String; <br />Code:String[50]; <br />Address是一长度为255的字符串，Code的最大长度为50。 <br />传统的Pascal字符串长度不能超过255。 <br />可以用字符串连接操作"+"把字符串连接在一起： <br />Result:=String1+String2; </font>
				</div>
				<font size="2">
						<div>
								<br />
								<font face="宋体, Simsun">2． Delphi中的长字符串 <br />　　Delphi除了支持传统的Pascal短字符串还支持长字符串。长字符称为ANSIString。长字符串动态分配内存，即用字符串时才分配字符串所需内存，所以其长度不受限制。在Delphi中你如果用String1:String作类型说明，则String1既可能是短字符串也可能是长字符串，这取决于编译器中$H开关的设置。默认值为$H+，代表ANSI长字符串，VCL中的组件使用ANSI长字符串。长字符串以null结束，这就说明长字符串与C语言中的以null结束的字符串完全兼容。 <br />可以通过SetLength函数设置字符串的最大长度： <br />SetLength(String1,100);用TrimLeft,TrimRight和Trim函数分别来消除字符串开头，结尾和首尾的空白区。</font>
						</div>
						<div>
								<font face="宋体, Simsun">
										<br />3． 类似于C的字符数组 <br />　　可以用以0为起点的数组来存储以null结束的字符串。如下定义： <br />Var <br />Name:Array[0..50] of Char; </font>
						</div>
						<div>
								<br />
								<font face="宋体, Simsun">4． Pchar指针 <br />　　如果Delphi中的Exended Syntax 已经设置（缺省值），以0为起点的字符数组就和指向字符的指针Pchar完全兼容，因为以0为起点的字符数组名即指向该字符数组首字符的指针。可以将字符串直接付值给Pchar指针。例如： <br />var <br />P: PChar; <br />begin <br />P := 'Hello world'; <br />end; <br />　　这样P就指向存储字符串'Hello world'并以null结束的一块内存。 <br />许多Windows的应用程序接口API函数要求用Pchar类型作参数。Pchar指针在使用是首先用GetMem(var P: Pointer; Size: Integer)函数申请分配内存，程序结束时用FreeMem(var P: Pointer[; Size: Integer])函数释放内存。例如： <br />Var WinDir,SysDir:Pchar; <br />Begin <br />GetMem(WinDir,256);{为指针分配内存} <br />GetWindowsDirectory(WinDir,128);{将Windows安装目录放至WinDir} <br />ShowMessage('Windows directory is'+WinDir);{显示结果} <br />End; </font>
						</div>
						<div>
								<br />
								<font face="宋体, Simsun">二：字符串转换 <br />　　以上介绍了Delphi中的四类字符串的定义和使用。由于各类函数对字符串参数类型要求不一，这就需要进行字符串类型转换。 <br />1． 可以用StrPas将以null结束的字符串转换为Pascal短字符串。StrpCopy则完成相反的转换。</font>
						</div>
						<div>
								<font face="宋体, Simsun">
										<br />2． 因为长字符串以null结束，所以可以用强制类型转换将长字符串转换成Pchar类型。用法是：Pchar(s),s是一个长字符串。强制类型转换返回一个指向长字符串首字符的指针，并且所指字符串以null 结束。例如： <br />Var <br />Caption,Message:string; <br />Caption:='Hello World!'; <br />Mssage:='This is a test of long string'; <br />MessageBox(0,Pchar(Message),Pchar(Caption),MB_OK); <br />小结：在使用Delphi中的字符串时，要时刻清楚该字符串的类型，以免引起混淆。在理解字符串时要把字符串与指针，内存分配联系起来，加强理解。</font>
						</div>
				</font>
		</div>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/19561.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-11-24 10:25 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/11/24/19561.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>delphi经典函数介绍（摘抄）</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/11/24/19559.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Fri, 24 Nov 2006 02:05:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/11/24/19559.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/19559.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/11/24/19559.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/19559.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/19559.html</trackback:ping><description><![CDATA[
		<h4 class="TextColor1" id="subjcns!48D04C7AA0250ECD!231" style="MARGIN-BOTTOM: 0px">Delphi 7.0常用函数速查手册</h4>
		<div id="msgcns!48D04C7AA0250ECD!231">
				<div>
						<span>函数由一句或多句代码组成，可以实现某个特定的功能。使用函数可以使代码更加易读、易懂，加快编程速度及减少重复代码。过程与函数类似，过程与函数最重要的区别在于，过程没有返回值，而函数能有返回值。 
<p>　　在Delphi 7.0中，已为我们定义好了非常多的函数，大致分类有6种：数据类型转换函数、字符串、数组操作函数、文件、磁盘操作函数、内存、指针操作函数、数学运算函数、日期函数。</p><p>　　在Delphi中调用函数，一般情况下可以直接使用函数即可，但由于有一些函数未包含在Uses中列出的单元中(默认单元有Windows,Messages,SysUtils,Variants,Classes,Graphics, Controls,Forms,Dialogs;)，所以需要我们手动添加单元。比如，MidStr函数就未包含在这些单元中，MidStr所属单元在StrUtils中，因此我们将StrUtils添加Uses中即可。</p><p>　　在本手册中，凡是未包含在默认列出的单元中的函数，都标明了其所属的单元，使用时应当注意。</p><p>　　一、数据类型转换函数<br />　　在我们编写程序当中，根据不同情况，会使用到多种数据类型。当要对不同的类型进行操作时，必须要将不同的类型转换成同样的类型。因此熟练地掌握数据类型的转换是非常重要的。</p><p>　　1.FloatToStr<br />　　功能说明：该函数用于将“浮点型”转换成“字符型”。</p><p>　　参考实例：</p><p>　　Edit1.Text := FloatToStr(1.981); </p><p>　　2.IntToStr<br />　　功能说明：该函数用于将“整数型”转换成“字符型”。</p><p>　　参考实例：</p><p>　　S := IntToStr(10);(注：S为String类型变量。)</p><p>　　3.IntToHex<br />　　功能说明：该函数用于将“十进制”转换成“十进制”。该函数有二个参数。第一个参数为要转换的十进制数据，第二个参数是指定使用多少位来显示十六进制数据。</p><p>　　参考实例：</p><p>　　Edit1.Text := IntToHex('100', 2);</p><p>　　执行结果，Edit1.Text等于64。</p><p>　　注意：Delphi没有提供专门的“十六进制”转换为“十进制”的函数。使用StrToInt函数可以实现这个功能。具体代码是：I := StrToInt('S\' + '64'); 这时I等于100。加上一个'S\'即可将“十六进制”转换为“十进制”。</p><p>　　4.StrToInt<br />　　功能说明：该函数用于将“字符型”转换成“整数型”。</p><p>　　参考实例：</p><p>　　I := StrToInt('100');</p><p>　　注意：不能转换如 StrToInt('ab')或StrToInt('好')这样的类型，因为他们并不存在数字型。</p><p>　　5.StrToFloat<br />　　功能说明：该函数用于将“字符型”转换成“浮点型”。</p><p>　　参考实例：</p><p>　　N := StrToFloat(Edit1.Text);</p><p>　　注意：Edit1.Text中的内容为1.981(凡在Edit控件中显示的文本均为字符串)。N为Double类型，用于保存转换后的浮点型数据。</p><p>　　二、字符串、数组操作函数<br />　　对字符串及数组的操作，是每个程序员必须要掌握的。熟练的使用这些函数，在编程时能更加得心应手。</p><p>　　1.Copy<br />　　功能说明：该函数用于从字符串中复制指定范围中的字符。该函数有3个参数。第一个参数是数据源(即被复制的字符串)，第二个参数是从字符串某一处开始复制，第三个参数是要复制字符串的长度(即个数)。最后函数返回一个新的字符串(即是我们指定要复制的字符串内容)。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　 　MyStr: String; // 保存新的字符串</p><p>　　begin</p><p>　　 　S := 'I Love China!';</p><p>　　//下面将获取I Love China中的“Love”字符串。</p><p>　　MyStr := Copy(S, 3, 4);</p><p>　　end;</p><p>　　执行结果，MyStr等于“Love”，“Love”字符串在“I Love China!”中第3个位置开始，所以第二个参数为3，“Love”一共有4个字符，所以第三个参数为4。</p><p>　　2.Concat<br />　　功能说明：连接两个或多个字符串为一个字符串。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S1, S2: String;</p><p>　　begin</p><p>　　 　S1 := Concat('A', 'B'); // 连接两个字符串，S1变量等于AB。</p><p>　　 　S2 := Concat('Borland', ' Delphi', ' 7.0'); // 连接三个字符，S2变量等于Borland Delphi 7.0。</p><p>　　end;</p><p>　　3.Delete<br />　　功能说明：删除字符串中指定的字符串。该函数有三个参数。第一个参数为要进行处理的字符串，第二个参数为从何处开始删除，第三个参数为删除的字符个数。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　begin</p><p>　　 　S := 'I Like Reading CPCW.'; </p><p>　　 　// 下面的代码将删除S变量中的“C”字符。</p><p>　　 　Delete(S, 16, 1);</p><p>　　end;</p><p>　　此时S变量则是I Like Reading PCW.(“C”已经不存在了)。</p><p>　　4.High<br />　　功能说明：返回数组下标的最大值。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　arrText: array[0..9] of Char;</p><p>　　 　i: Integer;</p><p>　　begin</p><p>　　 　i := High(arrText); // i的值则为9</p><p>　　end;</p><p>　　5.Insert<br />　　功能说明：插入一个字符(串)。该函数有三个参数。第一个参数为要插入的字符(串)，第二个参数为被插入字符串(源字符串)，第三个参数为从何处插入。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　begin</p><p>　　 　S := 'Wat is your name?';</p><p>　　 　// 上面句子中的What单词查一个“h”字符，下面使用Insert函数将h添加进去。</p><p>　　 　Insert('h', S, 2); // 将“h”从第2位处插入。</p><p>　　end;</p><p>　　6.LeftStr(所在单元：StrUtils)<br />　　功能说明：返回字符串左边指定个数的新字符(串)。该函数有两个参数。第一个参数为完整的字符串，第二个参数为指定个数。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S, A: String;</p><p>　　begin</p><p>　　 　S := 'MSN Messenger';</p><p>　　 A := LeftStr(S, 3); // 从最左边开始，获取左边的三个字符。因此A变量则等于MSN。</p><p>　　end;</p><p>　　7.Length<br />　　功能说明：该函数用于统计指定字符串的长度(即个数)。</p><p>　　参考实例：</p><p>　　var</p><p>　　nLen1, nLen2: Integer; // 用于保存字符串长度</p><p>　　begin</p><p>　　 　nLen1 := Length('CPCW');</p><p>　　nLen2 := Length('电脑报');</p><p>　　end;</p><p>　　执行结果，nLen1等于4，nLen2等于6。由于一个汉字相当于两个字符的长度，所以3个汉字的长度为6。</p><p>　　8.Low<br />　　功能说明：返回数组下标的最小值。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　arrText: array[1..9] of Char;</p><p>　　 　i: Integer;</p><p>　　begin</p><p>　　 　i:= High(arrText); // i的值则为1</p><p>　　end;</p><p>　　9.LowerCase<br />　　功能说明：将字符(串)中的英文字符转换为小写。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S, A: String;</p><p>　　begin</p><p>　　 　S := 'ABC';</p><p>　　 　A := UpperCase(S); // 经过UpperCase函数转换后，A则等于abc。</p><p>　　end;</p><p>　　10.MidStr(所在单元：StrUtils)<br />　　功能说明：返回指定范围内的字符串。该函数有三个参数。第一个参数为源字符串，第二个参数为起点，第三个参数为结束点。通过第二、第三个参数则可指定要复制字符串的范围。</p><p>　　Copy函数与此函数类似。MidStr主要用于处理含有中文字符的字符串。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　 　H: String;</p><p>　　begin</p><p>　　 　S := MidStr('China', 1, 2); // S变量为Ch</p><p>　　 　H := MidStr('电脑报', 1, 1); // H变量为“电”。如果使用Copy函数，则应是H := Copy('电脑报, 1, 2)，否则返回的将不是“电”字。因此在使用操作含有中文的字符串时，最好使用MidStr。</p><p>　　end;</p><p>　　11.Pos<br />　　功能说明：查找字符(串)所在位置。该函数有二个参数。第一个参数为要查找的字符(串)，第二个参数为被查找字符(串)。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　nPos: Integer; // 用于保存查找的字符所在位置</p><p>　　begin</p><p>　　 　nPos := Pos('Like', 'I Like Reading!');</p><p>　　end;</p><p>　　此时nPos等于3。如果没有查找到，则nPos为0。</p><p>　　注意：Pos函数在查找时是要区分字符大小的。如果要实现不区分大小，那么需要使用UpperCase或LowerCase函数将两个参数的字符(串)转换为“大写”或“小写”再进行查找。</p><p>　　另外还有一个查找字符(串)的函数----AnsiPos，该函数的使用方法与Pos函数完全一样。当你查找的是汉字时，最好使用AnsiPos函数。</p><p>　　12.RightStr(所在单元：StrUtils)<br />　　功能说明：返回字符串右边指定个数的新字符(串)。该函数有两个参数。第一个参数为完整的字符串，第二个参数为指定个数。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S, A: String;</p><p>　　begin</p><p>　　 　S := 'MSN Messenger';</p><p>　　 　A := RightStr(S, 3); // 从最右边开始，获取右边的三个字符。因此A变量则等于ger。</p><p>　　end;</p><p>　　13.SetLength<br />　　功能说明：设置字符串或动态数组长度。该函数有两个参数。第一个参数为要设置的字符串变量或动态数组变量，第二个参数为指定的长度，其取值范围在0到255之间。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　 　arrText: array of Char; // 定义一个动态数组</p><p>　　begin</p><p>　　 　SetLength(S, 10); // 当设置后，S变量只能赋值长度为10的字符串。</p><p>　　 　SetLength(arrText, 10); // 只有使用SetLength为动态数组分配内存空间后才能使用动态数组。这句代码的作用相当于arrText: array[0..9] of Char</p><p>　　end;</p><p>　　14.StrPCopy<br />　　功能说明：将字符串复制到字符数组中。该函数有两个参数。第一个参数为“目标数组”，第二个参数为“字符串”。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　arrChar: array[0..255] of Char; // 这里声明了长度为256的Char型数组</p><p>　　begin</p><p>　　 　StrPCopy(arrChar, 'Come on, baby!');</p><p>　　end;</p><p>　　15.Trim<br />　　功能说明：删除字符串左右两边的空格(无论左右两边有多少个空格均被全部删除)。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　begin</p><p>　　 　S := ' Delphi 7.0 ';</p><p>　　 　S := Trim(S);</p><p>　　end;</p><p>　　16.TrimLeft<br />　　功能说明：删除字符串左边的空格(无论左边有多少个空格均被全部删除)。</p><p>　　参考实例：</p><p>　　 　S := TrimLeft(' Delphi');</p><p>　　17.TrimRight<br />　　功能说明：删除字符串左边的空格(无论左边有多少个空格均被全部删除)。</p><p>　　参考实例：</p><p>　　 　S := TrimRight('Delphi ');</p><p>　　18.UpperCase<br />　　功能说明：将字符(串)中的英文字符转换为大写。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S, A: String;</p><p>　　begin</p><p>　　 　S := 'abc';</p><p>　　 　A := UpperCase(S); // 经过UpperCase函数转换后，A则等于ABC。</p><p>　　end;</p><p>　　三、文件、磁盘操作函数<br />　　软件大多都要对文件、磁盘进行操作。熟悉掌握这些函数可以帮助你轻松实现创建、删除、保存文件等功能。</p><p>　　1.Append<br />　　功能说明：追加内容到文件中。文件必须要存在。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　 　F: TextFile;</p><p>　　begin</p><p>　　 　S := 'This is a book.';</p><p>　　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。 </p><p>　　 　Append(F); // 以追加的方式打开文件</p><p>　　 　Writeln(F, S); // 将S变量中的内容追加到文本尾后。</p><p>　　 　CloseFile(F); // 关闭文件</p><p>　　end;</p><p>　　2.AssignFile<br />　　功能说明：与指定的文件建立连接。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　F: TextFile; // 声明文本文件类型变量</p><p>　　begin</p><p>　　 　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　end;</p><p>　　3.ChDir<br />　　功能说明：改变当前目录(文件夹)。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　sDir: String;</p><p>　　begin</p><p>　　 　sDir := 'C:\Windows';</p><p>　　 　ChDir(sDir); // 此时，系统的当前目录则为C:\Windows目录。</p><p>　　end;</p><p>　　4.CloseFile<br />　　功能说明：关闭文件。当对文件的操作完成后，应该使用CloseFile函数关闭打开的文件。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　 　AllText: String;</p><p>　　 　F: TextFile;</p><p>　　begin</p><p>　　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　 　Reset(F); // 打开文件</p><p>　　 　while not EOF(F) do begin // 使用While循环，一直判断是否到了文件未尾</p><p>　　 　　Readln(F, S); // 读取一行文本</p><p>　　 　　AllText := AllText + S;</p><p>　　 　end;</p><p>　　 　CloseFile(F); // 关闭文件</p><p>　　end;</p><p>　　5.DeleteFile<br />　　功能说明：删除指定的文件。该函数只有一个参数。此参数为欲删除文件的完整路径。如果删除成功，则返回True。若删除失败、或文件不存在则返回False。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　IsOK: Boolean; // 用于保存删除状态</p><p>　　begin</p><p>　　 　IsOK := DeleteFile('C:\My Documents\Index.html'); // 函数执着后，将结果返回给IsOK变量。如果IsOK变量为True，则表示文件删除成功。</p><p>　　 　if IsOK then ShowMessage('文件删除成功！')</p><p>　　 　else ShowMessage('文件删除失败！');</p><p>　　end;</p><p>　　6.DirectoryExists<br />　　功能说明：检测指定的文件夹否存在。如果存在则返回True，反之则为False。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　IsExists: Boolean;</p><p>　　begin</p><p>　　 　IsExists := DirectoryExists ('C:\Windows');</p><p>　　 　if IsExists then ShowMessage('Windows文件夹存在！')</p><p>　　 　else ShowMessage('Windows文件夹不存在！');</p><p>　　end;</p><p>　　7.DiskFree<br />　　功能说明：获取指定磁盘的剩余空间。该函数只有一个参数。该参数用于指定要获取剩余空间的磁盘号。当参数为0时，表示获取当前磁盘的剩余空间，1为A盘，2为B盘，以此类推。如果返回值为-1，表示指定的磁盘无效。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　FreeSize: Int64;</p><p>　　begin</p><p>　　 　FreeSize := DiskFree(3); // 获取C盘中的剩余空间。返回的值是以“字节”为单位的。</p><p>　　end;</p><p>　　8.DiskSize<br />　　功能说明：获取指定磁盘的空间。该函数只有一个参数。该参数用于指定要获取磁盘空间的磁盘号。当参数为0时，表示获取当前磁盘的空间，1为A盘，2为B盘，以此类推。如果返回值为-1，表示指定的磁盘无效。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　DiskSize: Int64;</p><p>　　begin</p><p>　　 　DiskSize:= DiskSize(3); // 获取C盘的空间。返回的值是以“字节”为单位的。</p><p>　　end;</p><p>　　9.EOF<br />　　功能说明：判断文件指针是否移动到了文件未尾。当EOF函数返回值为True时，则不可以使用Readln函数进行读取文件了。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　 　AllText: String;</p><p>　　 　F: TextFile;</p><p>　　begin</p><p>　　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　 　Reset(F); // 打开文件</p><p>　　 　while not EOF(F) do begin // 使用While循环，一直判断是否到了文件未尾</p><p>　　 　　Readln(F, S); // 读取一行文本</p><p>　　 　　AllText := AllText + S;</p><p>　　 　end;</p><p>　　end;</p><p>　　10.Erase<br />　　功能说明：删除文件。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　F: File;</p><p>　　begin</p><p>　　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　 　Reset(F); // 打开文件</p><p>　　 　CloseFile(F); // 关闭文件</p><p>　　 　Erase(F); // 删除文件。在删除文件之前必须先关闭文件。</p><p>　　end;</p><p>　　11.FileExists<br />　　功能说明：检测指定的文件否存在。如果存在则返回True，反之则为False。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　IsExists: Boolean;</p><p>　　begin</p><p>　　 　IsExists := FileExists('C:\Test.txt');</p><p>　　 　if IsExists then ShowMessage('该文件存在！')</p><p>　　 　else ShowMessage('该文件不存在！');</p><p>　　end;</p><p>　　12.FileSize<br />　　功能说明：获取文件大小。返回的结果是字节为单位。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　F: file of Byte;</p><p>　　 　nSize: Longint;</p><p>　　begin</p><p>　　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　 　Reset(F); // 打开文件</p><p>　　 　nSize := FileSize(F); // 获取文件大小。</p><p>　　 　CloseFile(F); // 关闭文件</p><p>　　end;</p><p>　　13.ForceDirectories<br />　　功能说明：创建新的子目录。路径中不存在的目录将一同创建。</p><p>　　参考实例：</p><p>　　ForceDirectories('C:\Flash\MyFolder'); // 如果Flash文件夹本身不存的话，那么将会先创建Flash文件夹，然后再创建MyFolder文件夹。</p><p>　　14.MkDir<br />　　功能说明：创建一个新的子目录(文件夹)。</p><p>　　参考实例：</p><p>　　MkDir('C:\MyFolder'); // 在C盘根目录中创建了一个名叫MyFolder的文件夹。</p><p>　　需要注意的是，如果在本身不存在的目录中创建子目录将会失败。比如C盘根本不存在Flash文件夹，写成MkDir('C:\Flash\MyFolder');这样将不能成功创建MyFolder文件夹。</p><p>　　15.Reset<br />　　功能说明：以只读方式打开文件。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　F: TextFile; // 声明文本文件类型变量</p><p>　　begin</p><p>　　 　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　 　Reset(F); // 打开文件</p><p>　　end;</p><p>　　16.Rewrite<br />　　功能说明：以可写方式打开文件。如果文件不存在，将会自动创建。使用该函数，将会覆盖文件中的所有内容。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　F: TextFile; // 声明文本文件类型变量</p><p>　　begin</p><p>　　 　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　 　Rewrite(F); // 打开文件。如果文件不存在，将会在C盘中创建MyFile.txt文件。如果文件存在，将会覆盖MyFile.txt中的所有内容。</p><p>　　end;</p><p>　　17.Readln<br />　　功能说明：读取一行文本。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　 　F: TextFile;</p><p>　　begin</p><p>　　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　 　Reset(F); // 打开文件</p><p>　　 　Readln(F, S); // 读取一行文本到S变量中</p><p>　　end;</p><p>　　18.Rename<br />　　功能说明：更改文件名。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　F: File;</p><p>　　begin</p><p>　　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　 　ReName(F, 'C:\NewFile.txt'); // 更名为NewFile.txt</p><p>　　end;</p><p>　　19.Writeln<br />　　功能说明：写入一行文本。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　 　F: TextFile;</p><p>　　begin</p><p>　　 　S := 'This is a book.';</p><p>　　AssignFile(F, 'C:\MyFile.txt'); // 将C:\MyFile.txt文件与F变量建立连接，后面可以使用F变量对文件进行操作。</p><p>　　 　Rewrite(F); // 创建新文件</p><p>　　 　Writeln(F, S); // 将S变量中的内容写入文本中。</p><p>　　end;</p><p>　　四、内存、指针操作函数<br />　　在编程中，动态数组为我们处理数据带来了很大的方便。Windows API函数也为增强程序的功能提供了强有力的保障。当我们在使用这些动态数组及API函数时，常常需要动态分配内存空间，这样动态数组才能被我们使用，API函数才能正确的返回结果。因此，这些函数是必不可少的。</p><p>　　1.AllocMem<br />　　功能说明：分配内存空间并自动初始化为零。如果不需要初始化为零，可以使用GetMem代替AllocMem。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　Buffer: PChar;</p><p>　　begin</p><p>　　 　Buffer := AllocMem(256); // 分配大小为256个字节的内存空间</p><p>　　end;</p><p>　　2.Dispose<br />　　功能说明：释放为指针分配的内存空间。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　P: Pinteger; // 声明一个Integer(整型)指针</p><p>　　begin</p><p>　　 　New(P);</p><p>　　 　P^ := 100;</p><p>　　 　Dispose(P) // 释放内存</p><p>　　end;</p><p>　　3.FreeMem<br />　　功能说明：释放分配的内存空间。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　Buffer: Pchar;</p><p>　　begin</p><p>　　 　GetMem(Buffer, 256); // 分配大小为256个字节的内存空间。</p><p>　　 　FreeMem(Buffer); // 释放内存空间</p><p>　　end;</p><p>　　4.GetMem<br />　　功能说明：分配内存空间。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　Buffer: PChar;</p><p>　　begin</p><p>　　 　GetMem(Buffer, 256); // 分配大小为256个字节的内存空间。</p><p>　　end;</p><p>　　5.New<br />　　功能说明：为指针分配内存空间。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　P: PInteger; // 声明一个Integer(整型)指针</p><p>　　begin</p><p>　　 　New(P); // 分配内存</p><p>　　 　P^ := 100; // 赋值</p><p>　　end;</p><p>　　五、数学运算函数<br />　　我们在编写跟数学紧密相关的程序时，数学运算函数将大有用处。比如图像处理软件，就会大量用到这些数学运算函数。</p><p>　　默认情况下，Delphi新建的工程里，没有包含大多数的数学运行函数，因此需要在Uses中加入Math单元。</p><p>　　1.Abs<br />　　功能说明：求绝对值。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　r: Single;</p><p>　　 　i: Integer;</p><p>　　begin</p><p>　　 　r := Abs(-2.8); // r等于 2.8 </p><p>　　 　i := Abs(-156); // I 等于 156</p><p>　　end;</p><p>　　2.Exp<br />　　功能说明：Exp返回e的X次幂的值，其中e是一个自然对数基底。</p><p>　　参考实例：</p><p>　　 　e := Exp(1.0); // e为real型变量</p><p>　　end;</p><p>　　3.Floor<br />　　功能说明：取得小于等于X的最大的整数。</p><p>　　参考实例：</p><p>　　Floor(-2.8) = -3</p><p>　　Floor(2.8) = 2</p><p>　　Floor(-1.0) = -1</p><p>　　4.Int<br />　　功能说明：返回参数中的整数部分。</p><p>　　参考实例：</p><p>　　var </p><p>　　 　R: Real;</p><p>　　begin</p><p>　　 　R := Int(123.456); // R等于 123.0</p><p>　　 　R := Int(-123.456); // R等于 -123.0</p><p>　　end;</p><p>　　5.Max(所在单元：Math)<br />　　功能说明：比较两个数字，并返回最大的一个数字。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　k: Integer;</p><p>　　begin</p><p>　　 　k := Max(10, 20); // k将为20</p><p>　　end;</p><p>　　6.Min(所在单元：Math)<br />　　功能说明：比较两个数字，并返回最小的一个数字。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　k: Integer;</p><p>　　begin</p><p>　　 　k := Min(10, 20); // k将为10</p><p>　　end;</p><p>　　7.PI<br />　　功能说明：精确计算返回圆周率。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　x Extended;</p><p>　　begin</p><p>　　 　x := PI; // x等于3.1415926535897932385</p><p>　　end;</p><p>　　8.Round<br />　　功能说明：对一个实数进行四舍五入。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　I, j: Integer;</p><p>　　begin</p><p>　　 　i := Round(1.25); // i等于1</p><p>　　 　j := Round(1.62); // j等于2 </p><p>　　end;</p><p>　　9.Sqr<br />　　功能说明：取给定值的平方。</p><p>　　参考实例：</p><p>　　var</p><p>　　 i: Integer;</p><p>　　begin</p><p>　　 i := Sqr(3); // i等于9</p><p>　　end;</p><p>　　六、日期函数<br />　　对日期的处理，一般在有日期限制的共享、商业软件中经常使用到。如果你打算编写一款有日期限制的软件，熟悉使用下面的函数即可以实现。</p><p>　　1.Date<br />　　功能说明：返回当前的日期。</p><p>　　参考实例：</p><p>　　procedure TForm1.Button1Click(Sender: TObject);</p><p>　　begin</p><p>　　 　Label1.Caption := '今天是：' + DateToStr(Date);</p><p>　　end;</p><p>　　Label显示为：今天是2005年1月1日。</p><p>　　2.DateToStr<br />　　功能说明：将日期型转换为字符型。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　begin</p><p>　　 　S := DateToStr(Date);</p><p>　　end;</p><p>　　3.DateTimeToStr<br />　　功能说明：将DateTime型转换为字符型。</p><p>　　参考实例：</p><p>　　var</p><p>　　 　S: String;</p><p>　　begin</p><p>　　 　S := DateTimeToStr(Now);</p><p>　　end;</p><p>　　4.DayOfTheMonth(所在单元：DateUtils)<br />　　功能说明：获取指定日期的日。</p><p>　　参考实例：</p><p>　　Label1.Caption := IntToStr(DayOfTheMonth(Now));</p><p>　　假设当前日期为2005年1月2日，那么Label将显示为2。</p><p>　　5.DayOfTheWeek(所在单元：DateUtils)<br />　　功能说明：根据指定日期，获取星期几。</p><p>　　参考实例：</p><p>　　Label1.Caption := IntToStr(DayOfTheMonth(Now));</p><p>　　假设当前日期为2005年1月2日，那么Label将显示为7。根据返回的值来判断是周几。7表示星期天，1为星期一，依类类推。</p><p>　　6.DayOfTheYear(所在单元：DateUtils)<br />　　功能说明：根据指定日期，获取天数。</p><p>　　参考实例：</p><p>　　Label1.Caption := IntToStr(DayOfTheYear(Now));</p><p>　　假设当前日期为2005年1月2日，那么Label将显示为2。表示是2005年的第2天。</p><p>　　7.DayOf(所在单元：DateUtils)<br />　　功能说明：根据指定的日期，返回日。</p><p>　　参考实例：</p><p>　　Label1.Caption := IntToStr(DayOf(Date));</p><p>　　假设当前日期为2005年1月2日，那么Label将显示为2。</p><p>　　8.IsLeapYear<br />　　功能说明：根据指定的年，判断是否为闰年。可使用YearOf函数获取年。</p><p>　　参考实例：</p><p>　　procedure TForm1.Button1Click(Sender: TObject);</p><p>　　begin</p><p>　　 　if IsLeapYear(YearOf(Date)) then ShowMessage('是闰年')</p><p>　　 　else ShowMessage('不是闰年');</p><p>　　end;</p><p>　　9.MonthOf(所在单元：DateUtils)<br />　　功能说明：根据指定的日期，返回月份。</p><p>　　参考实例：</p><p>　　Label1.Caption := IntToStr(MonthOf(Date));</p><p>　　假设当前日期为2005年1月2日，那么Label将显示为1。</p><p>　　10.Now<br />　　功能说明：返回当前日期及时间。</p><p>　　参考实例：</p><p>　　procedure TForm1.Button1Click(Sender: TObject);</p><p>　　begin</p><p>　　 　Label1.Caption := '现在是：' + DateTimeToStr(Now);</p><p>　　end;</p><p>　　11.YearOf(所在单元：DateUtils)<br />　　功能说明：根据指定的日期，返回年。</p><p>　　参考实例：</p><p>　　Label1.Caption := IntToStr(YearOf(Date));</p><p>　　假设当前日期为2005年1月2日，那么Label将显示为2005。</p></span>
				</div>
		</div>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/19559.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-11-24 10:05 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/11/24/19559.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>delphi中动态链接库dll的使用（转载）</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/11/23/19537.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Thu, 23 Nov 2006 03:35:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/11/23/19537.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/19537.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/11/23/19537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/19537.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/19537.html</trackback:ping><description><![CDATA[动态链接库是一个能够被应用程序和其它的DLL调用的过程和函数的集合体,它里面包含的是公共代码或资源。由于DLL代码使用了内存共享技术,在某些地方windows也给了DLL一些更高的权限,因而DLL中可以实现一些一般程序所不能实现的功能,如实现windows的HOOK、ISAPI等。同时,DLL还为不同语言间代码共享提供了一条方便的途径。因而DLL在编程时应用较为广泛,本文将介绍如何在 Delphi 中建立和使用DLL。 <br />一．DLL 库内存共享机制 <br />从使用效果看,DLL和unit 很像,它们都可以被别的工程模块所调用,但二者在内部的实现机制上确存在着差别。如果一个程序模块中用uses语句引用了某个unit,编译程序在编译该模块时,便会连同unit一起编译,并把编译后的可执行代码链接到本程序模块中,这就是一个程序模块能够调用所引用unit中过程和函数的原因。当同一个unit被多个工程所引用时,则每个工程中都含有该unit的可执行代码,当含有该unit的多个工程同时执行时,unit的可执行代码会随不同工程而多次被调入内存,造成内存资源的浪费。DLL则不同,它即使被某个工程调用,编译后仍是独立的,也就是说编译后,一个DLL库形成一个单独的可执行文件,而不与任何其它的可执行文件连接在一起,因而DLL库并不从属于某个特定的工程,当多个工程调用同一个DLL库时只有第一个工程把DLL库调入内存,其余工程并不重复调入同一个DLL库到内存,而是到同一个共享内存区读取。并且,DLL的执行代码是在程序运行期间动态调入的,而不是如unit在程序运行时就与整个工程一起调入内存。这样便可消除unit带来的相同代码多处占用内存的弊病。 <br />二 Delphi中DLL库的建立 <br />在Delphi环境中,编写一个DLL同编写一个一般的应用程序并没有太大的区别。事实上作为DLL主体的DLL函数的编写,除了在内存、资源的管理上有所不同外,并不需要其它特别的手段。 <br />一般工程文件的格式为: <br />program 工程标题; <br />uses 子句; <br />程序体 <br />而DLLs工程文件的格式为: <br />library 工程标题; <br />uses 子句; <br />exprots 子句; <br />程序体 <br />它们主要的区别有两点: <br />1.一般工程文件的头标用program关键字,而DLL工程文件头标用library 关键字。不同的关键字通知编译器生成不同的可执行文件。用program关键字生成的是.exe文件,而用library关键字生成的是.dll文件; <br />2.假如DLL要输出供其它应用程序使用的函数或过程,则必须将这些函数或过程列在exports子句中。而这些函数或过程本身必须用export编译指令进行编译。 <br />在Delphi主菜单file 中选new...项,在弹出的窗口中双击DLL图标,便会自动给出DLL源模块框架,如下: <br />Library project1; <br />{...注释...} <br />uses <br />SysUtils, Classes; <br />begin <br />end. <br />接下来便可在USES和begin之间加入想在该DLL中实现的过程和函数的定义,并用export和exprots保字把它们引出,以便别的模块引用,在begin和end之间加入初始化代码,初始化代码是用来对DLL变量初始化的。应注意,即便无初始化代码begin与end也不可省略,如下例: <br />library minmax; <br />function Min(X, Y: Integer): Integer; export; <br />begin <br />if X &lt; Y then Min := X else Min := Y; <br />end; <br />function Max(X, Y: Integer): Integer; export; <br />begin <br />if X &gt; Y then Max := X else Max := Y; <br />end; <br />exports <br />Min index 1, <br />Max index 2; <br />begin <br />end. <br />经编译后,并以minmax.DLL存盘后,一个DLL库文件便形成了。 <br />三 DLL库的访问 <br />访问DLL库有两种方式,一种是静态引用,另一种是动态引用。 <br />用静态引用这种方法装入DLL要做两件事情:为DLL 库创建一个输入单元,以及用USES把输入单元连接到要使用DLL 函数的程序模块中。为DLL库创建的输入单元与普通的单元的区别仅在于:在它的接口处声明的过程、函数,并不在它的实现部分给出真正的实现代码,而是用external关键字把过程、函数的实现细节委托给外部DLL模块。 <br />external命令的使用语法如下: <br />procedure /function 过程/函数名;external DLL模块名; <br />下面给出为上面创建的minmax.DLL库写的输入单元源文件testdll .pas,从中可看出输入单元与一般单元的一些差别,代码如下所示: <br />unit testdll; <br />interface <br />uses <br />function Min (X, Y: Integer): Integer; <br />function Max (X, Y: Integer): Integer; <br />implementation <br />function Min; external ‘minmax.DLL’; <br />function Max; external ‘minmax.DLL’; <br />end. <br />一个应用程序若想调用minmax.DLL中的函数,只须在其uses语句中加入testdll 单元即可。 <br />动态装入DLL,要用到Windows的三个API函数。Loadlibrary、Freelibrary和GetprocAddress 。loadlibrary函数用来装入DLL库,其调用格式如下: <br />function loadlobrary (DLLfileName:Pchar): THandle: <br />当不再需要一个DLL库时,应调用FreeLibrary函数将其释放,以空出宝贵的内存资源,其调用格式如下: <br />procedure FreeLibrary (Libmodule:THandle) <br />Libmodule 为由LoadLibrary调用得到的DLL库句柄。在用loadlobrary 函数装入某个DLL库和调用FreeLibrary释放该DLL库之间的程序段中, 可以使用该DLL库中的过程和函数,具体使用方法是:用GetprocAddress函数把DLL库中函数的地址传递给程序中某个函数变量,再用该变量实现DLL函数的调用。GetprocAddress函数声名如下, <br />function GetprocAddress (Libmodule:THandle:procname:pchar):TFarProc: <br />如下例所示: <br />type <br />TTimeRec = record <br />Second: Integer; <br />Minute: Integer; <br />Hour: Integer; <br />end; <br />TGetTime = procedure(var Time: TTimeRec); <br />THandle = Integer; <br />var <br />Time: TTimeRec; <br />Handle: THandle; <br />GetTime: TGetTime; <br />... <br />begin <br />Handle := LoadLibrary('DATETIME.DLL'); <br />if Handle &lt;&gt; 0 then <br />begin <br />@GetTime := GetProcAddress(Handle, 'GetTime'); <br />if @GetTime &lt;&gt; nil then <br />begin <br />GetTime(Time); <br />with Time do <br />WriteLn('The time is ', Hour, ':', Minute, ':', Second); <br />end; <br />FreeLibrary(Handle); <br />end; <br />end; <br />在调用动态链接库时应注意, 所需动态链接库须与应用程序在同一目录或Windows System 目录下。 <br />动态链接库是 Windows下程序组织的一种重要方式,使用动态链接库可以极大地保护用户在不同开发工具、不同时期所做的工作,提高编程效率。<img src ="http://www.cnitblog.com/flyinggoal/aggbug/19537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-11-23 11:35 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/11/23/19537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sybase中常用的系统函数</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/11/23/19529.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Thu, 23 Nov 2006 02:39:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/11/23/19529.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/19529.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/11/23/19529.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/19529.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/19529.html</trackback:ping><description><![CDATA[六、Sybase预定义函数 <br />1．聚集函数 <br />sum([all|distinct]表达式) <br />avg([all|distinct]表达式) <br />count([all|distinct]表达式) <br />count(*) <br />max(表达式) <br />min(表达式) <br />2．字符串函数 <br />upper(字符表达式) <br />lower(字符表达式) <br />char(整型表达式) <br />char_length(字符表达式) <br />ltrim(字符表达式) <br />rtrim(字符表达式) <br />…… <br />3．数学函数 <br />abs(精确小数型表达式) <br />floor(精确小数型表达式)求小于或等于给定表达式值的最大整数（取底） <br />rand([整数型] <br />round(精确小数型表达式,整数) <br />sign(精确小数型表达式) <br />power(精确小数型表达式,整数幂) <br />…… <br />4．日期函数 <br />getdate() <br />datepart(日期部分，日期) <br />datediff(日期部分，日期1,日期2) <br />dateadd(日期部分，数值表达式，日期) <br />5．类型转换函数 <br />convert(数据类型，表达式[，格式]) <br />6．系统函数 <br />db_name([数据库ID]) <br />host_name() <br />isnull(表达式1,表达式2) <br /><img src ="http://www.cnitblog.com/flyinggoal/aggbug/19529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-11-23 10:39 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/11/23/19529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>delphi 中处理时间的函数</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/10/24/18343.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Tue, 24 Oct 2006 07:03:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/10/24/18343.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/18343.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/10/24/18343.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/18343.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/18343.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18.05pt">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">Delphi中的用于表示时间的类型：</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
								<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">首先，看一看在<span lang="EN-US">delphi中用于描述时间的几种数据结构，对时间的操作，其实就是对这些结构的操作。<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">TDateTime类型<i>：</i></span>
				<i>
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
								<o:p>
								</o:p>
						</span>
				</i>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">Delphi中最常用的表示日期时间的数据类型TDateTime类型，和普通的整形数一样，你可以给日期定义一个日期型变量以便在程序中进行操作。TdateTime类型实质上是一个Double型的数，在Delphi中是这样定义TdateTime类型： type<span style="mso-spacerun: yes">  </span>TDateTime = type Double ,具体的算法是用Double数的整数部分表示日期，以1989年12月30日为基准点，以天为单位进行加减，如数字1表示1900年1月1日，数字-1表示1989年12月29日。而小数部分则用来表示时间，其值为欲表示的时间与一整天总时间的比值，如早上6点就是6/24=0.25,而早上6:15就是(6*60+15)/(24*60)=0.2604166666666666666666666666667，下面，给出几个例子说明TDateTime类型与Double类型的交互关系</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">0<span style="mso-spacerun: yes">       </span>12/30/1899 00:00:00</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">2.75<span style="mso-tab-count: 1"></span><span style="mso-spacerun: yes">   </span>1/1/1900 18:00:00<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">-1.25<span style="mso-tab-count: 1"></span><span style="mso-spacerun: yes">   </span>12/29/1899 6:00:00 </span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">35065<span style="mso-tab-count: 1"></span><span style="mso-spacerun: yes">   </span>1/1/1996 00:00:00</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">相信大家一定能自己理解<span lang="EN-US">TdateTime与Double之间的转换方法，因此，从根本上对TDateTime的操作与Double完全一样。</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">TTimeStamp 类型：</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">这是一个用来描述日期与时间的一个结构类型，在<span lang="EN-US">Delphi中是这样定义的：</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">type <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>TTimeStamp = record<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">    </span>Time: Integer;<span style="mso-spacerun: yes">      </span>{从午夜0点开始到指定时间的毫秒数 }<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">    </span>Date: Integer;<span style="mso-spacerun: yes">      </span>{以本日为基准到指点日期的天数</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>end;</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">和<span lang="EN-US">TDateTime相比，可更直观表示高精度的时间，一般用于毫秒级的运算以及用于表示较长的时间。</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">PsystemTime 类型：</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">一个用于<span lang="EN-US">WinApi中对时间操作的指针型结构。他的定义为：<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">type<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">PSystemTime = ^TSystemTime;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">TSystemTime = record<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>wYear: Word;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>wMonth: Word;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>wDayOfWeek: Word;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>wDay: Word;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>wHour: Word;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>wMinute: Word;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>wSecond: Word;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<span style="mso-spacerun: yes">  </span>wMilliseconds: Word;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">end;</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-hansi-font-family: 'Times New Roman'">这个结构多用于调用<span lang="EN-US">WinApi操作时使用。<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">在了解了各种时间类型的本质后，相信大家都有一套操作这些类型的时间的想法，不过在<span lang="EN-US">Delphi中还提供了一整套用于操作时间的过程函数，这些过程和函数都定义在SysUnit这个单元中，现在就向大家介绍Delphi中相关函数：</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
								<o:p> </o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<b>
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">用于时间操作的函数</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">Date函数：</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">定义：<span lang="EN-US">Date: TDateTime;</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">作用：返回当前的日期</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">范例：<span lang="EN-US">CurrentDate := Date;<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">DayOfWeek函数：</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">定义：<span lang="EN-US">function DayOfWeek(Date: TDateTime): Integer;</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">作用：得到指定日期的星期值，返回<span lang="EN-US">1～7，代表周日到周六。</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">IncMouth函数：</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">定义：<span lang="EN-US">function IncMonth(const Date: TDateTime; NumberOfMonths: Integer): TDateTime;</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">作用：求给定的日期<span lang="EN-US">Data在NumberOfMonths个月后的日期。</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">范例：<span lang="EN-US">Date1 := IncMonth(date,10);<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 45pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">如果今天是<span lang="EN-US">2002-5-3，则Date1就是2003-3-3<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">IsLeapYear函数：</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">定义：<span lang="EN-US">function IsLeapYear(Year: Word): Boolean;</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">作用：判断指定的年份是否是闰年；</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">范例：<span lang="EN-US">if isLeapYear(2000) then ShowMessage(‘该年是闰年’);<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">Now函数：</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">定义：<span lang="EN-US">function Now: TDateTime;</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">作用：用于取得当前的日期时间</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">范例：<span lang="EN-US">CurrentDateTime := Now; <o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">ReplaceDate 过程</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">定义：<span lang="EN-US">procedure ReplaceDate(var DateTime: TDateTime; const NewDate: TDateTime);<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">作用：使用参数<span lang="EN-US">Newdate日期部分替换参数DateTime的日期部分，但不改变时间部分。</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">ReplaceDate 过程</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">定义：<span lang="EN-US">procedure ReplaceTime(var DateTime: TDateTime; const NewTime: TDateTime);<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">作用：使用参数<span lang="EN-US">Newdate时间部分替换参数DateTime的时间部分，但不改变日期部分。</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">如果上述这两个过程一起用，就相当于赋值了。</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">Time函数：</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">定义：<span lang="EN-US">function Time: TDateTime;</span></span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">作用：返回当前的时间</span>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">范例：<span lang="EN-US">CurrentTime := Time; <o:p></o:p></span></span>
		</p>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/18343.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-10-24 15:03 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/10/24/18343.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>delphi中关于资源释放（Free/release/freeAndNil）的一点体会</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/09/28/17448.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Thu, 28 Sep 2006 08:40:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/09/28/17448.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/17448.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/09/28/17448.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/17448.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/17448.html</trackback:ping><description><![CDATA[
		<p>
				<strong>
						<font color="#0000ff">经过这段时间对delphi中free 和 release 的仔细学习，先总结如下：<br />1。form.free直接释放资源后，调用OnDestroy事件，但是没有将form指针改为nil<br />2。form.release 等待资源不再使用后释放资源，同样不修改form指针为nil，所以在destroy中最好使用    release进行资源释放操作。<br />3。局部变量释放资源时，可以考虑用freeandnil()释放资源，这样效率会高些，能提高内存的利用率<br />4。在对窗体操作时，单纯通过assigned(form1)判断窗体是否已经创建是不够的，因为如果窗体通过free   /release进行资源释放的话，form1指向的是一个未知地址，而非nil，所以需要用(not    Assigned(ShowForm)) and (not (ShowForm is  TForm2)) 来判断该窗体是否已经创建在内存中</font>
				</strong>
				<a href="/flyinggoal/">
				</a>
		</p>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/17448.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-09-28 16:40 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/09/28/17448.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>xml学习</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/09/22/17187.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Fri, 22 Sep 2006 04:45:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/09/22/17187.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/17187.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/09/22/17187.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/17187.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/17187.html</trackback:ping><description><![CDATA[现在看网上对xml的研究如火如荼，同时对xml在数据交换上面的优势，也对她有些兴趣，在此<br />共享一些找到的珍贵资料以及自己的学习感受，以供大家交流共同提高。<img src ="http://www.cnitblog.com/flyinggoal/aggbug/17187.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-09-22 12:45 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/09/22/17187.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>制作u盘启动搜到资料，拿来共享</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/07/26/14214.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Wed, 26 Jul 2006 03:27:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/07/26/14214.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/14214.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/07/26/14214.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/14214.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/14214.html</trackback:ping><description><![CDATA[
		<font color="#a52a2a">用优盘做启动盘-转帖<br />盘版的DOS启动盘制作使用方法：<br /><br />特别说明：本文所说的U盘指的是USB接口的闪存盘（俗称U盘），不是USB硬盘。<br /><br />适用对象：有U盘的朋友（嫌光盘麻烦的朋友）<br /><br />基本功能：<br />A、支持himem和emm386的内存管理，可突破DOS的640K常规内存的限制。<br />B、支持各种常见IDE接口光驱（CDROM、DVD-ROM）。<br />C、支持smartdrv磁盘加速，大大加快DOS下磁盘读写的速度，尤其是在DOS下安装系统、GHOST镜像操作、扫描病毒木马，会为你节省不少时间。<br />D、支持串口（Serial）和PS/2口鼠标。<br />E、支持NTFS分区的读写。<br /><br />新版启动型U盘制作工具下载地址(复制链接，使用工具下载)：<br />地址1：<br /></font>
		<a href="http://nnmm.arongsoft.com/dos/boot/usb/usboot.rar" target="_blank">
				<font color="#a52a2a">http://nnmm.arongsoft.com/dos/boot/usb/usboot.rar</font>
		</a>
		<br />
		<font color="#a52a2a">地址2：<br /></font>
		<a href="http://nnmm.arongsoft.net/dos/boot/usb/usboot.rar" target="_blank">
				<font color="#a52a2a">http://nnmm.arongsoft.net/dos/boot/usb/usboot.rar</font>
		</a>
		<br />
		<font color="#a52a2a">下载后把程序解压缩出来，再把你的U盘插上，按照下面的步骤就可以把你的U盘制作成DOS启动型的（注意事先备份U盘中有用的数据）：<br />　<br /><br />USBOOT运行后（见下图）：<br /><br />①选中你的U盘；<br /><br />②点击蓝色的字选择工作模式；<br /><br />③强烈建议选择ZIP模式！<br />HDD模式和FDD模式建议在ZIP模式不能正常工作时再试用；<br /><br />ZIP模式是指把U盘模拟成ZIP驱动器模式，启动后U盘的盘符是A:<br />HDD模式是指把U盘模拟成硬盘模式；特别注意：如果选择了HDD模式，那么这个启动U盘启动后的盘符是C:，在对启动分区进行操作时就容易产生很多问题，比如：装系统时安装程序会把启动文件写到U盘而不是你硬盘的启动分区！导致系统安装失败。所以请尽量先选择ZIP模式。<br />FDD模式是指把U盘模拟成软驱模式，启动后U盘的盘符是A:，这个模式的U盘在一些支持USB-FDD启动的机器上启动时会找不到U盘，所以请酌情使用。<br />　<br /><br />④点击《开始》，开始制作。<br /><br />⑤出现下面这个对话框时，确保你的U盘中数据已没用，再选择《是》。<br /><br />⑥启动盘制作时出现下面的提示，请按正常程序拔下U盘：<br /><br />Win9x系统：可直接拔下U盘<br /><br />Win2000、XP、2003系统：请双击任务栏右侧红色圆圈内的《安全删除硬件》图标，正常卸载U盘。<br /><br />⑦请再次插上U盘<br /><br />⑧稍后就会出现下面这个成功的提示，说明你的U盘目前已经是可启动基本DOS的了，点击右上角的×关闭USBOOT。<br /><br />2、根据你U盘的模式，下载下面的rar压缩包，把里面的所有文件释放到U盘的根目录下，注意必须是根目录！<br /><br />下载地址(复制链接，使用工具下载)：<br /><br />ZIP和FDD模式压缩包下载地址1：<br /></font>
		<a href="http://nnmm.arongsoft.com/dos/boot/usb/usb-zip-fdd-1218.rar" target="_blank">
				<font color="#a52a2a">http://nnmm.arongsoft.com/dos/boot/usb/usb-zip-fdd-1218.rar</font>
		</a>
		<br />
		<font color="#a52a2a">ZIP和FDD模式压缩包下载地址2：<br /><br /></font>
		<a href="http://nnmm.arongsoft.net/dos/boot/usb/usb-zip-fdd-1218.rar" target="_blank">
				<font color="#a52a2a">http://nnmm.arongsoft.net/dos/boot/usb/usb-zip-fdd-1218.rar</font>
		</a>
		<br />
		<font color="#a52a2a">★★★★★★★★★★★★★★★★★★★★★★★★★★★★<br /><br />HDD模式压缩包下载地址1：<br /></font>
		<a href="http://nnmm.arongsoft.com/dos/boot/usb/usb-hdd-1218.rar" target="_blank">
				<font color="#a52a2a">http://nnmm.arongsoft.com/dos/boot/usb/usb-hdd-1218.rar</font>
		</a>
		<br />
		<font color="#a52a2a">HDD模式压缩包下载地址2：<br /></font>
		<a href="http://nnmm.arongsoft.net/dos/boot/usb/usb-hdd-1218.rar" target="_blank">
				<font color="#a52a2a">http://nnmm.arongsoft.net/dos/boot/usb/usb-hdd-1218.rar</font>
		</a>
		<br />
		<br />
		<font color="#a52a2a">3、如果你只想拥有本页顶部描述的基本功能，请跳过此条，看下一条。<br />想拥有更强大的DOS功能，请下载下面的压缩包(复制链接，使用工具下载)：<br />地址1：<br /></font>
		<a href="http://nnmm.arongsoft.com/dos/boot/dosapp-1218.rar" target="_blank">
				<font color="#a52a2a">http://nnmm.arongsoft.com/dos/boot/dosapp-1218.rar</font>
		</a>
		<br />
		<font color="#a52a2a">地址2：<br /></font>
		<a href="http://nnmm.arongsoft.net/dos/boot/dosapp-1218.rar" target="_blank">
				<font color="#a52a2a">http://nnmm.arongsoft.net/dos/boot/dosapp-1218.rar</font>
		</a>
		<br />
		<font color="#a52a2a">这个压缩包里包含了以下内容：<br />BIOS－DOS下模拟AWARDBIOS界面的一个小工具，可以让你在模拟的环境里学习调整BIOS，它不会触及到你真正的BIOS，放心使用，执行文件：bios.exe。<br />DM955－dm万用版9.55，分区和修复硬盘的常用工具，执行文件：dm.com。<br />DOSLFN－DOS下支持长文件名的工具DOSLFN0.32o版，使用方法请看附带说明。<br />DOS－最常用的DOS外部命令和一些DOS工具，最大限度的扩展你的DOS功能。<br />HDFIX－江民的硬盘修复王，修硬盘的利器，菜鸟慎用，执行文件：jmhdfix.exe。<br />HWINFO－DOS下不错的硬件信息查看工具，这个是最新forDOS版本4.95，执行文件：hwinfo.exe。<br />GHOST－各个DOS版本的GHOST，请选择你需要的。<br />NDD2004－诺顿的磁盘医生2004的DOS＋WIN的2合1版，用来修复硬盘的问题，DOS下的执行文件：ndd.exe，windows下的执行文件：ndd32.exe。<br />NTFS－可在DOS下读写NTFS分区的工具，对运行DOS版的杀毒软件和操作NTFS分区的数据都有实际用途，可执行文件：ntfspro.exe。（NTFS功能本启动盘已经包括）PQ805－最新的pqmagic的8.05版，DOS下分区的利器，支持200G以上的大硬盘，支持鼠标操作，可执行文件：pqmagic.exe。<br />SEA－DOS最棒的秀图工具，这个是1.3的注册版，支持鼠标操作，执行文件：sea.exe，退出按F10。<br />TW－DOS下的汉字平台：天汇3.2，执行文件：tway.bat，会自动加载拼音和五笔输入法，Alt+F2启动拼音输入法，Alt+F3启动五笔输入法，右Shift键中英文输入法切换。<br />UCDOS－DOS下的汉字平台：UCDOS98袖珍特别版，内含CCED5.18和WPS2.0，自带拼音和五笔输入法，Alt+F2启动拼音输入法，Alt+F5启动五笔输入法，右Shift键中英文输入法切换，启动UCDOS：u.bat，启动CCED：cced.exe，启动WPS：wps.com。（注意，UCDOS目录必须在光盘、硬盘、U盘的根目录下，否则运行起来会有问题，CCED和WPS运行前必须启动UCDOS或TW，否则显示的都是乱码。）VC－VolkovCommander4.99.08，DOS下支持中文长文件名的文件管理器，具有图形化的界面，支持鼠标操作，执行文件：vc.com。<br /><br /><br />此压缩包下载后解压缩到硬盘上，按目录释放到U盘根目录下即可，待启动到DOS后，转到U盘的盘符，进入相应目录执行相应的程序即可。<br /><br />4、至此，你已经有了一个功能不错的DOS启动U盘了。<br /><br />5、用这个U盘启动计算机：将U盘插入主板USB接口（最好将其他无关的USB设备暂时拔掉），重启电脑，在系统自检的界面上按Del键进入BIOS设置（如果是特殊BIOS，请参考主板手册后确定按哪个键进入BIOS），进入BIOSFEATURESSETUP中，将BootSequence（启动顺序）设定为USB-ZIP（或USB-HDD、USB-FDD，请与你制作的U盘工作模式对应）第一，设定的方法是在该项上按PageUP或PageDown键来转换选项。设定好后按ESC一下，退回BIOS主界面，选择SaveandExit（保存并退出BIOS设置，直接按F10也可以，但不是所有的BIOS都支持）回车确认退出BIOS设置。<br /><br />注意：有些主板（尤其是老主板）的BIOS中不支持U盘启动，所以会找不到相应的选项。<br /><br />6、系统重启后会自动从U盘引导DOS系统，出现的引导菜单选项如下：<br /><br /><br />BootDOSwithCDROM标准功能+光驱驱动<br />BootDOSwithCDROM+NTFS标准功能+光驱驱动+读写NTFS分区<br />BootDOSONLY(NoAnyDrivers)只启动基本DOS系统<br />REBOOTYOURPC重启计算机<br />SHUTDOWNYOURPC关闭计算机<br /><br />注1：标准功能是指已加载himem.sys和emm386.exe内存驱动、smartdrv磁盘加速、鼠标驱动、doskey。<br />注2：基本DOS系统是指仅仅加载IO.SYS、MSDOS.SYS和COMMAND.COM这3个DOS核心文件，不加载其他任何驱动和程序。<br /><br />用↑↓键选择你需要的启动方式，回车确定。<br /><br />7、启动成功后，会显示DOSLOADINGSUCCESSFUL的字样。<br /><br />如果是ZIP模式或FDD模式的U盘，会出现A:\&gt;的提示符<br />如果是HDD模式的U盘，会出现C:\&gt;的提示符<br /><br />至此DOS系统启动完毕，你现在就可以做你该做的事情了。<br /><br /><br />注意事项：<br /><br />1、制作启动盘之前请备份好U盘上有用的数据，最好能完全格式化一遍U盘。<br /><br />2、有NTFS分区的硬盘或多硬盘的系统，在DOS下硬盘的盘符排列和在Windows中的顺序可能不一样，请大家自行查找确定，以免误操作。<br /><br />3、如果启动U盘在使用中发生问题，请试试下面的方法：<br /><br />①换成其他的工作模式（ZIP、HDD、FDD）；<br />②选择DOS启动菜单中其他的选项；<br />③更换一个不同品牌的U盘重新制作一次；<br />④把U盘拿到其他品牌的电脑上试一下能不能正常工作。<br /><br />4、U盘启动盘出现问题主要原因：<br /><br />①主板不支持U盘启动（或支持的不完善）；<br />②某些DOS软件（尤其是对磁盘操作类的）对U盘支持的可能不是很好；<br />③U盘是DOS之后出现的新硬件，种类比较繁杂，而且目前绝大多数的USB设备都没有DOS下的驱动，目前使用的基本都是兼容驱动，所以出现一些问题也在所难免；<br />④U盘本身质量有问题；<br />⑤经常对U盘有不正确的操作，比如2000、XP、2003下直接插拔U盘，而不是通过《安全删除硬件》来卸载。<br /><br />5、关于USBOOT这个工具的使用注意事项和容易产生的问题，请看其压缩包中的PDF文档，里面说的已经很详细了。<br /></font>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/14214.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-07-26 11:27 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/07/26/14214.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载Delphi学习细节</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/05/09/10273.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Tue, 09 May 2006 15:19:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/05/09/10273.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/10273.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/05/09/10273.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/10273.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/10273.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="590" align="left" border="0">
				<tbody>
						<tr>
								<td width="51" background="http://www.blogcn.com/images/bobo/skin1/dirary_bj.jpg">
								</td>
								<td valign="top" width="539">
										<table cellspacing="0" cellpadding="0" width="539" align="left" bgcolor="#fbfbfb" border="0">
												<tbody>
														<tr>
																<td>
																		<!--日志开始main.js-->
																		<span id="showcontent">
																				<table id="wp" style="WORD-BREAK: break-all; WORD-WRAP: break-word" cellspacing="0" cellpadding="0" width="100%" border="0">
																						<!--StartDiry-->
																						<!--6353580-->
																						<tbody>
																								<tr>
																										<td>
																												<p>
																												</p>
																												<table class="diary_bg2" cellspacing="3" cellpadding="3" width="100%" border="0">
																														<tbody>
																																<tr>
																																		<td>
																																				<a class="diary_title" href="http://www.blogcn.com/user29/chendi0301/blog/6353580.html">
																																						<font class="diary_title">delphi问题集（二） [转]</font>
																																				</a>
																																				<br />
																																				<br />问题1：在Delphi中如何对变量赋值？<br />答：在Delphi中使用的编程语言是基于Pascal的面向对象语言，但是在功能上更为强大。所用的语法与Pascal一样，对于赋值语句aa:= ″1234″;不能省掉等号前的冒号,这是Pascal赋值语句所必须的,并且语句最后的分号也必不可少,它代表一个语句的结束。另外，在使用变量前必须先对其声明（定义变量），否则无法使用。下面是一个完整的包含赋值语句的程序段：<br />　　var aa:string;<br />　　begin<br />　　aa:=DateToStr((Date＋5))；<br />　　end;<br />　　<br />问题2：如何在Delphi中制作数据库报表?<br />答：在任何数据库系统中报表系统都十分重要，它是主要的输出系统，Delphi中当然也少不了报表系统。<br />　　QuickReport就是Delphi中以控件组的形式提供的报表系统，完全支持Delphi数据库，可以方便地实现数据库的报表功能。可以立即打开Delphi在控件组模板中找到QuickReport。<br />　　启动Delphi后选择File|News，这时会出现一个模板和向导组，选择Business中的QuickReport Wizard,按照向导指示进行选择就可以制作一个简单的数据库报表程序。如果需要将自己的数据库资料输出到报表，请先打开数据库项目，然后在File|News菜单中选择New中的Report选项,可以立即生成一个空的报表窗口，通过鼠标右键激活报表设定。在FoxPro的报表中表格线是通过画线条来实现，而在QuickReport中可以选择QrShape来实现，只需修改属性Shape的设定值(qrsVertLine代表垂直线，qrsHorLine代表水平线)即可,至于线条的宽度和长度可以在相应的属性中设定。<br /><br />问题3：Delphi在BDE别名中不识别“网上邻居”的路径，应该怎样做？<br />答：利用Windiws95对等网可以简单地实现数据共享。将数据库放在其中某个共享路径下就能实现数据库资料共享，但是如何在BDE中设定？在网络中无法使用本地路径，所以可以先将共享路径映射为网络驱动器，然后就可以象本地文件一样了，另外直接输入网络路径也可以实现这种功能，例如可以输入\\Computer1\Database\, 指定共享计算机名为Computer1的Database目录。另外，还可以通过浏览方式找到“网上邻居”中指定的网络路径。<br /><br />问题4：请介绍一些学习Delphi的书籍和网站。<br />答：现在许多书只介绍Delphi入门、有关Pascal的语法和整个运行环境的使用，但是对于更进一步的使用说明和范例就不多了。当然最终要掌握Delphi还是得学会看Delphi的帮助，它才是最权威的资料，其中有许多范例，直接复制过来作一定的修改就可以在自己的程序中使用。我推荐给读者的网站有：Delphi的制作公司Inprise的网站<img alt="::URL::" hspace="2" src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.inprise.com/" target="_blank">http://www.inprise.com/</a>  ，其次是中文Delphi网站<img alt="::URL::" hspace="2" src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.vclxx.com/" target="_blank">http://www.vclxx.com</a>  ， Delphi用户最好能到这些网站去访问，其中有许多有趣的资源、范例程序和已经增强的控件。<br /><br />问题5:问题集一中介绍的ExecuteFile()函数为什么在使用时出现错误，甚至无法使用?<br />答:首先,必须将声明加入程序,而且不要在form的OnCreate中调用，因为调用Form－OnCreate时数据未初始化，就会出现非法读取内存错误。<br /><br /><span id="dissub1"><div id="blog_sub_st" name="blog_sub_st">loading...</div></span></td>
																																</tr>
																														</tbody>
																												</table>
																										</td>
																								</tr>
																								<!--/6353580-->
																								<!--6353548-->
																								<tr>
																										<td>
																												<p>
																												</p>
																												<div class="diary_datetitle"> </div>
																												<table class="diary_bg1" cellspacing="3" cellpadding="3" width="100%" border="0">
																														<tbody>
																																<tr>
																																		<td>
																																				<a class="diary_title" href="http://www.blogcn.com/user29/chendi0301/blog/6353548.html">
																																						<font class="diary_title">delphi问题集（一） [转]</font>
																																				</a>
																																				<br />
																																				<br />标题:delphi问题集（一）<br />1.问：Delphi中实现类似VB中的字符串操作？<br />　答：Delphi提供了丰富的字符串操作，可以实现许多复杂的处理。<br />　Pos在字符串中查找指定字符串的位置，用于文字的查找<br />　Delete删除字符串中从指定位置开始指定数量的字符<br />　Insert在字符串指定文字开始插入字符串<br />　Copy返回字符串中指定位置的一定长度的字符串<br />　Length返回指定字符串的长度<br /><br />2.问：如何进行字符串与其他类型数据转换？<br />　答：可以用inttostr()函数，这是一个十分常用的函数，如果你希望将整数转化为字符串的形式，就必须使用这个函数。使用的方法十分简单，inttostr(整数)返回一个代表这个整数的字符串。对应函数strtoint(字符串)返回整数。特别注释：如果你不想因为输入了不是数字的字符串而引起异常报警（这是很常见的），你可以使用一个替代的函数，自己进行输入校验，这个函数就是StrToIntDef。使用的方法是：StrToIntDef（字符串，默认数字），返回的是数字，如果输入的字符串不是合法的数字，返回的将是默认的数字，如果对其进行检测，就可以发现问题。If (Inputbox(′输入数字′),－1)=－1 then showmessage(′你输入的不是数字或者输入了－1′);对应的函数还有许多，下面仅列出其函数名，具体的使用方法类似，如果需要进一步了解此类函数，请参阅delphi的联机帮助。<br />　　FloatTostr浮点数转化成字符串<br />　　FloatToStrF带格式的浮点数转化成字符串<br />　　IntToHex整数到十六进制字符串<br />　　TimeToStr时间转化成字符串<br />　　DateToStr日期转化成字符串<br />　　DateTimeToStr日期时间转化成字符串<br />　　FmtStr按指定格式输出字符串，<br />3.delphi编程中调用其他执行程序？<br />　答：Function ExecuteFile(const FileName, Params, DefaultDir: string;ShowCmd: Integer): THandle; 是最简单的执行文件调用方法。<br />　　演示的程序如下：<br />　　executefile(′c:\winamp\winamp.exe′, <br />'winamp.m3u′,'d:\mp3\′,0);<br />　　这段程序就是我编写的定时启动播放音乐程序的一部分，仅供大家参考。<br />　　提示：最为有趣的是如果在输入的参数中填入的不是可执行文件名，而是某个数据文件如DOC文件，它会自动调用相应的程序打开（如Word）。通过这一功能还可以实现，自动发送E－mail，自动访问指定网站的功能。<br />　　executefile(′mailto:delphi32@infoworld.sh.cn′,″,″,0);<br />　　简单的语句实现了调用默认电子邮件程序向我发信的功能。<br />　　executefile(′<img alt="::URL::" hspace="2" src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://delphi.sq.sh.cn′,″,″,0);/" target="_blank">http://delphi.sq.sh.cn′,″,″,0);</a><br />　　立即可以拨号上网看到我的主页<br />　　executefile(′d:\mp3\cd01\001.mp3′,″,″,0);<br />　　立即调用默认的MP3播放程序播放这首歌曲。<br /><br /><br />--------------------------------------------------------------------------------<br /><span id="dissub2"><div id="blog_sub_st" name="blog_sub_st">loading...</div></span></td>
																																</tr>
																														</tbody>
																												</table>
																										</td>
																								</tr>
																								<!--/6353548-->
																								<!--6353317-->
																								<tr>
																										<td>
																												<table class="diary_bg2" cellspacing="3" cellpadding="3" width="100%" border="0">
																														<tbody>
																																<tr>
																																		<td>
																																				<a class="diary_title" href="http://www.blogcn.com/user29/chendi0301/blog/6353317.html">
																																						<font class="diary_title">delphi中的几个技巧</font>
																																				</a>
																																				<br />
																																				<br />1、判断一个字符串是否包含于另外一个字符串的方法<br />例如：if pos('ab','abcd')&lt;&gt;0 then<br />messagedlg('ab是包含于abcd',mtConfirmation,[mbYes, mbNo],0);<br />pos(obj,target) 在target字符串中找出第一个出现obj的第一个字符位置,如果找不到,返回0.<br /><br />2、如何使窗口全屏，类似游戏一样，而不是窗口的最大化! <br />(1) BorderStyle 为 bsNone<br />(2) Windowstate 为 wsMaximized<br />(3) 退出时可加一个按钮之类的，写上 close 即可退出。<br /><br />3、数字格式化输出<br />format('%8.2f',[123.456])，返回字符串' 123.46'。<br /><br />4、播放一个wav文件<br />use mmsystem;<br />SndPlaySound('hello.wav',SND_FILENAME or SND_SYNC);<br /><br />5、InputBox,InputQuery和ShowMessage函数的威力<br />uses dialogs;<br />var s,s1:string;<br />b:boolean;<br />begin<br />s:=trim(Inputbox('NewPassword','Password','masterkey'));<br />b:=s&lt;&gt;''<br />s1:=s;<br />if b then b:=InputQuery('Confirm Password','Password',s1);<br />if not b or (s1&lt;&gt;s) then ShowMessage('Password Failed');<br />end;<br /><br />6、几个有关子目录的操作的过程<br />MkDir(str); ChDir(str); GetDir(DriveID,str); SetCurrentDir(str);<br />IOResult --上面几个过程调用成功即返回0值<br /><br />7、将一个可视控件变成图形类型<br />例如将一个带背景的LABEL变成一个TIMAGE图片类型，可以这样做：<br />image1.width:=label1.width;<br />image1.height:=label1.height;<br />label1.perform(WM_PAINT,image1.Canvas.Handle,0);<br /><br />8、如何得到字符的ASCII值<br />得到字符的ASCII值，可以用如下语句：<br />var: a:integer;<br />string1:string;<br />begin<br />string1:='ABC'<br />a:=byte(string[1]); {此时就得到'A'的ASCII值}<br />end; <br /><br />9、动态更新DBGrid的颜色<br />例如，如果一个城市的人口大于200万，我们就让它显示为蓝色。使用的控件事件为DBGrid.OnDrawColumeCell： <br />procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect:TRect;DataCol: Integer; Column: TColumn; State: TGridDrawState);<br />begin<br />if Table1.FieldByName('Population').AsInteger &gt; 20000000 then<br />DBGrid1.Canvas.Font.Color := clBlue;<br />DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);<br />end; <br /><br />10、获得命令行参数<br />1. 取得命令列参数的个数: ParamCount 函数<br />2. 呼叫 ParamStr(0), 传回执行档的档名(含路径) <br />3. 呼叫ParamStr(n), 传回第ｎ个参数的内容<br />例子：<br />procedure TForm1.FormCreate(Sender: TObject);<br />var<br />　ix: integer;<br />begin<br />　Memo1.Lines.Clear;<br />　if ParamCount = 0 then<br />　　Memo1.Lines.Add('没有参数')<br />　else<br />　begin<br />　　Memo1.Lines.Add('档名:' + ParamStr(0));<br />　　for ix := 1 to ParamCount do <br />　　Memo1.Lines.Add(ParamStr(ix));<br />　end;<br />end;<br /></td>
																																</tr>
																														</tbody>
																												</table>
																										</td>
																								</tr>
																						</tbody>
																				</table>
																		</span>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/10273.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-05-09 23:19 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/05/09/10273.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>delphi的运行时浅析（学习中）</title><link>http://www.cnitblog.com/flyinggoal/archive/2006/03/18/7754.html</link><dc:creator>风筝</dc:creator><author>风筝</author><pubDate>Sat, 18 Mar 2006 09:38:00 GMT</pubDate><guid>http://www.cnitblog.com/flyinggoal/archive/2006/03/18/7754.html</guid><wfw:comment>http://www.cnitblog.com/flyinggoal/comments/7754.html</wfw:comment><comments>http://www.cnitblog.com/flyinggoal/archive/2006/03/18/7754.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/flyinggoal/comments/commentRss/7754.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flyinggoal/services/trackbacks/7754.html</trackback:ping><description><![CDATA[
		<p>
				<font size="2">Delphi 的RTTI机制浅探&lt;一&gt;</font>
		</p>
		<p>
				<font size="2">作者：</font>
				<a href="mailto:Savetime|savetime2k@yahoo.com">
						<font size="2">Savetime|savetime2k@yahoo.com</font>
				</a>
				<font size="2">    转贴自：Delphibbs.com<br />目录<br />===========================================================<br />⊙ RTTI 简介<br />⊙ 类(class) 和 VMT 的关系<br />⊙ 类(class)、类的类(class of class)、类变量(class variable) 的关系<br />⊙ TObject.ClassType 和 TObject.ClassInfo<br />⊙ is 和 as 运算符的原理<br />⊙ TTypeInfo – RTTI 信息的结构<br />⊙ 获取类(class)的属性(property)信息<br />⊙ 获取方法(method)的类型信息<br />⊙ 获取有序类型(ordinal)、集合(set)类型的 RTTI 信息<br />⊙ 获取其它数据类型的 RTTI 信息<br />===========================================================<br />本文排版格式为：<br />    正文由窗口自动换行；所有代码以 80 字符为边界；中英文字符以空格符分隔。</font>
		</p>
		<p>
				<font size="2">(作者保留对本文的所有权利，未经作者同意请勿在在任何公共媒体转载。)</font>
		</p>
		<p>
				<br />
				<font size="2">正文<br />===========================================================<br />⊙ RTTI 简介<br />===========================================================</font>
		</p>
		<p>
				<font size="2">RTTI(Run-Time Type Information) 翻译过来的名称是“运行期类型信息”，也就是说可以在运行期获得数据类型或类(class)的信息。这个 RTTI 到底有什么用处，我现在也说不清楚。我是在阅读 Delphi 持续机制的代码中发现了很多 RTTI 的运用，只好先把 RTTI 学习一遍。下面是我的学习笔记。如果你发现了错误请告诉我。谢谢！</font>
		</p>
		<p>
				<font size="2">Delphi 的 RTTI 主要分为类(class)的 RTTI 和一般数据类型的 RTTI，下面从类(class)开始。</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ 类(class) 和 VMT 的关系<br />===========================================================</font>
		</p>
		<p>
				<font size="2">一个类(class)，从编译器的角度来看就是一个指向 VMT 的指针(在后文用 VMTptr 表示)。在类的 VMTptr 的负地址方向存储了一些类信息的指针，这些指针的值和指针所指的内容在编译后就确定了。比如 VMTptr - 44 的内容是指向类名称(ClassName)的指针。不过一般不使用数值来访问这些类信息，而是通过 System.pas 中定义的以 vmt 开头的常量，如 vtmClassName、vmtParent 等来访问。</font>
		</p>
		<p>
				<font size="2">类的方法有两种：对象级别的方法和类级别的方法。两者的 Self 指针意义是不同的。在对象级别的方法中 Self 指向对象地址空间，因此可以用它来访问对象的成员函数；在类级别的方法中 Self 指向类的 VMT，因此只能用它来访问 VMT 信息，而不能访问对象的成员字段。</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ 类(class)、类的类(class of class)、类变量(class variable) 的关系<br />===========================================================</font>
		</p>
		<p>
				<font size="2">上面说到类(class) 就是 VMTptr。在 Delphi 中还可以用 class of 关键字定义类的类，并且可以使用类的类定义类变量。从语法上理解这三者的关键并不难，把类当成普通的数据类型来考虑就可以了。在编译器级别上表现如何呢？</font>
		</p>
		<p>
				<font size="2">为了简化讨论，我们使用 TObject、TClass 和 TMyClass 来代表上面说的三种类型：</font>
		</p>
		<p>
				<font size="2">type<br />  TClass = class of TObject;<br />var<br />  TMyClass: TClass;<br />  MyObject: TObject;<br />begin<br />  TMyClass := TObject;<br />  MyObject := TObject.Create;<br />  MyObject := TClass.Create;<br />  MyObject := TMyClass.Create;<br />end;<br />  <br />在上面的例子中，三个 TObject 对象都被成功地创建了。编译器的实现是：TObject 是一个 VMTPtr 常量。TClass 也是一个 VMTptr 常量，它的值就是 TObject。TMyClass 是一个 VMTptr 变量，它被赋值为 TObject。TObject.Create 与 TClass.Create 的汇编代码完全相同。但 TClass 不仅缺省代表一个类，而且还(主要)代表了类的类型，可以用它来定义类变量，实现一些类级别的操作。</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ TObject.ClassType 和 TObject.ClassInfo<br />===========================================================</font>
		</p>
		<p>
				<font size="2">function TObject.ClassType: TClass;<br />begin<br />  Pointer(Result) := PPointer(Self)^;<br />end;</font>
		</p>
		<p>
				<font size="2">TObject.ClassType 是对象级别的方法，Self 的值是指向对象内存空间的指针，对象内存空间的前 4 个字节是类的 VMTptr。因此这个函数的返回值就是类的 VMTptr。</font>
		</p>
		<p>
				<font size="2">class function TObject.ClassInfo: Pointer;<br />begin<br />  Result := PPointer(Integer(Self) + vmtTypeInfo)^;<br />end;</font>
		</p>
		<p>
				<font size="2">TObject.ClassInfo 使用 class 关键字定义，因此是一个类级别的方法。该方法中的 Self 指针就是 VMTptr。所以这个函数的返回值是 VMTptr 负方向的 vmtTypeInfo 的内容。</font>
		</p>
		<p>
				<font size="2">TObject.ClassInfo 返回的 Pointer 指针，实际上是指向类的 RTTI 结构的指针。但是不能访问 TObject.ClassInfo 指向的内容(TObject.ClassInfo 返回值是 0)，因为 Delphi 只在 TPersistent 类及 TPersistent 的后继类中产生 RTTI 信息。(从编译器的角度来看，这是在 TPersistent 类的声明之前使用 {$M+} 指示字的结果。)</font>
		</p>
		<p>
				<font size="2">TObject 还定义了一些获取类 RTTI 信息的函数，列举在下，就不一一分析了：</font>
		</p>
		<p>
				<font size="2">  TObject.ClassName: ShortString;   类的名称<br />  TObject.ClassParent: TClass;      对象的父类<br />  TObject.InheritsFrom: Boolean;    是否继承自某类<br />  TObject.InstanceSize: Longint;    对象实例的大小</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ is 和 as 运算符的原理<br />===========================================================</font>
		</p>
		<p>
				<font size="2">我们知道可以在运行期使用 is 关键字判断一个对象是否属于某个类，可以使用 as 关键字把某个对象安全地转换为某个类。在编译器的层次上，is 和 as 的操作是由 System.pas 中两个函数完成的。</font>
		</p>
		<p>
				<font size="2">{ System.pas }<br />function _IsClass(Child: TObject; Parent: TClass): Boolean;<br />begin<br />  Result := (Child &lt;&gt; nil) and Child.InheritsFrom(Parent);<br />end;</font>
		</p>
		<p>
				<font size="2">_IsClass 很简单，它使用 TObject 的 InheritsForm 函数判断该对象是否是从某个类或它的父类中继承下来的。每个类的 VMT 中都有一项 vmtParent 指针，指向该类的父类的 VMT。TObject.InheritsFrom 实际上是通过[递归]判断父类 VMT 指针是否等于自己的 VMT 指针来判断是否是从该类继承的。</font>
		</p>
		<p>
				<font size="2">{ System.pas }<br />class function TObject.InheritsFrom(AClass: TClass): Boolean;<br />var<br />  ClassPtr: TClass;<br />begin<br />  ClassPtr := Self;<br />  while (ClassPtr &lt;&gt; nil) and (ClassPtr &lt;&gt; AClass) do<br />    ClassPtr := PPointer(Integer(ClassPtr) + vmtParent)^;<br />  Result := ClassPtr = AClass;<br />end;</font>
		</p>
		<p>
				<font size="2">as 操作符实际上是由 System.pas 中的 _AsClass 函数完成的。它简单地调用 is 操作符判断对象是否属于某个类，如果不是就触发异常。虽然 _AsClass 返回值为 TObject 类型，但编译器会自动把返回的对象改变为 Parent 类，否则返回的对象没有办法使用 TObject 之外的方法和数据。</font>
		</p>
		<p>
				<font size="2">{ System.pas }<br />function _AsClass(Child: TObject; Parent: TClass): TObject;<br />begin<br />  Result := Child;<br />  if not (Child is Parent) then<br />    Error(reInvalidCast);   // loses return address<br />end;</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ TTypeInfo – RTTI 信息的结构<br />===========================================================</font>
		</p>
		<p>
				<font size="2">RTTI 信息的结构定义在 TypInfo.pas 中：</font>
		</p>
		<p>
				<font size="2">  TTypeInfo = record        // TTypeInfo 是 RTTI 信息的结构<br />    Kind: TTypeKind;        // RTTI 信息的数据类型<br />    Name: ShortString;      // 数据类型的名称<br />   {TypeData: TTypeData}    // RTTI 的内容<br />  end;</font>
		</p>
		<p>
				<font size="2">TTypeInfo 就是 RTTI 信息的结构。TObject.ClassInfo 返回指向存放 class TTypeInfo 信息的指针。Kind 是枚举类型，它表示 RTTI 结构中所包含数据类型。Name 是数据类型的名称。注意，最后一个字段 TypeData 被注释掉了，这说明该处的结构内容根据不同的数据类型有所不同。</font>
		</p>
		<p>
				<font size="2">TTypeKind 枚举定义了可以使用 RTTI 信息的数据类型，它几乎包含了所有的 Delphi 数据类型，其中包括 tkClass。</font>
		</p>
		<p>
				<font size="2">  TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat,<br />    tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString,<br />    tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray);</font>
		</p>
		<p>
				<font size="2">TTypeData 是个巨大的记录类型，在此不再列出，后文会根据需要列出该记录的内容。</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ 获取类(class)的属性(property)信息<br />===========================================================</font>
		</p>
		<p>
				<font size="2">这一段是 RTTI 中最复杂的部分，努力把本段吃透，后面的内容都是非常简单的。</font>
		</p>
		<p>
				<font size="2">下面是一个获取类的属性的例子：</font>
		</p>
		<p>
				<font size="2">procedure GetClassProperties(AClass: TClass; AStrings: TStrings);<br />var<br />  PropCount, I: SmallInt;<br />  PropList: PPropList;<br />  PropStr: string;<br />begin<br />  PropCount := GetTypeData(AClass.ClassInfo).PropCount;<br />  GetPropList(AClass.ClassInfo, PropList);<br />  for I := 0 to PropCount - 1 do<br />  begin<br />    case PropList[I]^.PropType^.Kind of<br />      tkClass      : PropStr := '[Class] ';<br />      tkMethod     : PropStr := '[Method]';<br />      tkSet        : PropStr := '[Set]   ';<br />      tkEnumeration: PropStr := '[Enum]  ';<br />    else<br />      PropStr := '[Field] ';<br />    end;<br />    PropStr := PropStr + PropList[I]^.Name;<br />    PropStr := PropStr + ': ' + PropList[I]^.PropType^.Name;<br />    AStrings.Add(PropStr);<br />  end;<br />  FreeMem(PropList);<br />end;</font>
		</p>
		<p>
				<font size="2">你可以在表单上放置一个 TListBox ，然后执行以下语句观察执行结果：</font>
		</p>
		<p>
				<font size="2">  GetClassProperties(TForm1, ListBox1.Items);</font>
		</p>
		<p>
				<font size="2">该函数先使用 GetTypeData 函数获得类的属性数量。GetTypeData 是 TypInfo.pas 中的一个函数，它的功能是返回 TTypeInfo 的 TypeData 数据的指针：</font>
		</p>
		<p>
				<font size="2">{ TypInfo.pas }<br />function GetTypeData(TypeInfo: PTypeInfo): PTypeData; assembler;</font>
		</p>
		<p>
				<font size="2">class 的 TTypeData 结构如下：</font>
		</p>
		<p>
				<font size="2">  TTypeData = packed record<br />    case TTypeKind of<br />      tkClass: (<br />        ClassType: TClass;         // 类 (VMTptr)<br />        ParentInfo: PPTypeInfo;    // 父类的 RTTI 指针<br />        PropCount: SmallInt;       // 属性数量<br />        UnitName: ShortStringBase; // 单元的名称<br />       {PropData: TPropData});     // 属性的详细信息<br />  end;</font>
		</p>
		<p>
				<font size="2">其中的 PropData 又是一个大小可变的字段。TPropData 的定义如下：</font>
		</p>
		<p>
				<font size="2">  TPropData = packed record<br />    PropCount: Word;       // 属性数量<br />    PropList: record end;  // 占位符，真正的意义在下一行<br />    {PropList: array[1..PropCount] of TPropInfo}<br />  end;</font>
		</p>
		<p>
				<font size="2">每个属性信息在内存中的结构就是 TPropInfo，它的定义如下：</font>
		</p>
		<p>
				<font size="2">  PPropInfo = ^TPropInfo;<br />  TPropInfo = packed record<br />    PropType: PPTypeInfo;    // 属性类型信息指针的指针<br />    GetProc: Pointer;        // 属性的 Get 方法指针<br />    SetProc: Pointer;        // 属性的 Set 方法指针<br />    StoredProc: Pointer;     // 属性的 StoredProc 指针<br />    Index: Integer;          // 属性的 Index 值<br />    Default: Longint;        // 属性的 Default 值<br />    NameIndex: SmallInt;     // 属性的名称索引(以 0 开始计数)<br />    Name: ShortString;       // 属性的名称<br />  end;</font>
		</p>
		<p>
				<font size="2">为了方便访问属性信息，TypInfo.pas 中还定义了指向 TPropInfo 数组的指针：</font>
		</p>
		<p>
				<font size="2">  PPropList = ^TPropList;<br />  TPropList = array[0..16379] of PPropInfo;</font>
		</p>
		<p>
				<font size="2">我们可以使用 GetPropList 获得所有属性信息的指针数组，数组用完以后要记得用 FreeMem 把数组的内存清除。</font>
		</p>
		<p>
				<font size="2">{ TypInfo.pas }<br />function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): Integer;</font>
		</p>
		<p>
				<font size="2">GetPropList 传入类的 TTypeInfo 指针和 TPropList 的指针，它为 PropList 分配一块内存后把该内存填充为指向 TPropInfo 的指针数组，最后返回属性的数量。</font>
		</p>
		<p>
				<font size="2">上面的例子演示了如何获得类的所有属性信息，也可以根据属性的名称单独获得属性信息：</font>
		</p>
		<p>
				<font size="2">{ TypInfo.pas }<br />function GetPropInfo(TypeInfo: PTypeInfo; const PropName: string): PPropInfo;</font>
		</p>
		<p>
				<font size="2">GetPropInfo 根据类的 RTTI 指针和属性的名称字符串，返回属性的信息 TPropInfo 的指针。如果没有找到该属性，则返回 nil。GetPropInfo 很容易使用，举个例子：</font>
		</p>
		<p>
				<font size="2">  ShowMessage(GetPropInfo(TForm, 'Name')^.PropType^.Name);</font>
		</p>
		<p>
				<font size="2">这句调用显示了 TForm 类的 Name 属性的类型名称：TComponentName。</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ 获取方法(method)的类型信息<br />===========================================================</font>
		</p>
		<p>
				<font size="2">所谓方法就是以 of object 关键字声明的函数指针，下面的函数可以显示一个方法的类型信息：</font>
		</p>
		<p>
				<font size="2">procedure GetMethodTypeInfo(ATypeInfo: PTypeInfo; AStrings: TStrings);<br />type<br />  PParamData = ^TParamData;<br />  TParamData = record       // 函数参数的数据结构<br />    Flags: TParamFlags;     // 参数传递规则<br />    ParamName: ShortString; // 参数的名称<br />    TypeName: ShortString;  // 参数的类型名称<br />  end;<br />  function GetParamFlagsName(AParamFlags: TParamFlags): string;<br />  var<br />    I: Integer;<br />  begin<br />    Result := '';<br />    for I := Integer(pfVar) to Integer(pfOut) do begin<br />      if I = Integer(pfAddress) then Continue;<br />      if TParamFlag(I) in AParamFlags then<br />        Result := Result + ' ' + GetEnumName(TypeInfo(TParamFlag), I);<br />    end;<br />  end;<br />var<br />  MethodTypeData: PTypeData;<br />  ParamData: PParamData;<br />  TypeStr: PShortString;<br />  I: Integer;<br />begin<br />  MethodTypeData := GetTypeData(ATypeInfo);<br />  AStrings.Add('---------------------------------');<br />  AStrings.Add('Method Name: ' + ATypeInfo^.Name);<br />  AStrings.Add('Method Kind: ' + GetEnumName(TypeInfo(TMethodKind),<br />    Integer(MethodTypeData^.MethodKind)));<br />  AStrings.Add('Params Count: '+ IntToStr(MethodTypeData^.ParamCount));<br />  AStrings.Add('Params List:');<br />  ParamData := PParamData(@MethodTypeData^.ParamList);<br />  for I := 1 to MethodTypeData^.ParamCount do<br />  begin<br />    TypeStr := Pointer(Integer(@ParamData^.ParamName) +<br />      Length(ParamData^.ParamName) + 1);<br />    AStrings.Add(Format('  [%s] %s: %s',[GetParamFlagsName(ParamData^.Flags),<br />      ParamData^.ParamName, TypeStr^]));<br />    ParamData := PParamData(Integer(ParamData) + SizeOf(TParamFlags) +<br />      Length(ParamData^.ParamName) + Length(TypeStr^) + 2);<br />  end;<br />  if MethodTypeData^.MethodKind = mkFunction then<br />    AStrings.Add('Result Value: ' + PShortString(ParamData)^);<br />end;</font>
		</p>
		<p>
				<font size="2">作为实验，在表单上放置一个 TListBox，然后执行以下代码，观察执行结果：</font>
		</p>
		<p>
				<font size="2">type<br />  TMyMethod = function(A: array of Char; var B: TObject): Integer of object;<br />procedure TForm1.FormCreate(Sender: TObject);<br />begin<br />  GetMethodTypeInfo(TypeInfo(TMyMethod), ListBox1.Items);<br />  GetMethodTypeInfo(TypeInfo(TMouseEvent), ListBox1.Items);<br />  GetMethodTypeInfo(TypeInfo(TKeyPressEvent), ListBox1.Items);<br />  GetMethodTypeInfo(TypeInfo(TMouseWheelEvent), ListBox1.Items);<br />end;</font>
		</p>
		<p>
				<font size="2">由于获取方法的类型信息比较复杂，我尽量压缩代码也还是有这么长，让我们看看它的实现原理。GetMethodTypeInfo 的第一个参数是 PTypeInfo 类型，表示方法的类型信息地址。第二个参数是一个字符串列表，可以使用任何实现 TStrings 操作的对象。我们可以使用 System.pas 中的 TypeInfo 函数获得任何类型的 RTTI 信息指针。TypeInfo 函数像 SizeOf 一样，是内置于编译器中的。</font>
		</p>
		<p>
				<font size="2">GetMethodTypeInfo 还用到了 TypInfo.pas 中的 GetEnumName 函数。这个函数通过枚举类型的整数值得到枚举类型的名称。</font>
		</p>
		<p>
				<font size="2">function GetEnumName(TypeInfo: PTypeInfo; Value: Integer): string;</font>
		</p>
		<p>
				<font size="2">与获取类(class)的属性信息类似，方法的类型信息也在 TTypeData 结构中</font>
		</p>
		<p>
				<font size="2">  TTypeData = packed record<br />    case TTypeKind of<br />      tkMethod: (<br />        MethodKind: TMethodKind;            // 方法指针的类型<br />        ParamCount: Byte;                   // 参数数量<br />        ParamList: array[0..1023] of Char   // 参数详细信息，见下行注释<br />       {ParamList: array[1..ParamCount] of<br />          record<br />            Flags: TParamFlags;             // 参数传递规则 <br />            ParamName: ShortString;         // 参数的名称<br />            TypeName: ShortString;          // 参数的类型<br />          end;<br />        ResultType: ShortString});          // 返回值的名称<br />  end;</font>
		</p>
		<p>
				<font size="2">TMethodKind 是方法的类型，定义如下：</font>
		</p>
		<p>
				<font size="2">  TMethodKind = (mkProcedure, mkFunction, mkConstructor, mkDestructor,<br />    mkClassProcedure, mkClassFunction,<br />    { Obsolete }<br />    mkSafeProcedure, mkSafeFunction);</font>
		</p>
		<p>
				<font size="2">TParamsFlags 是参数传递的规则，定义如下：</font>
		</p>
		<p>
				<font size="2">  TParamFlag = (pfVar, pfConst, pfArray, pfAddress, pfReference, pfOut);<br />  TParamFlags = set of TParamFlag;</font>
		</p>
		<p>
				<font size="2">由于 ParamName 和 TypeName 是变长字符串，不能直接取用该字段的值，而应该使用指针步进的方法，取出参数信息，所以上面的代码显得比较长。</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ 获取有序类型(ordinal)、集合(set)类型的 RTTI 信息<br />===========================================================</font>
		</p>
		<p>
				<font size="2">讨论完了属性和方法的 RTTI 信息之后再来看其它数据类型的 RTTI 就简单多了。所有获取 RTTI 的原理都是通过 GetTypeData 函数得到 TTypeData 的指针，再通过 TTypeInfo.TypeKind 来解析 TTypeData。任何数据类型的 TTypeInfo 指针可以通过 TypeInfo 函数获得。</font>
		</p>
		<p>
				<font size="2">有序类型的 TTypeData 定义如下：</font>
		</p>
		<p>
				<font size="2">TTypeData = packed record<br />  tkInteger, tkChar, tkEnumeration, tkSet, tkWChar: (<br />    OrdType: TOrdType;         // 有序数值类型<br />    case TTypeKind of<br />      case TTypeKind of<br />        tkInteger, tkChar, tkEnumeration, tkWChar: (<br />          MinValue: Longint;   // 类型的最小值<br />          MaxValue: Longint;   // 类型的最大值<br />          case TTypeKind of<br />            tkInteger, tkChar, tkWChar: ();<br />            tkEnumeration: (<br />              BaseType: PPTypeInfo;      // 指针的指针，它指向枚举的 PTypeInfo<br />              NameList: ShortStringBase;     // 枚举的名称字符串(不能直接取用)<br />              EnumUnitName: ShortStringBase)); // 所在的单元名称(不能直接取用)<br />          tkSet: (<br />            CompType: PPTypeInfo));            // 指向集合基类 RTTI 指针的指针<br />end;</font>
		</p>
		<p>
				<font size="2">下面是一个获取有序类型和集合类型的 RTTI 信息的函数：</font>
		</p>
		<p>
				<font size="2">procedure GetOrdTypeInfo(ATypeInfo: PTypeInfo; AStrings: TStrings);<br />var<br />  OrdTypeData: PTypeData;<br />  I: Integer;<br />begin<br />  OrdTypeData := GetTypeData(ATypeInfo);<br />  AStrings.Add('------------------------------------');<br />  AStrings.Add('Type Name: ' + ATypeInfo^.Name);<br />  AStrings.Add('Type Kind: ' + GetEnumName(TypeInfo(TTypeKind),<br />    Integer(ATypeInfo^.Kind)));<br />  AStrings.Add('Data Type: ' + GetEnumName(TypeInfo(TOrdType),<br />    Integer(OrdTypeData^.OrdType)));<br />  if ATypeInfo^.Kind &lt;&gt; tkSet then begin<br />    AStrings.Add('Min Value: ' + IntToStr(OrdTypeData^.MinValue));<br />    AStrings.Add('Max Value: ' + IntToStr(OrdTypeData^.MaxValue));<br />  end;<br />  if ATypeInfo^.Kind = tkSet then<br />    GetOrdTypeInfo(OrdTypeData^.CompType^, AStrings);<br />  if ATypeInfo^.Kind = tkEnumeration then<br />    for I := OrdTypeData^.MinValue to OrdTypeData^.MaxValue do<br />      AStrings.Add(Format('  Value %d: %s', [I, GetEnumName(ATypeInfo, I)]));<br />end;</font>
		</p>
		<p>
				<font size="2">在表单上放置一个 TListBox，运行以下代码查看结果：</font>
		</p>
		<p>
				<font size="2">type TMyEnum = (EnumA, EnumB, EnumC);<br />procedure TForm1.FormCreate(Sender: TObject);<br />begin<br />  GetOrdTypeInfo(TypeInfo(Char), ListBox1.Items);<br />  GetOrdTypeInfo(TypeInfo(Integer), ListBox1.Items);<br />  GetOrdTypeInfo(TypeInfo(TFormBorderStyle), ListBox1.Items);<br />  GetOrdTypeInfo(TypeInfo(TBorderIcons), ListBox1.Items);<br />  GetOrdTypeInfo(TypeInfo(TMyEnum), ListBox1.Items);<br />end;</font>
		</p>
		<p>
				<font size="2">(如果枚举元素没有按缺省的 0 基准定义，那么将不能产生 RTTI 信息，为什么？)</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ 获取其它数据类型的 RTTI 信息<br />===========================================================</font>
		</p>
		<p>
				<font size="2">上面讨论了几个典型的 RTTI 信息的运行，其它的数据类型的 RTTI 信息的获取方法与上面类似。由于这些操作更加简单，就不一一讨论。下面概述其它类型的 RTTI 信息的情况：</font>
		</p>
		<p>
				<font size="2">LongString、WideString 和 Variant 没有 RTTI 信息；<br />ShortString 只有 MaxLength 信息；<br />浮点数类型只有 FloatType: TFloatType 信息；<br />  TFloatType = (ftSingle, ftDouble, ftExtended, ftComp, ftCurr);<br />Int64 只有最大值和最小值信息(也是 64 位整数表示)；<br />Interface 和动态数组不太熟悉，就不作介绍了。</font>
		</p>
		<p>
				<font size="2">===========================================================<br />⊙ 结束<br />==========================================================</font>
		</p>
<img src ="http://www.cnitblog.com/flyinggoal/aggbug/7754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flyinggoal/" target="_blank">风筝</a> 2006-03-18 17:38 <a href="http://www.cnitblog.com/flyinggoal/archive/2006/03/18/7754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>