当前位置:   article > 正文

Mastering Delphi7 阅读笔记(摘要) 续_delphi7 ipersiststreaminit 引用

delphi7 ipersiststreaminit 引用

 第12章  从COM到COM+
  本章主要内容
   OLE和COM技术历史简介
   实现IUnknown
   第一个COM服务器
   自动化
   编写一个自动化服务器
   使用复合文档
   介绍AxtiveX控件
   编写ActiveX控件
   介绍COM+
   Delphi 7中的COM和.NET
  
  OLE和COM技术历史简介
   所有以对象链接和嵌入(OLE)技术开发的部件,都是动态数据交换(DDE)模型的扩展,使用Clipboard可以为用户提供拷贝原始数据的功能,而使用DDE技术则允许用户将两份文件中的部分数据连接起来,OEL允许用户从服务器应用程序中将数据复制到客户应用程序中,其中包括那些与服务器相关的数据,或其它一些保存于Windows注册表中的引用信息.原始数据有可能会与其链接一起被复制(即对象嵌入),或者始终与原有文件中的内容保持一致.现在,OEL文件常又称作活动文档(Active Document).
   随后,MS将OLE更新为OLE2,并重新现实,OEL并不仅是DDE技术的进一步扩展,同时又添加了很多新技术,如:OLE自动控制化和OLE控件.接着还为用户创建了大量应用了OLE技术的window外壳程序与接口,并将OLE控件重命名为ActiveX控件(以前的OLE控件称OCX).
   由于这一技术得到了很大的扩展,所有它逐步成为Windows平台中的重要组成部分,MS又再次将其名称更改回OLE,随后又改为COM,并在Windows 2000中更改为COM+.(实际上更名的原因很少的一部分技术,相反市场因素比较重要)
   COM的含义从本质上来看,组件对象模型(Component Object Model)技术为客户模块和服务器模块之间借助指定接口进行通信这一工作定义了一种标准的方法.这里的模块(module)一词指的是应用程序或库(如DLL),相互通信的两个也可能位于相同的计算机上,或位于借助网络连接的不同计算机上.此时,也可可能会出现多接口的情况,这取决于客户端和服务器端各自所扮演的角色.此外,开发人员也可以根据自己的具体目标来添加新的接口,而这些接口虽由服务器对象完成的.服务器对象通常会实现多个接口,而且所有的服务器对象都会拥有一些公共的功能,因为它们都必须现实IUnknown接口.
   Delphi之所有可以轻松地提供COM功能,主要是因为它将各种接口类型集成到了Delphi语言中(相应的,这些接口还用于集成Windows平台中的Java和COM技术).
  创建COM接口的目的就是为了实现两个软件模块之间的通信功能,这两个模块可以是可执行文件,也可是DLL,通过DLL来实现COM对象非常简单.因为,在Win32中,一个应用程序和其使用的DLL都被被保留于相同的内存地址空间中,这意味着,应用程序向DLL传递一个内存地址是合法并有效的.而需要在两个可执行文件中实现通信时,则需要COM接口在后台完成大量的工作才能实现程序间的通信操作,该机制也被称为配置编组.
  注意,用于实现COM对象的DLL被称为进程内(in-process)服务器,而那些分别执行的服务器则被称为进程外(out-of-process)服务器.但是,当DLL在另一台计算机(DCOM)上或主机环境(MTS)中执行时,它们常也称进程外服务.
  实现IUnknown
   每个COM对象必须实现IUnknown接口,而在Delphi中则通常将那些非COM接口简称为IInterface.该接口是一个基础接口,Delphi中的每一个接口都是在该接口基本上派生出来的,同时Delphi还为IUnkown/IIngerface接口提供了一组不同的,现成的实例,其中包括TIngerfacedObject,TComObject.
      
       IUnknown接口提供了三个方法,_AddRef,_Release,QueryInterface.参照如下定义.
   type
     IUnkown = interface
     ['{00000000-0000-0000-C000-000000000046}']
     function QueryInterface(const IID,TGUID; out Obj): Integer; stdcall;
     function _AddRef: Integer; stdcall;
     function _Release: Integer; stdcall;    
   end;
   其中_AddRef和_Release方法用于实现引用计数,而QueryInterface方法则用于处理信息类型和对象类型的兼容问题.
   注意:尽管Delphi语言在对接口类型进行定义时,尽量使其与COM技术相互兼容性,但实际上,Delphi接口在工作时并不需要使用OOM技术.
   通常开发人员无需自己实现这些方法,Delphi提供了一个得要的类TComObject(ComObj Unit)当创建一个COM服务器时,通常需要继承该类.
   TComObject实现了IUnkown接口(它将其方法与ObjAddRef,ObjQuery,ObjRelease接口相映射)和ISupportErrorInfo接口(此时需要借助于InterfaceSupportErorInfo方法).注意:TComObject类的引用计类实现方兴未艾是具有线程安全性的,主要是因为这里使用了InterlockedIncrement和InterlockedDecrement API.
   最后,还应该注意与QueryInterface方法相关的以下两方法内容:
   QueryInterface方法用于类型检查操作.应用程序可以向某个对象询问:是我所感兴趣么?是否实现了相应的接口和我想调用的指定方法?如果回答是否定的,该应用程序就将寻找其他对象,甚至有可能会询问其它服务器.
   如果回答是肯定的,QueryInterface通常就会借助其引用输出参数(Obj)来返回该对象的指针.
   要理解QueryInterface方法的作用,就需要切记一个COM对象可以实现多个接口这一特性,正如TComObject类那样,当调用QueryInterface时,可以首先使用TGUID参数来寻找一个可供使用的对象接口.
   除了TComObject类外,Delphi还预先提供了其他一些COM类.下面列出Delphi VCL所提供的其他一些重要的COM类,以相关使用场合:
   TTypedComObject,该类在ComObj单元中定义,它是从TComObject那里继承而来的,而且实现了IProvideClassInfo接口(而IUnkown和ISupportErrorInfo接口已经由其类TComObject实现了)
   TAutoObject,该类在ComObj单元中定义,从TTypeedComObject继承,并实现IDispatch接口.
   TActiveXControl,该项类在AxCtrls单元中定义,继承于TAutoObjet,并实现了一些接口(IPersistStreamInit,IPersistStoreage,IOleObject和IOelControl等).
   全局唯一标识符 TGUID
   GUIDToString,StringToGUID函数.还可以使用相应的API如StringFromGuid2(对WideString类型)
   类工厂:是一个可以创建其他对象的对象.
   TComObjectFactory,TTypedComObjectFactory,TAutoObjectFactory及TActiveXControlFactory
   
      
   

