Delphi 的持续机制浅探_第1页
Delphi 的持续机制浅探_第2页
Delphi 的持续机制浅探_第3页
Delphi 的持续机制浅探_第4页
Delphi 的持续机制浅探_第5页
已阅读5页,还剩21页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

问题DELPHI的持续机制浅探积分100,回复10,阅读237分类OBJECTPASCAL版主MENXIN,CAKK来自SAVETIME,时间200412442200,ID2421751显示小字体|大字体DELPHI的持续机制浅探SAVETIME2KYAHOOCOM2004124HTTP/SAVETIMEDELPHIBBSCOM目录DFM文件与持续机制PERSISTENTREADCOMPONENTRESFILE/WRITECOMPONENTRESFILE函数DELPHI持续机制框架简述一个TFORM对象的创建过程TSTREAMCLASS和TSTREAMREADCOMPONENT方法TREADERCLASS和TREADERREADROOTCOMPONENT方法TREADERREADPREFIX方法TCOMPONENTREADSTATE虚方法TREADERREADDATA方法TREADERREADDATAINNER方法TREADERREADPROPERTY方法TPERSISTENTDEFINEPROPERTIES虚方法TREADERREADCOMPONENT方法TREADERREADVALUE/TREADERNEXTVALUE系列方法TREADERREADSTR方法TREADERREADINTEGER/READSTRING/READBOOLEAN系列方法TREADERREAD方法OBJECTBINARYTOTEXT/OBJECTTEXTTOBINARY函数本文排版格式为正文由窗口自动换行;所有代码以80字符为边界;中英文字符以空格符分隔。作者保留对本文的所有权利,未经作者同意请勿在在任何公共媒体转载。正文DFM文件与持续机制PERSISTENT我们在使用DELPHI的IDE进行快速开发的时候,可以方便地从元件面板上拖放元件COMPONENT至表单,完成表单的界面和事件设计。DELPHI将这些界面的设计期信息保存在表单相应的DFM文件中,方便程序员随时读取和修改。DFM文件根据元件在表单上的嵌套层次存放元件属性,以下是一个DFM文件的示例OBJECTFORM1TFORM1LEFT192TOP107WIDTH544CAPTIONFORM1OBJECTBUTTON1TBUTTONLEFT24TOP16CAPTIONBUTTON1ONCLICKBUTTON1CLICKENDEND应用程序编译之后,DFM文件的信息被二进制化了,这些二进制信息存储在应用程序的资源RESOURCE段中。每个表单也就是CLASS及表单上的元件在资源段中存储为与表单同名的资源,可以使用FINDRESOURCEAPI获得。应用程序在运行期创建表单实例的时候,会从资源段中读取表单的属性,还原设计期的设置。这种将类型信息保存在文件中,并且可以在运行期恢复类型的操作,在本文中被称之为持续PERSISTENT机制。持续机制是DELPHI成为RAD工具的原因之一。持续机制和RTTI是紧密结合的,但本文不讨论RTTI关于RTTI可参考我前几天写的两篇笔记,只讨论实现持续机制的总体框架及相关类CLASS。这些类包括TSTREAM、TFILER、TREADER、TWRITER、TPARSER、TPERSISETENT、TCOMPONENT、TCUSTOMFORM等。READCOMPONENTRESFILE/WRITECOMPONENTRESFILE函数让我们从一个比较直观的例子开始。CLASSESPAS中定义了两个函数READCOMPONENTRESFILE和WRITECOMPONENTRESFILE,它们的功能是“把元件的属性信息保存到文件”和“从文件中恢复元件属性信息”。先做个试验。新建一个项目,在FORM1上放置两个BUTTON和一个MEMO。BUTTON的CLICK事件代码如下。按F9运行该项目,先在MEMO1中输入一些字符,然后按下BUTTON1,再按下BUTTON2,你会看一个新建的FORM。它的属性几乎和FORM1一样,甚至连MEMO1中的字符都保存下来了,唯一的不同只是它的NAME属性变成了“FORM1_1”。你可以查看FORM1RES文件的内容看看DELPHI是如何存储元件信息的。PROCEDURETFORM1BUTTON1CLICKSENDERTOBJECTBEGINWRITECOMPONENTRESFILECFORM1RES,FORM1ENDPROCEDURETFORM1BUTTON2CLICKSENDERTOBJECTVARNEWFORMTFORM1BEGINNEWFORMTFORM1CREATENEWAPPLICATIONREADCOMPONENTRESFILECFORM1RES,NEWFORMNEWFORMLEFTNEWFORMLEFT100ENDWRITECOMPONENTRESFILE函数的代码如下,它只是调用STREAM对象的WRITECOMPONENTRES方法将对象属性保存到资源文件中的PROCEDUREWRITECOMPONENTRESFILECONSTFILENAMESTRINGINSTANCETCOMPONENTBEGINSTREAMTFILESTREAMCREATEFILENAME,FMCREATESTREAMWRITECOMPONENTRESINSTANCECLASSNAME,INSTANCESTREAMFREEENDREADCOMPONENTRESFILE函数也是调用STREAM的方法实现从文件中读取对属信息FUNCTIONREADCOMPONENTRESFILECONSTFILENAMESTRINGINSTANCETCOMPONENTTCOMPONENTBEGINSTREAMTFILESTREAMCREATEFILENAME,FMOPENREADORFMSHAREDENYWRITERESULTSTREAMREADCOMPONENTRESINSTANCESTREAMFREEENDREADCOMPONENTRESFILE函数可以通过INSTANCE参数传入对象句柄,也可以通过返回值获得对象句柄。INSTANCE参数只能是已实例化的对象或NIL。如果是NIL,那么READCOMPONENTRESFILE会自动根据文件信息创建对象实例,但必须使用REGISTERCLASS函数注册将要被载入的类,否则会触发异常。有个类似的函数READCOMPONENTRES,它从应用程序的资源段中恢复对象的属性信息。它的RESNAME参数就是表单类的名称FUNCTIONREADCOMPONENTRESCONSTRESNAMESTRINGINSTANCETCOMPONENTTCOMPONENTDELPHI持续机制框架简述持续机制的实现必须由IDE、编译器、表单类、元件类和辅助类合作完成。这里的表单类不是指一般所指的TFORMCLASS,在DELPHI的帮助文件中,称之为“ROOTCLASS”。ROOTCLASS是指能在设计期被FORMDESIGNER作为最上层编辑表单的类如TCUSTOMFORM、TFRAME、TDATAMODULE等。DELPHI在设计期将元件的PUBLISHED属性的值保存在DFM文件中,也只有PUBLISHED的属性才能被OBJECTINSEPECTOR设置赋值。FORMDESIGNER设计的ROOTCLASS对象在编译时,DELPHI将对象的属性以及其所包含的元件的属性保存在应用程序的资源段RT_RCDATA中。辅助类包括TSTREAM、TREADER、TWRITER、TPARSER等。这些类起着中间层的作用,用于存储和读取对象属性的信息。虽然我称它们为辅助类,但是保存和恢复对象信息的实际操作是由它们完成的。一个TFORM对象的创建过程下面是一个典型的表单FORM1的创建过程,缩进代表调用关系FORM1READSTATE例外,防止缩进太多,带“”的函数表示我尚未仔细考察的部分,带“”表示元件编写者需要注意的函数。APPLICATIONCREATEFORMTFORM1,FORM1|FORM1NEWINSTANCE|FORM1CREATEAPPLICATION|FORM1CREATENEWAPPLICATION|INITINHERITEDCOMPONENTFORM1,TFORM|INTERNALREADCOMPONENTRESFORM1CLASSNAME,FORM1RESHINST,FORM1|TRESOURCESTREAMCREATEFORM1RESHINST,FORM1CLASSNAME,RT_RCDATA|TRESOURCESTREAMREADCOMPONENTFORM1|TREADERCREATERESOURCESTREAM,4096|TREADERREADROOTCOMPONENTFORM1|TREADERREADSIGNATURE|TREADERREADPREFIXFLAGS,CHILDPOS|IFFORM1NILTHENFORM1FINDCLASSREADSTRCREATE|INCLUDEFORM1FCOMPONENTSTATE,CSLOADING|INCLUDEFORM1FCOMPONENTSTATE,CSREADING|FORM1NAMEFINDUNIQUENAMEREADSTR|FFINDERTCLASSFINDERCREATE|FORM1READSTATEREADER|TCUSTOMFORMREADSTATEREADERDISABLEALIGN|TWINCONTROLREADSTATEREADERDISABLEALIGN|TCONTROLREADSTATEREADERINCLUDEFCONTROLSTATE,CSREADINGSTATEPARENTTWINCONTROLREADERPARENT|TCOMPONENTREADSTATEREADER|READERREADDATAFORM1|READERREADDATAINNERFORM1|WHILENOTENDOFLISTDOREADERREADPROPERTYFORM1|IFPROPINFONILTHENREADPROPVALUEFORM1,PROPINFO|ELSEFORM1DEFINEPROPERTIESREADER|WHILENOTENDOFLISTDOREADCOMPONENTNIL|READPREFIXFLAGS,POSITION|IFFFINHERITEDTHENFINDEXISTINGCOMPONENT|ELSECREATECOMPONENT|SUBCOMPONENTREADSTATEREADERLIKEFORM1READSTATE|DOFIXUPREFERENCES过程简述TCUSTOMFORMCREATE函数中先调用CREATENEW设置缺省的表单属性,然后调用CLASSESINITINHERITEDCOMPONENT函数。INITINHERITEDCOMPONENT用于初始化一个ROOTCLASS对象。该函数的功能就是从应用程序的资源中恢复设计期的表单信息。INITINHERITEDCOMPONENT的声明如下CLASSESPASFUNCTIONINITINHERITEDCOMPONENTINSTANCETCOMPONENTROOTANCESTORTCLASSBOOLEANINITINHERITEDCOMPONENT传入两个参数INSTANCE参数代表将要从资源段中恢复信息的对象,ROOTANCESTOR表示该对象的祖先类。如果从资源中恢复信息成功,则返回TRUE,否则返回FALSE。INITINHERITEDCOMPONENT通常只在ROOTCLASS的构造函数中调用。CONSTRUCTORTCUSTOMFORMCREATEAOWNERTCOMPONENTBEGINCREATENEWAOWNER/初始化缺省的FORM属性INCLUDEFFORMSTATE,FSCREATING/标记为CREATING状态IFNOTINITINHERITEDCOMPONENTSELF,TFORMTHEN/从资源中恢复FORM信息RAISEERESNOTFOUNDCREATEFMTSRESNOTFOUND,CLASSNAMEEXCLUDEFFORMSTATE,FSCREATING/取消CREATING状态ENDINITINHERITEDCOMPONENT调用自身内置的函数INITCOMPONENTINSTANCECLASSTYPE。INITCOMPONENT先判断INSTANCECLASSTYPE是否是TCOMPONENT或ROOTANCESTOR,如果是则返回FALSE并退出,否则调用INTERNALREADCOMPONENTRES。INITCOMPONENT递归调用自己检查类信息。没看懂为什么要这样设计,如果有谁看懂了请告诉我。FUNCTIONINITCOMPONENTCLASSTYPETCLASSBOOLEANBEGINRESULTFALSEIFCLASSTYPETCOMPONENTORCLASSTYPEROOTANCESTORTHENEXITRESULTINITCOMPONENTCLASSTYPECLASSPARENTRESULTINTERNALREADCOMPONENTRESCLASSTYPECLASSNAME,FINDRESOURCEHINSTANCEFINDCLASSHINSTANCECLASSTYPE,INSTANCEORRESULTENDINTERNALREADCOMPONENTRES使用INSTANCECLASSNAME作为RESOURCENAME,调用FINDRESOURCEHINSTANCE找到CLASS资源所在模块的HINST句柄因为CLASS可能是在动态链接库中,并通过引用方式传递INSTANCE对象好像没有必要使用引用方式,INITINHERITEDCOMPONENT也没有使用引用方式CLASSESPASFUNCTIONINTERNALREADCOMPONENTRESCONSTRESNAMESTRINGHINSTTHANDLEVARINSTANCETCOMPONENTBOOLEANINTERNALREADCOMPONENTRES先检查CLASS资源是否存在,如果存在则创建一个TRESOURCESTREAM对象TRESOURCESTREAM的CREATE构造函数把CLASS信息的资源内存地址和大小记录在成员字段中,然后使用TRESOURCESTREAMREADCOMPONENT方法从资源中读取INSTANCE的信息。TRESOURCESTREAM并没有定义READCOMPONENT方法,而是使用祖先类TSTREAM的方法。TSTREAMREADCOMPONENT创建一个TREADER对象,然后使用自己的对象地址SELF作为参数,调用TREADERREADROOTCOMPONENT读取INSTANCE对象的内容。TREADERFUNCTIONREADROOTCOMPONENTROOTTCOMPONENTTCOMPONENTREADROOTCOMPONENT先调用TREADERREADSIGNATURE。READSIGNATURE从STREAM中读取4字节的内容,如果读出来的内容不是TPF0,则触发异常SINVALIDIMAGE,表示该STREAM的内容是错误的。然后READROOTCOMPONENT调用READPREFIX读取元件的状态信息。如果ROOT参数是NIL,也就是说ROOT对象还没被创建,则直接从流中读取ROOT的类名,再使用FINDCLASS函数找到该类在内存中的地址,并调用该类的构造函数创建ROOT的实例。接下来READROOTCOMPONENT调用ROOT的READSTATE虚函数从流中读取ROOT对象的属性。TCOMPONENTREADSTATE只有一行代码READERREADDATASELF。READDATA调用READDATAINNER读取ROOT元件及ROOT的子元件的属性信息。READDATAINNER先循环调用READPROPERTY从流中读取ROOT元件的属性,直到遇到ENDOFLIST标志VANULL。READPROPERTY使用RTTI函数,将从流中读出的数据设置为对象的属性。READPROPERTY中还调用了INSTANCEDEFINEPROPERTIES,用于实现自定义的属性存储。READDATAINNER然后循环调用READCOMPONENTNIL读取子元件的信息。READCOMPONENT的执行过程与READROOTCOMPONENT的过程很相似,它根据流中的信息使用FINDCOMPONENTCLASS找到元件类在内存中的地址,然后调用该元件类的构造函数创建对象,接下来调用新建对象的READSTATETREADERREADDATAREADDATAINNERTREADERREADPROPERTY,重复READROOTCOMPONENT的过程。TREADERREADCOMPONENT和TCOMPONENTREADSTATE形成递归调用过程,把表单上嵌套的元件创建出来。最后INITINHERITEDCOMPONENT函数返回,一个ROOTCLASS对象从资源中实例化的过程完成。TSTREAMCLASS和TSTREAMREADCOMPONENT方法TSTREAM在对象持续机制扮演的角色是提供一种存储媒介,由TFILER对象使用。TSTREAM是一个虚类,它定义了数据的“流式”读写方法。它的继承类TFILESTREAM、TMEMORYSTREAM、TRESOURCESTREAM等实现对不同媒体的读写。对象的PERSISTENT信息可以存储在任何TSTREAM类中,也可以从任何TSTREAM中获得。由于DELPHI缺省的对象信息存储在应用程序的资源段中,因此,可以从程序的资源段中读取数据的TRESOURCESTREAM类就显得更加重要。TSTREAM定义两个读写缓冲的方法READBUFFER和WRITEBUFFER。这两个方法封装了TSTREAMREAD和TSTREAMWRITE纯虚方法必须被后继类重载。TSTREAMPROCEDUREREADBUFFERVARBUFFERCOUNTLONGINTPROCEDUREWRITEBUFFERCONSTBUFFERCOUNTLONGINT可以看到这两个方法的BUFFER参数都是无类型的,也就是使用引用的方式传入的,所以不管是使用单个字符或自定义的结构都是正确的当然,不能使用常量。COUNT指示要读或写入的BUFFER的大小BYTES。TSTREAM还定义了两个元件信息的读写方法READCOMPONENT和WRITECOMPONENT。由于WRITECOMPONENT通常是由DELPHI的IDE/编译器调用的,很难跟踪它的执行过程,所以我们以后主要考察READCOMPONENT方法。我们可以很容易想像这两个方法互为逆过程,理解了其中一个也就能知道另一个所做的工作。TSTREAMFUNCTIONREADCOMPONENTINSTANCETCOMPONENTTCOMPONENTPROCEDUREWRITECOMPONENTINSTANCETCOMPONENTTSTREAMREADCOMPONENT创建了一个TREADER对象,将自己的对象地址作为参数传递给READER,并调用READERREADROOTCOMPONENT创建对象实例。FUNCTIONTSTREAMREADCOMPONENTINSTANCETCOMPONENTTCOMPONENTVARREADERTREADERBEGINREADERTREADERCREATESELF,4096/4096是缓冲区大小RESULTREADERREADROOTCOMPONENTINSTANCEREADERFREEENDTSTREAM把自己的对象句柄交给TREADER之后,就成了TREADER读取对象属性资料的来源。此后TSTREAM对象只由TREADER来掌控,自己不再主动进行其它工作。TREADERCLASS和TREADERREADROOTCOMPONENT方法TREADER和TWRITER都是从TFILER继承下来的类。TFILER是个纯虚类,它的构造函数被TREADER和TWRITE共享。TFILERCREATE先把STREAM参数保存在FSTREAM字段中,然后生成一个自己的缓冲区CONSTRUCTORTFILERCREATESTREAMTSTREAMBUFSIZEINTEGERBEGINFSTREAMSTREAM/保存STREAM对象GETMEMFBUFFER,BUFSIZE/创建自己的缓冲区,加速数据访问FBUFSIZEBUFSIZE/设置缓冲区大小END上面说到TSTREAMREADCOMPONENT在创建TREADER对象之后,立即调用TREADERREADROOTCOMPONENT方法。TREADERREADROOTCOMPONENT方法的功能是从STREAM中读取ROOTCLASS对象的属性。并返回该对象的指针。TREADERFUNCTIONREADROOTCOMPONENTROOTTCOMPONENTTCOMPONENTREADROOTCOMPONENT先调用TREADERREADSIGNATURE。TREADERREADSIGNATURE方法从STREAM中读取4字节的内容,如果读出来的内容不是TPF0,则触发异常SINVALIDIMAGE,表示该STREAM的内容是错误的。TPF0就是ROOTCLASS对象的标记。然后READROOTCOMPONENT调用READPREFIX读取元件的继承信息。如果ROOT参数是NIL,也就是说ROOT对象还没被创建,则直接从流中读取ROOT的类名,再使用FINDCLASS函数找到该类在内存中的地址,并调用该类的构造函数创建ROOT的实例。如果ROOT实例已存在,则调用内嵌的FINDUNIQUNAME函数检查ROOTNAME是否与已有的实例重复,如有重复则在ROOTNAME后加上序号使其唯一。接下来READROOTCOMPONENT调用ROOT的READSTATE虚方法从流中读取ROOT对象的属性。TREADERREADPREFIX方法READPREFIX方法用于读取元件的状态信息,这些信息是由WRITER在写入元件属性之前写入的。TREADERPROCEDUREREADPREFIXVARFLAGSTFILERFLAGSVARACHILDPOSINTEGERVIRTUALFLAGS参数是以引用方式传递的,用于设置元件的在表单中的状态,元件的状态在这里包含三种情况FFINHERITED表示元件存在于表单的父类之中FFCHILDPOS表示元件在表单中的创建次序CREATIONORDER是重要的FFINLINE表示元件是最上级TOPLEVEL的元件,比如表单或数据模块如果元件的状态中包含FFCHILDPOS,READPREFIX还会读取元件的创建次序值,存放在ACHILDPOS参数中。TCOMPONENTREADSTATE虚方法设置READSTATE方法的主要目的是在读取属性信息的前后可以让元件进行一些处理工作。READSTATE是COMPONENTWRITER需要注意的方法。TCOMPONENTPROCEDUREREADSTATEREADERTREADERVIRTUAL由于READSTATE是虚函数,在TCONTROL、TWINCONTROL、TCUSTOMFORM等后续类中都被重载,进行自己需要的操作比如DISABLEALIGN、UPDATECONTROLSTATE。TCOMPONENTREADSTATE只有一行代码READERREADDATASELF注意自己重载READSTATE方法必须调用INHERITED。TREADERREADDATA方法上面说到TCOMPONENTREADSTATE又回头调用TREADERREADDATA方法。它的主要代码如下TREADERPROCEDURETREADERREADDATAINSTANCETCOMPONENTBEGINREADDATAINNERINSTANCEDOFIXUPREFERENCESENDTREADERREADDATA基本上是个包装函数,它调用TREADERREADDATAINNER读取ROOT对象及ROOT所包含的元件的属性信息。TREADERREADDATAINNER方法READDATAINNER负责读取元件的属性和子元件的属性,它的主要代码如下PROCEDURETREADERREADDATAINNERINSTANCETCOMPONENTBEGINWHILENOTENDOFLISTDOREADPROPERTYINSTANCEWHILENOTENDOFLISTDOREADCOMPONENTNILENDREADDATAINNER先循环调用READPROPERTY从流中读取对象的属性,直到遇到ENDOFLIST标志VANULL。再循环调用READCOMPONENTNIL读取子元件的信息。这两个方法都是TREADER的重要方法,后面分两节讨论。READDATAINNER在READPROPERTY调用之后还设置了元件的PARENT和OWNER关系。TREADERREADPROPERTY方法READPROPERTY使用RTTI函数将从流中读出的数据设置为对象的属性。它先解析从流中读出的属性名称,然后判断该属性是否有RTTI信息,如果有则调用TREADERREADPROPVALUE方法从流中读取属性值;如果该属性没有RTTI信息,说明该属性不属于PUBLISHED段,而是由元件自己写入的,因此调用TPERSISTENTDEFINEPROPERTIES读取自定义的元件信息。READPROPERTY的关键代码PROCEDURETREADERREADPROPERTYAINSTANCETPERSISTENTBEGINPROPINFOGETPROPINFOINSTANCECLASSINFO,FPROPNAMEIFPROPINFONILTHEN/检查属性RTTI信息READPROPVALUEINSTANCE,PROPINFO/从流中读取属性ELSEBEGININSTANCEDEFINEPROPERTIESSELF/调用自定义存储过程IFFPROPNAMETHENPROPERTYERRORFPROPNAME/注意这里ENDENDREADPROPVALUE方法基本上是使用SETORDPROP、SETFLOATPROP、SETSTRPROP、GETENUMVALUE等RTTI函数设置元件的属性值,它的代码冗长而简单,不再单独列出。下面介绍比较重要的DEFINEPROPERTIES函数。TPERSISTENTDEFINEPROPERTIES虚方法DEFINEPROPERTIES虚方法用于元件设计者自定义非PUBLISHED属性的存储和读取方法。TPERSISTENT定义的该方法是个空方法,到TCOMPONENT之后被重载。PROCEDURETPERSISTENTDEFINEPROPERTIESFILERTFILERVIRTUAL下面以TCOMPONENT为例说明该方法的用法PROCEDURETCOMPONENTDEFINEPROPERTIESFILERTFILERVARANCESTORTCOMPONENTINFOLONGINTBEGININFO0ANCESTORTCOMPONENTFILERANCESTORIFANCESTORNILTHENINFOANCESTORFDESIGNINFOFILERDEFINEPROPERTYLEFT,READLEFT,WRITELEFT,LONGRECFDESIGNINFOLOLONGRECINFOLOFILERDEFINEPROPERTYTOP,READTOP,WRITETOP,LONGRECFDESIGNINFOHILONGRECINFOHIENDDEFINEPROPERTIES调用FILERDEFINEPROPERTY或DEFINEBINARYPROPERTY方法读写流中属性值。TREADERDEFINEPROPERTY方法检查传入的属性名称是否与当前流中读到的属性名称相同,如果相同,则调用传入的READDATA方法读取数据,并设置FPROPNAME为空,用以通知READPROPERTY已经完成读属性值的工作,否则将会触发异常。PROCEDURETREADERDEFINEPROPERTYCONSTNAMESTRINGREADDATATREADERPROCWRITEDATATWRITERPROCHASDATABOOLEANBEGINIFSAMETEXTNAME,FPROPNAMEANDASSIGNEDREADDATATHENBEGINREADDATASELFFPROPNAMEENDENDTWRITERDEFINEPROPERTY根据HASDATA参数决定是否需要写属性值。PROCEDURETWRITERDEFINEPROPERTYCONSTNAMESTRINGREADDATATREADERPROCWRITEDATATWRITERPROCHASDATABOOLEANBEGINIFHASDATAANDASSIGNEDWRITEDATATHENBEGINWRITEPROPNAMENAMEWRITEDATASELFENDEND如果FILERANCESTOR不是NIL,表示当前正在读取的元件继承自表单父类中的元件,元件设计者可以根据ANCESTOR判断是否需要写属性至流中。例如当前元件的属性值与原表单类中的元件属性值相同的时候,可以不写入通常是这样设计。READDATA、WRITEDATA参数是从FILER对象中读写数据的方法地址,它们的类型是TREADERPROCPROCEDUREREADERTREADEROFOBJECTTWRITERPROCPROCEDUREWRITERTWRITEROFOBJECT比如PROCEDURETCOMPONENTREADLEFTREADERTREADERBEGINLONGRECFDESIGNINFOLOREADERREADINTEGERENDPROCEDURETCOMPONENTWRITELEFTWRITERTWRITERBEGINWRITERWRITEINTEGERLONGRECFDESIGNINFOLOEND对于二进制格式的属性值,可以使用TFILERDEFINEBINARYPROPERTY方法读写PROCEDUREDEFINEBINARYPROPERTYCONSTNAMESTRINGREADDATA,WRITEDATATSTREAMPROCHASDATABOOLEANOVERRIDETSTREAMPROCPROCEDURESTREAMTSTREAMOFOBJECTSTREAM参数是从流中读出的二进制数据或要写入二进制数据的流对象句柄。注意自己定义属性的读写方法时要记得调用INHERITEDDEFINEPROPERTIESFILER,否则祖先类的自定义属性读写操作不会进行。TCONTROL是个例外,因为它已经定义了PUBLISHEDLEFT和TOP属性。TREADERREADCOMPONENT方法READCOMPONENT的执行过程与READROOTCOMPONENT的过程很相似,它根据流中的信息使用FINDCOMPONENTCLASS方法找到元件类在内存中的地址,然后调用该元件类的构造函数创建对象,接下来调用新建对象的READSTATETREADERREADDATAREADDATAINNERTREADERREADPROPERTY,重复READROOTCOMPONENT的过程。TREADERFUNCTIONREADCOMPONENTCOMPONENTTCOMPONENTTCOMPONENTTREADERREADCOMPONENT和TCOMPONENTREADSTATE形成递归调用过程,把表单上嵌套的元件创建出来。TREADERREADVALUE/TREADERNEXTVALUE系列方法READVALUE方法从流中读出一个TVALUETYPE类型的数据,它主要由其它的方法调用。TVALUETYPE中只有VALIST比较特殊,它表示后面的数据是一个属性值系列,以VANULL结束。其余的枚举值的都是指属性的数据类型或值。TVALUETYPEVANULL,VALIST,VAINT8,VAINT16,VAINT32,VAEXTENDED,VASTRING,VAIDENT,VAFALSE,VATRUE,VABINARY,VASET,VALSTRING,VANIL,VACOLLECTION,VASINGLE,VACURRENCY,VADATE,VAWSTRING,VAINT64,VAUTF8STRINGFUNCTIONTREADERREADVALUETVALUETYPEBEGINREADRESULT,SIZEOFRESULTENDNEXTVALUE方法调用READVALUE返回流中下一个数据的类型,然后将流指针回退至读数据之前。通常用于检测流中下一个数据的类型。FUNCTIONTREADERNEXTVALUETVALUETYPEBEGINRESULTREADVALUEDECFBUFPOSENDCHECKVALUE方法调用READVALUE检查下一个数据类型是否是指定的类型,如果不是则触发异常。READLISTBEGIN方法检查下一个数据是否是VALIST,它调用CHECKVALUE方法。READLISTEND方法检查下一个数据是否是VANULL,它调用CHECKVALUE方法。SKIPVALUE方法使用READVALUE获得下一个数据的类型,然后将流指针跳过这个数据。TREADERREADSTR方法READSTR方法读出流中的短字符串,TREADER内部使用它读取属性名称等字符串,元件设计者应该使用READSTRING函数读取属性值。FUNCTIONREADSTRSTRINGTREADERREADINTEGER/READSTRING/READBOOLEAN系列方法TREADER有一系列读取属性值的函数,可供元件设计者使用。FUNCTIONREADINTEGERLONGINTFUNCTIONREADINT64INT64FUNCTIONREADBOOLEANBOOLEANFUNCTIONREADCHARCHARPROCEDUREREADCOLLECTIONCOLLECTIONTCOLLECTIONFUNCTIONREADFLOATEXTENDEDFUNCTIONREADSINGLESINGLEFUNCTIONREADCURRENCYCURRENCYFUNCTIONREADDATETDATETIMEFUNCTIONREADIDENTSTRINGFUNCTIONREADSTRINGSTRINGFUNCTIONREADWIDESTRINGWIDESTRINGFUNCTIONREADVARIANTVARIANTTREADERREAD方法TREADER中所有的数据都是通过TREADERREAD方法读取的。TREADER不直接调用TSTREAM的读方法是因为TREADER的读数据操作很频繁,它自己建立了一个缓冲区4K,只有当缓冲区中的数据读完之后才会调用TSTREAMREAD再读入下一段数据,这样可以极大地加快读取速度。READ是个汇编函数,编写得很巧妙,它的代码及注释如下PROCEDURETREADERREADVARBUFCOUNTLONGINTASSEMBLERASMPUSHESIPUSHEDIPUSHEBXMOVEDI,EDXEDIFBUFPOSJMP2JA2MOVEAX,ESIELSEEAXSELFCALLTREADERREADBUFFERCALLREADBUFFERMOVECX,ESITREADERFBUFENDECXFBUFEND2检查要读出的数量是否超过缓冲区大小,如是则分批读取2CMPECX,EBXIFFBUFENDCOUNTJMP3JB3MOVECX,EBXELSEECXCOUNT3分批读取缓冲区3PUSHESISUBEBX,ECXCOUNTCOUNTFBUFENDMOVEAX,ESITREADERFBUFFEREAXFBUFFERADDEAX,ESITREADERFBUFPOSEAXFBUFFERFBUFPOSADDESITREADERFBUFPOS,ECXFBUFPOSFBUFPOSFBUFENDMOVESI,EAXESICURRFBUFFERADDRMOVEDX,ECXEDXFBUFENDSHRECX,2ECXFBUFEND/4CLDREPMOVSDCOPYBUF

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论