使用Delphi来跟我学COM (第一部 基本知识)
来源:互联网 发布:cdrx4官方软件下载 编辑:程序博客网 时间:2024/05/22 01:38
======================================================
注:本文源代码点此下载
======================================================
第一章 在delphi中使用接口
1.1 定义接口:
目的:什么是接口,以及和抽象类的关联以及不同点。
抽象类(备注理解接口最简单的方法)
永远不能创建一个抽象类的实例;
本身不能实现功能,依靠派生类实现;
接口
被申明为interface类型。接口名从字母i开始。类类型名从t开始。
所有的接口从iunknown继承;
不能创建接口实例;
不能在接口中指定范围指示。所有的方法都是公有型(public),不能在接口中申明包括范围指示;
不能申明变量;接口只能决定提供什么样的功能,对于如何完成功能没有限制;
接口中申明的所有函数和过程,概念上都是虚抽象函数和过程;因此申明时不能带virtual;
接口是不变的;
1.2申明一个接口
目的:如何声明一个接口
常用的接口:clsid、iid、和libid;
guid(globally unique identifier)全球唯一标示符: cocreateguid产生(api);
clsid(class identifier): 代表com对象的类别,代表com对象的coclass;
iid(interface identifier): 代表一个com对象的接口;
例如:如何建立com对象的方法;
var
iroot: iunkown;
begin
...
iroot := createcomobject(progidtoclassid('project1.interface1')); //取得实体样例
...
end;
应用程序在内存中建立了com对象的实体样例;
注意: createcomobject回传的是com对象的实体样例的iunknown接口;
appid(application indentifier): 应用程序id;
catid(category identifier): com组件实现的组件类型;
libid(library identifier): com对象实现的type library代表的id;
progid: 有意义的字符串代表特定的clsid;
1.3 实现接口
目的:如何实现接口
实现iunknown: queryinterface、 _addref、 _release
使用tinterfaceobject来自动实现iunknown,否则的话自己要实现上面的方法。
创建、使用及销毁接口: create;指向接口的指针不访问任何信息;自动释放、强迫销毁一个接口将变量置为nil
注:delphi自动创建和销毁接口。
获取单个接口的指针:
直接分配:类与他们实现的接口类型兼容的
getinterface(const iid: tguid; out obj):判断对象是否支持一个接口
as操作符: 对象支持特定的接口(对象不支持接口就错的话,可以拦截错误);
as自动调用计数功能;
1.4 高级多级接口问题
目的:在一个类中实现多个接口
在一个类中实现多个接口
txy = class(tinterfacedobject, ixx, iyy): 类txy 实现了ixx和iyy接口的所有方法。
多个接口不是多重继承:txy有且只有一个基类tinterfacedobject;
方法分辨字句:当接口方法在类中实现时,方法分辨子句可使用改变他的名称
txy = class(tinterfacedobject, ixx, iyy)
procedure ixx.pxy = pxy1
procedure iyy.pxy = pxy2
接口授权:一个接口的实现授权给另一个类:一个类包含针对另一个类的指针。
内部类: 实现一个或多个接口的功能性;
外部类: 简单的将这些方法传递给内部类,而不是重新实现接口;
接口属性:可以定义只读、只写、或者读写属性;
但是所有访问都必须通过访问函数,因为接口不能定义存储。
1.5 小结
目的:如何在delphi应用程序中内部使用接口,了解delphi语言要素的接口。
申明一个接口;
在类中实现接口;
实现iunknown所需要的功能;
自动对象析构的处理;
在类中实现多个接口;
将一个接口的实现授权给一个内部对象;
定义并实现接口属性
[第一章 接口][第二章 接口与com][第三章 类型库][第四章 自动化][第五章 activex][末尾]
第二章 接口与com
2.1 guids 和 com
目的:
clsid: class id是guid一个具体的类型的名称,注册表 hkey_classes_root\clsid
每个接口clsid或guid都代表一个com接口的实现
com对象: tcomobject继承(tinterfacedobject不提供实现com对象的必要功能)
hresult: 特殊类型的返回值,意味着函数调用成功还是失败。
olecheck: 检查函数调用可能产生的错误;当调用返回hresult的com函数时应使用该函数;
类厂(class factory):
com对象不是由程序直接例示的;
com使用类厂来创建对象;
类厂是一个对象,目的就是创建其他对象;
每一个com都有一个相关的类厂,负责创建在服务器中实现的com对象;
类厂把com从实际构造一个对象的过程中分离出来,com没有对象构造过程
类厂支持iclassfactory接口: iclassfactory只定义2个函数createinstance和lockserver
createinstance函数: 负责创建类厂涉及的com对象的实例的函数;
lockserver: 保持服务器在内存中,一般不要调用他;
类厂中的双重类:
2.2 进程内的com服务器(in-process com server)
目的:理解进程内的com服务器
共性:有一个inprocserver32的子键、所有进程内服务器都输出以下四个标准函数;
dllregisterserver: 2种方式自动调用
ide的register activex server菜单
windows的命令行应用程序regsvr32.exe(或boland应用程序tregsvr)
dllunregisterserver: 是dllregisterserver的逆进程,移走放在注册表中的条目;
dllgetclassobject:
负责提供给com一个类厂,该类厂用语创建一个com对象;
每个com服务器将实现它输出的每个com对象的类厂;
dllcanunloadnow: 返回s_true,co在内存中移走com服务器;如果返回s_false
线程支持(threading support): 只适用于进程内服务器;被保存在注册表中;线程模型如下
single-thread apartment(sta): 实际上根本没有线程支持,所有对com服务器的访问由windows顺序执行,不必考虑同步存取的问题。
mutli-threaded apartment(mta): 允许同时有多个线程存取com对象,必须控制不同线程同步存取的程序代码;
both apartment: 可以执行在mts或sta中;
自由的:
注册服务器(registering the server): 所有的com服务器都需要windows注册表来工作。
定制构造函数(custom constructors): delphi中com对象的基类包括一系列的非虚构造函数。
只需重载initialize方法;
不要试图重载一个com对象的构造函数;
创建一个进程内com对象
function createcomobject(const classid: tguid): iunknown;
cocreateinstance内部创建负责创建com对象类厂的实例,然后使用类厂来创建对象,创建完后com对象后,类厂被销毁;
虚方法表(virtual method tables):
接口实现为独立的方法表,该表实现在内存中紧靠vmt的地方;
不同的接口占据不同的内存部分,不能简单的把一个接口值赋给另外一个接口;
通常使用as操作符从一个接口转换为另外一个接口;
2.3 进程外com服务器(out-of-process com server)
目的:理解进程外com服务器
进程外服务器是在exe中实现;
实例化(instancing): 创建多少个客户需要的实例;可以支持三个实例化方法中的一个;
single instace(单实例):
只容许一个com对象的实例
每个需要com对象实例的应用程序将产生com服务器的单独拷贝;
multiple instance(多实例):
指com server可以创建一个com对象的多个拷贝;
客户请求com对象的一个实例时,由当前运行的服务器创建com对象的一个实例;
internal only(内部实例):用于不被客户应用程序使用的com对象;
调度数据(marshaling data):
一个可执行的程序不能直接访问另一个可执行程序的地址空间;
windows通过调度(marshaling)进程在调用应用程序和进程外com服务器之间移动数据;
自动化兼容 smallint、integer、single、double、currency、tdatetime、widestring、idispatch、scode、wordbool、olevariant、iunknown、shortint、byte;
记录和数组不能自动调度;
2.4 variant 数组
目的:如何使用variant 数组;
variant:
一种可以拥有各种数据类型;
也可以告诉目前存储的数据是什么类型(通过使用vartype函数);
可以给相同的variant分配不同的数据类型,只要variant包含数字值就可以执行算法;
variant数组只不过是variant型的数组,不必包含同类型的 数据;
variant数组的创建方法:
function vararraycreate(const bounds: array of integer; vartype: integer): variant;
bounds: 告诉数组的上下界;
vartype: 决定了数组的中存储什么类型的数据。
例如:创建数组的数组, 可以模仿任何类型的数据结构类型:
vararrayx := vararraycreate([1,10], varvariant);
数组的单个元素可以装载一个数组: vararrayx[1] := vararraycreate([1,5], varvariant);
function vararrayof(const values: array of variant): variant;
运行时用于创建一维数组;
可以创建全异的数值数组;
例如: myarray := vararrayof(['李维', 30, '60', 60.369, 'china']);
使用variant数组: 与使用标准delphi数组类似;
vararraylowbound、vararrayhighbound(与数组的low、high类似)计算边界;
vararraydimcount:计算数组的维数;
2.5 小结
目的:接口guid及进程com服务器的基本知识了解;
guid是什么;以及为什么guid对com是如此重要;如何创建guid以供自己使用;
进程内com服务器,创建及如何使用;
variant数组; 是什么、及如何使用;
进程外com服务器的介绍、调度及windows可自动调度的类型;
只有能理解虚方法表(vmt)的面向对象的语言才能访问只有虚方法表的com服务器
[第一章 接口][第二章 接口与com][第三章 类型库][第四章 自动化][第五章 activex][末尾]
第三章 类型库
3.1 定义类型库
目的: 类型库是什么,和它的作用是什么。
使用类型库的好处:
编写自动化控制时早期连接(early binding);
许多编译器可以从一种类型库中自动生成针对特定编程语言的代码;
实用程序可以用来读取并显示有关包含类型库的com服务器的信息;
在com客户和服务器之间自动参数调度;
类型库对某些com服务器是必须的,例如:自动化服务器和activex控件;
ttypedcomobject: delphi由该类及其派生类提供了对类型库的支持;
delphi自动创建xxxx_tlb.pas文件;
com由ttypedcomobject派生,而不是tcomobjectfactory.create;
初始时,delphi调用了ttypedcomobjectfactory.create、而不是tcomobjectfactory.create;
3.2 使用delphi来创建类型库
目的: 如何使用delphi来创建类型库的基本知识;
可以使用idl(interface definition language 接口定义语言)编码类型库;
类型库编辑器:
工具条:可以添加接口、方法、以及属性到com服务器中;
注:工具条上可以通过点击鼠标右键弹出的菜单中选择text labels命令打开工具条的标题;
interface(接口): 自动为每一个新建的接口产生一个guid;
dispinterface(派遣接口): 与接口类似,但是使用不同的派遣机制调用服务器中的方法;
coclass(): 类别的定义,被指定给实现接口的com对象;
使用com对象之前必须先使用一种方法从类别定义建立真正的类别对象(变量);
再从类别对象取去需要的接口;
最后再从取得的接口中调用需要执行的方法或需要存取的属性;
enumeration(枚举): 与枚举类型类似;有整数id来指明,而不是通过集合类型;
constant(常量):只有在枚举下才有用;可以编辑name、value属性;
alias(别名): 用于定义用户要包括一条记录类型(record)或联合类型(union)中的类型;
record(记录类型): 记录结构;
union(联合类型): 等同于pascal variant类型;
module(模块): 模块是方法和常量的集合;
method(方法): 输入参数(in)、输出参数(out)、可变参数(var);
property(属性): 只读、只写、读写三种;
refresh(更新): 使delphi更新源文件;
register(注册): 编译com服务器并把服务器注册到windows中;
export(输出到idl): 在midl或corba格式中很有用;
friend
对象列表(object list):显示服务器中定义的接口、方法等;
页控件(page control):显示对象列表中当前选中的接点的类型信息;
类型库也是一种资源;
不必在客户应用程序中直接读取类型库;
3.3 小结
目的: 类型库的运用;
类型库是什么;
如何创建一个类型库;
如何编译一个类型库类给自己的服务器添加方法、属性及枚举类型;
如何读取类型库的信息;
[第一章 接口][第二章 接口与com][第三章 类型库][第四章 自动化][第五章 activex][末尾]
第四章 自动化
通过自动化操作类型库;接口和自动化;variants和自动化;派遣接口;双重接口;自动化ado;
4.1 定义自动化
目的: 自动化以及客户通过使用接口、variants派遣接口和双重接口创建并使用自动化服务器;
自动化是一种从应用程序的内部自动控制另一个应用程序的方法。
获取自动化服务器的com对象的两种主要访问方法:
接口:早期连接(early binding)
早期连接是指对接口方法的所有调用在编译时检查参数是否正确;
variants: 后期连接 (late binding)
后期连接指连接意味着方法调用直到运行时才被实现;
variant不是对象指针;对象的调用方法是后期连接;
编写快速、简单的客户应用程序不用费力去输入一个类型库;
派遣接口(dispinterface)
在接口和variant中间的某个地方就是派遣接口;与接口有很多类似;
只是方便客户而设定的;
并没有在服务器上实现派遣接口;是服务器上实现了接口;
假设服务器的com对象也支持idispatch接口,客户应用程序可以使用variants或派遣接口;
双重接口(dual interface): 自动化服务器
简单定义为自动化服务器,支持早期连接(接口)和后期连接(variants);
使用delphi创建的任何任何自动化服务器将自动支持双重接口;
4.2 进程内自动化服务器
目的: 创建并使用进程内自动化服务器;
createoleobject和getactiveoleobject
createoleobject:总是创建特定服务器的新实例;
getactiveoleobject: 用来获取正在内存中运行的服务器的引用;
例如:
procedure startorlinktoword;
var v: variant;
begin
try
v := getactiveoleobject('word.basic');//判断是否wod已启动;
except
v := createoleobject('word.basic');//否则启动word; 通常自动化服务器启动是隐藏的;
v.appshow;//显示word应用程序;
end;
v.filenew;//创建一个新的文档;
v.insert('automation is easy!');
end;
访问自动化服务器的方法:
interface 通过接口;
variant 通过variant: 通过可使用的类名;createoleobject
dispinterface 通过派遣接口;
4.3 进程外自动化服务器
目的: 自动化的基础;创建一个automation服务器,如何使用接口、派遣接口、和variants来控制此服务器;
在本身应作为独立服务器应用程序的情况下,使用进程外非常好;
hresult:
自动服务器中的所有方法必须返回一个hresult,暗示是成功还是失败;
所有其他参数必须在out参数中返回;
safecall:
调用协议可使编码;
指示delphi自动把所有方法包括在try...except模块中;
在客户端safecall导致客户检查是否有hresult类型的返回失败码;
4.4 com事件和回调
目的: 两种方式的比较;
派遣接口(dispinterface):
与interface的比较
dispinterface: 为事件提供了更好的支持;与vb兼容;实现事件是最兼容的方法;
interface: 不与vb兼容;但速度比派遣接口稍快;
回调接口(callback interface):除非有极重要的原因否则不要使用;
服务器做大量的工作,而刻户端不需要太多的工作;
接口中定义回调方法,而不是使用派遣接口把事件送回到客户端;
回调接口在服务器中定义,但在客户中实现;
如果知道服务器和客户提供的接口,回调接口更有效;
4.5 自动化ado: microsoft最新的数据库技术;
目的:如何使用delphi来快速、轻松的使用基于com的技术;
主要组件:connection、recordset、command;
connection对象: 用于连接到一个本地或远处的数据库;
recordset对象: 提供了一个记录集的连接;
command对象: 向数据库发出命令,不返回结果集;
连接数据库:connection.open();
记录集打开:recordset.open();
执行命令:对数据库进行操作,并返回结果集,应使用command对象(与parameter一起工作);
访问字段值:
访问field对象的值: recordset.fields.item[fieldno].value;
访问字段名称:recordset.fields.item[fieldno].name;
数据库错误处理:error对象,该对象提供任何错误的详细代码;
4.6 小结
目的: 接口、派遣接口和variants三种方法之间的不同,在特定的环境中使用那种方法;
创建进程内和进程外com自动化服务器;
vraiants在com自动化服务器中的作用,以及如何使用容许后期连接到自动化对象;
实现com事件和回调;
如何使用delphi能相对轻松的使用ado;
知道接口、派遣接口、和variants的区别;
[第一章 接口][第二章 接口与com][第三章 类型库][第四章 自动化][第五章 activex][末尾]
第五章 activex控件和activeforms
5.1 activex控件
目的:
5.2 创建activex控件;
目的:
5.3 activeform(active窗体);
目的: 组件导向的中介软件;activeform的开发;开发浏览器的客户端应用程序;
创建activex工程:
new-->activex-->activex library
new-->acitvex-->active form
设计时期开发执照;
关于对话框;
版本控制编号;(一般要包括,控制新旧版本、以及是否从服务器下载);
分发:project-->web deploy options
target dir: activeform组件于html首页中codebase tag的目的;
target url: delphi分发activex组件的时候自动产生一个html的首页档案;
html dir: 储存这个html首页档案的位置;
use cab file compression:
include file version number: 分发时包含版本信息;
auto increment release number: 自动增加版本编号;
deploy required package:
deploy additional file:
project-->wep deploy开始分发;
5.4 小结
目的:加强activex组件的能力;
使用activex组件;
如何把已有组件转换为activex组件;实现delphi没有提供的功能;
如何从窗体创建activeform;
备注: 有不当的理解之处请大家指正,谢谢;
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
- 使用Delphi来跟我学COM (第一部 基本知识)
- 跟我来学jQuery(三)
- 使用Delphi学COM
- 跟我来学CSS
- 跟我来学C(一)类型
- 跟我来学jQuery(一)
- 跟我来学jQuery(二)
- 跟我来学shiro,第一课
- 跟我来学shiro,第二课
- 跟我一起学C++课程笔记(第一天)
- 跟我学C语言(第三天)
- 跟我一起学C语言(第五天)
- 跟我一起学C语言(第七天)
- 跟我学C语言(第八天)
- 跟我一起学C语言(第九天)
- 跟我一起学linux基础(第一天)
- 跟我一起学linux基础(第三天)
- 跟我一起学linux基础(第五天)
- Java随记5
- java 类型的字符转换
- 一个简单的Ajax例子
- delphi for php 中文完全支持方法[转]
- 关于 Delphi 中流的使用(1) 用 TMemoryStream(内存流) 入门
- 使用Delphi来跟我学COM (第一部 基本知识)
- java 的 StringBuffer 类
- Html5小游戏之小小塔防
- 当 HTML 5 遇见 Google
- extjs 总是返回failure
- HTML代码过滤函数
- 用Delphi编写的一个上网助手
- DELPHI 线程类
- Digg 顶 踩(jQuery+Ajax)