第三部分  Delphi面向数据库的体系结构
 第13章  Delphi的数据库体系结构
  本章包括以下内容
       Delphi的数据组件
   数据库访问方法
   使用数据敏感控件
   DBGrid控件
   处理表字段
   使用标准控件的数据库应用程序
   
  访问数据库:dbExpress,本地数据及其他
   BDE,ADO
   dbExpress库,BDE,InterBase Express(IBX)
       MyBase和ClientDataSet组件
    ClientDataSet是一个用于访问内存数据的数据集,内存中数据可以是临时的(由程序创建,并在程序退出的同时丢弃),从一个本地文件中载入然后再存回这个文件,或使用一个供应器组件从其他的数据集中导入.
   用于ADO的dbGo
   定制数据集组件
    作为进一步的选择,我们可以编写自己定制的数据集组件,或选择众多可用组件中的一个.开发定制的数据集组件是Delphi编程中最复杂的问题之一,我们将在第17章"编写数据库组件"中进行祥细介绍.界时,我们能够学习TDataSet类的内部工作情况.
   MyBase : 独立的ClientDataSet
    如果我们希望使用Delphi编写一个单用户的数据库应用程序,最简单的方法是使用ClientDataSet组件并将它映射到一个本地文件中,这个本地文件映射不同于传统的数据到本地文件的映射,传统的方法是一次从文件中读取一个记录,而可能还有一个文件来存储索引.而ClientDataSet要将整个数据表格(可能是一个主/祥结构)映射到文件中,当程序启动时,整个文件将载入内存,之后所有的内容都被一次性存储.
    注意:如果两个程序或一个程序的两个实例同时对一个ClientDataSet对应的内存数据修改,那么最后进行的存储操作将会把前面的应用程序修改覆盖掉.
    对于保存ClientDataSet内容的这种支持是数年之前创建的,被称为公文包模型.一个用户可以从他的数据库服务器向客户机下载数据,保存一部分数据,离线工作,最后重新连接并提交这些变化.
   连接到现有的本地表格
    通过设置ClientDataSet的FileName属性(*.cds),将它映射到本地文件.       在OnCreate事件添加
     cds.open;
   从MidasDLL到MidasLib单元
   CDS和XML格式
    ClientDateSet组件支两种不同的流格式:本机格式及基于XML的格式.默认情况下MyBase将数据集存为XML格式,通过SaveToFile,LoadFromFile实现.(如果内存中有一个ClientDataSet,我们可以通过XMLData属性来获取它的XML表现形式,而不必用流导出数据.
   定义新的本地表格
    通过ClientDataSet还可以创建新的表格,需要设置FieldDefs属性来定义表结构,之后,可以为表格创建物理文件(Create DateSet命令或运行时调用 CreateDate方法)
    加OnCreate事件添加:
    if not FileExists(cds.FileName) then
      cds.CreateDataSet;
    cds.Open;
    cds.MergeChangeLog;
    cds.LogChanges:=false;

    我们可以对ClientDataSet组件在内存中,进行很多操作,如:索引,过滤,查找记录,以及比较复杂的操作,如:分组,定义合计值,管理变化日志信息.

    索引是通过IndexFieldNames,和IndexDefs属性来设置的,可以动态的定义索引,该组件还支持基于计算字段的索引.
    过滤是通过设置Filter属性完成的,过程中还可以使用一些运算符及函数,In操作符,通配符.
    定位记录通过Locate属性完成.
    示例
     cds.Locate('Lastname',EditName.Text,[])
     cds.Locate('LastName;FirstName',VarArraof(['Cook','Kevion'],[])
     cds.Locate('Company;Contact;Phone', VarArrayOf(['Sight Diver', 'P', '831-431-1000']), [loPartialKey]);//第三个参数设置Location的Options
    Undo和SavePoint
     ClientDataSet有一个UndoLastChange方法,可以用来实现丢弃操作.这个水运 的FollowChange参数允许我们跟随Undo的操作,客户端数据集将移动到使用Undo操作恢复的记录上,如:
     cds.UndoLastChange(True);
     Undo的一个扩展可以支持用于保存日志信息位置(当前状态)变更的书签,并通过撤销所有成功的变更来恢复它.SavePoint属性可以用于在记录上保存变化的数量,也可以重设日志到过去的位置,注意:我们只能从变更日志中删除记录,而不能得新插入变更.也就是,SavePoint在日志中与位置对应,因此它只能返回到前面几个记录的位置.     使日志生效(Enabling)和无效(Disabling)
     使用LogChanges属性禁用日志记录.这样也同时停止的撤销的操作.
     使用MergeChangesLog方法从变化日志记录上删除所有当前编辑,同时确认以往的编辑操作.注意:如果我们在单个会活中保留和撤消日志,然后在不保留变化日志的情况下保存数据集,就很有意义了.
   使用Delphi中的数据敏感控件(DataAware)
     DBEdit,DBCheckBox,等,所有这些组件都使用DataSource属性与数据资源连接,其中一些组件与整个数据集相关,如DBNavigator,还有一些引用数据资源的特殊字段,如DataField属性.
    网格中的数据
    DBGrid是一个可以一次显示整个数据表格的网格.它允许滚动与定位,还可以编辑网络的内容,是Delphi网格控件的扩展.
    可以通过DBGrid的Options属性的各种标记并修改其Columns集合来定制它.网格允许用户使用滚动条确定数据的位置,并执行所有的操作,用户可以直接编辑数据,在指定位置按Insert插入新记录,按Down箭头键在末端附加一个新记录,或使用Ctrl+Del删除当前记录.
    Columns属性是一个集合,可以选择在网格中要查看的数据表格字段,并为每个字段设置列与标题属性(颜色,字体,宽度,对齐,标题等),某些更高级的属性,如获至宝ButtonStyle,DropDownRows可以用于为网格单元或数值的下位式列表提供定制的编辑器.
    DBNavigator与数据集操作
    DBNaviagator是一个按钮集合,用于在数据库上进行定位并执行操作,我们可以通过删除Visblebuttons集合属性中的一些元素,禁用DBNavigator控件上的按钮.(这些按钮在相连的数据集上执行基本操作,我们也可以用自己的工具栏代替它们,特别是当我们使用Delphi预定义数据库操作的Actionist组件时)
    基于文本的数据敏感控件DBText,DBEdit,DBMemo
    基于列表的数据敏感控件DBListBox,DBComboBox,DBRadioGroup(Items,Values属性)DBCheckBox(ValueChecked,ValueUnchecked属性)
    使用查寻控件
    DBLookupListBox,DBLookupComboBox
    示例:
    Object DBLookupComboBoxx1 : TDBLookupComboBox
      DataField='CustNo'
      DataSurce=DataSourceOrders
      KeyField='CustNo'
      ListField='Compnay;CustonNo'
      ListSource=DataSourceCustomer
      DropDownWidth=30
    end
    图形数据敏感控件DBImage.
   数据集组件(DataSet)  
    TDataSet的规则
     同一时间只能有一个活动的记录.
     只能编辑活动记录
     可以修改活动缓冲区中的数据,但只有通过明确声明(通过Edit命令)之后才行,还可以使用Insert命令建立一个新的空记录,并通过Post命令关闭这两个操作(插入和编辑)
    TDataSet的定义:
    TDataSet = class(TComponent, IProviderSupport)
    private
      ...
    public
      // Create and Destory, open and close
      constructor Create(AOwner: TComponent); override;
          destructor Destroy; override;
      procedure Open;
      procedure Close;
      ...
      // status infomation
      ...
      //datasource
      ...
      // fields, including blobs ,details ,calculated, and more 
      ...
      // position,movement
      ...
      // bookmark
      ...
      // find ,locate 
      ...
      // filtering
      ...
      // refreshing, updating
      ...
           // editing, inserting, posting, and deleting
      ...
      // events related to editing, inserting, posting , and deleting
      ...
      // support utilities
    数据集的状态[dsBrowse,dsEdit,dsInsert,dsIncative,dsCalcFields,dsNewValue,dsOldValue,dsCurValue,dsFilter]
    数据集的字段(TField组件,Fields属性,FieldByName方法,Value属性,AsDate,AsString,AsInteger属性)
    示例:
    strName:=cds.Fields[0].AsString;
    strName:=cds.FieldByName('LastName').AsString;
    默认属性FieldValues示例:
    strName:=cds.Fields['LastName'];
    strName:=cds['LastName'];
    Fields编辑器
   使用Field对象(DisplayFormat属性,TField组件的Alignment,DiplayLable,DisplayWidth,Visible属性,Field类的层次式结构)
    使用计算字段(OnCalcFields事件)
     cdsPopulactionDensity.value=cdsPopulation.value/cdsArea.Value;
    查寻字段(DBLookupComboBox)
    用字段事件处理零(Null)值 OnValidate,OnChange,OnGetText,OnSetText
    定位数据集(相关的Position,Locate方法,RecordCount属性,RecNo属性)
   数据表格列的总和
    begin
      Total:=0;
      cds.First;
      while not cds.EOF do
      begin
        Total :=Total+cdsSalary.Value;
        cds.Next;
      end;
      MessageDlg('Sum of new Salaries is '+ Fromat('%m',[Total]),mtInofmration,[mbOK],0);
    end
   使用书签TBookmark数据类型
   编辑数据表格列(cds.Edit)
   自定义数据库网格
    绘制DBGrid(必须将DefaultDrawing属性设置为False)并处理OnDrawColumnCell事件.   
   示例(事件DrawColumnCell):
   begin
     // red font color if length >100
     if ( Column.Field=cdsLengthcm) and (cdsLengthcm.AsInteger>100) then
       DGrid1.Canvas.Font.Color:=clRed;
     // default Drawing
     DBGrid1.DefaultDrawDataCell(Rect,Column.Field,State); 
   end;
   对于备注字段,使用OnGetText,OnSetText事件,并用Trim去掉文本末的不打印字符.
   对于图像字段,最简单的办法是建立临时的TBitmap对象,将这个图形字段赋给它,并在Canvas里绘制.还有一种办法,就是把图形字段的Visible属性设置为False,并将图像添加到鱼的名称上.
   如下代码(OnDrawColumnCell事件)
   var
     Picture: TPicture;
     OutRect: TRect;
     PictWidth: Integer;   
   begin
     // default out rectangle 
     outRet:= Rect;
     if Column.Field =cdsCommon_Name then
     begin
       //draw the image
       Picture := TPicture.Create;
       try
         Picture.Assign(cdsGraphic);
         PicthWidth:= (Rect.Button-Rect.Top)*2;
         OutRect.Right:= Rect.Left+PictWidth;
         DBGrid1.Canvas.StretchDraw(OutRect,Picture.Grapthic);
       finally
         Picture.Free;
       end;
       // reset output rectangle, leaving space for the graphic  
       OutRect := Rect;
       OutRect.Left:= OutRect.Left+PictWidth;
     end;
     // red font color if lenght>100 (omitted see above) 
     DBGrid1.DefaultDrawDataCell(OutREct,Column,Field,State);
   end
   允许选择多重网格(Options属性中的dgMultiSelect元素,SelectedRows属性)
   向网络拖动记录(MouseCoord)
   带有未准控件的数据库应用程序
    模拟Delphi的数据敏感控件(OnAfterScroll,OnStateChange,BeforePost,AfterInsert,OnNewRecord)事件
  向数据库发送请求
  分组与合计
   分组,IndexDefs中的GroupingLevel
   定义合计,Aggregates中的AggregateName,Expression,GroupingLevel
  主/祥结构
   TDataSet的DataSource属性建立主数据源,同时它结合起来了MaterFields属性
  处理数据库错误(try/except,Application的OnException事件OnPostError,onEditError,OnDeleteError,OnUnpdateError事件) 
     

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/234282
推荐阅读
相关标签
  

闽ICP备14008679号