CreateComObject函数,如果是自动化对象,则导入类型库,然后uses类型库单元,然后调用那个com对象的CoXXX.Create就可以了。
你可以看看《delphi6 Com深入编程》这本书。
你可以看看《delphi6 Com深入编程》这本书。
解决方案 »
- 如何设置 MaskEdit 的EditMask属性,使其为 yyyy/mm/dd 样式
- Treeview 节点问题
- 请问这应该怎么做,大家帮一下忙呀
- 我想把visio的*.vsd文件里的图形数据(矢量)读出来,怎么读?或者谁知道他的格式也行
- 如何在delphi下制作类似于VB的Line控件
- 关于删除记录的两个问题。
- 请问在delphi中如何启动mysql服务
- 急求帮助解决下,搞了4天的问题在老外那发现解决方法,但看不懂。
- 怎样实现分组打印
- 那里有FastReport的中文文档?如能介绍不胜感激。
- 一个关于窗体创建的问题,很简单的我是初学者,呵呵,分一定给
- DELPHI与ACCESS相连,怎么在ACCESS中自动增加字段?
或者用自动化对象,导入类型库,必须uses类型库单元,然后调用那个com对象的CoXXX.Create
就OK 了
var
pPnt:IPoint;
begin
pPnt:=CoPoint.create as IPoint;
end;此外,对CoClass才能用CoClass.create,如果是AbstractClass或Class就不能直接实例化了,Class可以通过其他已经实例化的对象属性方法获得它的实例,AbstractClass则是通过继承关系获得它的实例
library TextComfrm;{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }uses
SysUtils,
comobj,
comserv,
Classes,
comfromsource in 'comfromsource.pas' {Form1},
globalmessage in 'globalmessage.pas',
TextComfrm_TLB in 'TextComfrm_TLB.pas';Const
Clsid_testcom:TGuid='{FE573162-AD80-40A1-8C85-A1A7D3FAEFEC}';
Type
IUTestCom=Interface
['{FF083796-6737-4F4C-ACD8-BFD5DD1CEEF5}']
function createform(parentHandle:LongInt):LongInt;Stdcall;
function showform:Integer;stdcall;
function close:Integer;stdcall;
End;
TUTestfrmcom=Class(TComObject,IUTestCom)
Private
Form:TForm1 ;
protected
Public
function createform(parentHandle:LongInt):LongInt;Stdcall;
function showform:Integer;stdcall;
function close:Integer;stdcall;
End;
Exports
DllRegisterServer,DllUnRegisterServer,DllGetClassObject,DllCanUnLoadNow;
{$R *.TLB}{$R *.RES}
function TUTestfrmcom.createform(parentHandle:LongInt):LongInt;
Begin
Form:=TForm1.Create(Nil,ParentHandle);
Result:=Form.Handle;
End;
function TUTestfrmcom.showform:Integer;
Begin
Form.Show;
Result:=0;
End;
function TUTestfrmcom.close:Integer;
Begin
Form.Close;
Form.Free;
Form:=Nil;
Result:=0;
End;
begin
TComObjectFactory.Create(ComServer,TUTestfrmcom,Clsid_testcom,'Test Com Form',
'Test',ciMultiInstance);
end.
unit TestForComSendMessage;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,ComObj,
StdCtrls,globalmessage, AppEvnts;
Const
Clsid_testcom:TGuid='{FE573162-AD80-40A1-8C85-A1A7D3FAEFEC}';
Type
IUTestCom=Interface
['{FF083796-6737-4F4C-ACD8-BFD5DD1CEEF5}']
function createform(parentHandle:LongInt):LongInt;Stdcall;
function showform:Integer;stdcall;
function close:Integer;stdcall;
End;
Tmainfrm = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
ApplicationEvents1: TApplicationEvents;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
private
{ Private declarations }
public
{ Public declarations }
childHandle:LongInt;
Procedure MsgShowMessage(Var Msg:TMessage);Message uwm_formtocrtlshowmessage;
end;var
mainfrm: Tmainfrm;implementation{$R *.DFM}procedure Tmainfrm.Button1Click(Sender: TObject);
var
temp:IUTestCom;
begin
temp:=createcomobject(Clsid_testcom) as IUTestCom;
childHandle:=temp.createform(Handle);
temp.showform;
end;procedure Tmainfrm.Button2Click(Sender: TObject);
begin
SendMessage(ChildHandle,uwm_ctrltoclose,0,0);
end;procedure Tmainfrm.Button3Click(Sender: TObject);
begin
SendMessage(ChildHandle,uwm_ctrltoformshowmessage,0,0);
end;procedure Tmainfrm.MsgShowMessage(var Msg: TMessage);
begin
// ShowMessage('Com Form Send Message To Form To ShowMessage!!');
end;procedure Tmainfrm.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key=#27 then
SendMessage(ChildHandle,uwm_ctrltoclose,0,0);end;procedure Tmainfrm.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
if Msg.message =WM_KeyDOWn then
MessageBox(handle,pchar(IntToStr(msg.wParam)),'key',MB_OK);
If (Msg.wParam = 27) and (msg.message =WM_KEYDOWN) Then
begin
//showmessage('yes');
Msg.wParam :=13; end;
end;end.
//OK!!!!
Step0: 从Word的类型库(Type Library)文件生成声明文件(xxx_TLB.pas), 要使用自动对象,必须先读取相应的类型库文件(*.TLB),从其中得到自动对象的类型信息, 方法:在Delphi IDE中打开......\Microsoft Office\Office\M$Word8.olb Delphi将根据类型库中的信息生成声明单元Word_TLB.pas, 注意,Delphi在转换过程中将以下符号(symbol)进行了重命名(rename):
--------------------------------------------------------
类型库中的符号 重命名为
--------------------------------------------------------
Application WordApplication
Document WordDocument
Font WordFont
ParagraphFormat WordParagraphFormat
OLEControl WordOLEControl
LetterContent WordLetterContent
--------------------------------------------------------
这个问题后面会详细讨论 Word_TLB.pas中包含的如下信息:
...
...
const
...
//coClass "Application" 的ClassID
CLASS_WordApplication: TGUID = '{000209FF-0000-0000-C000-000000000046}';
...
...
...
我们也将在后面用到
Step1: 创建WordApplication对象,如下: 函数CreateCOMObject将根据指定的ClassID创建对应的COM自动对象,声明如下: //unit COMObj
function CreateCOMObject(const ClassID: TGUID): IUnknown;0D 在本例中,我们创建WordApplication对象的代码如下:
// 引用COMObj单元和Word_TLB单元
uses
..., ..., ..., COMObj, Word_TLB; type
TfmMain = class(TForm)
...
...
private
// 声明一个变量,保存WordApplication的引用
// WordApplication在Word_TLB单元中声明
WordApp: WordApplication;
protected
procedure StartWordApp;0D
procedure TerminateWordApp;
end; 其中StartWordApp方法将分别创建一个WordApplication对象,
实现如下: procedure TfmMain.StartWordApp;
begin
if not Assigned(WordApp) then
try
// 创建WordApplication对象
WordApp:=CreateCOMObject(CLASS_WordApplication) as WordApplication;0D
with WordApp do
begin
// 指定COM对象的属性
Caption:='This copy of WinWord is launched by '+Forms.Application.ExeName;
0A Visible:=True;
end;
ShowMsg('启动 Word Application 成功');
except
ShowError('启动 Word Application 失败');
end;
end; procedure TfmMain.btStartWordAppClick(Sender: TObject);0D
begin
StartWordApp;
end;================================================================
一颗红心向前看,为了革命两茫然,不好意思才囊尽,只能说上一点点。
★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆
★ 我踢 我踢 我踢 我踢 我踢 我踢 我踢 我踢 我踢 ★
★ 你UP 你UP 你UP 你UP 你UP 你UP 你UP 你UP 你UP ★
★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆
======================================================
procedure TfmMain.btNewDocClick(Sender: TObject);
var
DocTemplate,
NewTemplate : OleVariant;
begin
StartWordApp;
DocTemplate := UnAssigned; // 打开新文档时使用的模板
NewTemplate := False; // 是否将文档作为模板打开
WordApp.Documents.Add(DocTemplate,NewTemplate);
end; // 关闭当前文档
procedure TfmMain.btCloseDocClick(Sender: TObject);
0A var
SaveChanges,
OriginalFormat,
RouteDocument : OleVariant;
begin
SaveChanges := WdDoNotSaveChanges; // 不保存修改
OriginalFormat := UnAssigned; // 未赋值
RouteDocument := UnAssigned; // 未赋值
WordApp.ActiveDocument.Close(SaveChanges,OriginalFormat,RouteDocument);
end;
Step3:COM对象使用完毕后,注意释放 TerminateWordApp方法将释放WordApp指向的COM对象,
实现如下: procedure TfmMain.TerminateWordApp;
var
SaveChanges,
OriginalFormat,
RouteDocument : OleVariant;
begin
if Assigned(WordApp) then
begin
SaveChanges := WdDoNotSaveChanges; // 不保存修改
OriginalFormat := UnAssigned; // 未赋值
RouteDocument := UnAssigned; // 未赋值
try
// 调用COM对象方法
WordApp.Quit(SaveChanges,OriginalFormat,RouteDocument);
ShowMsg('关闭 Word Application 成功');
except
ErrorMsg('关闭 Word Application 失败');
end;
// 将WordApp赋值为Nil,则原来指向的COM对象的引用记数减1
// 当引用记数为0时,COM对象将被释放
WordApp := Nil;
end;
end; procedure TfmMain.FormDestroy(Sender: TObject);
begin
TerminateWordApp;
end;================================================================
一颗红心向前看,为了革命两茫然,不好意思才囊尽,只能说上一点点。
★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆
★ 我踢 我踢 我踢 我踢 我踢 我踢 我踢 我踢 我踢 ★
★ 你UP 你UP 你UP 你UP 你UP 你UP 你UP 你UP 你UP ★
★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆
================================================================
1、以上所述方法是完全通过编程直接调用COM实现的,
所有使用COM的地方都可以通过上面的方法实现,
步骤为:
(0)根据类型库文件生成声明单元
(1)得到需要的ClassID后使用CreateCOMObject函数创建COM对象
(2)使用COM对象的属性和方法完成操作
(3)释放COM对象 2、我们的目的不仅仅是为了控制Word,而是为了说明使用COM的根本方法,
选择Word作为例子,是因为大家都比较熟悉,
对Word的控制,Delphi已经提供了一些支持,包括:
......\Delphi5\Ocx\Servers\Word97.pas
等于前面所说的Word_TLB.pas, ......\Delphi5\Demos\Activex\Oleauto\Word8\autoimpl.pas
将以上对COM对象的操作封装成了一个Delphi类 还可以参考两个示例:
......\Delphi5\Demos\Activex\Oleauto\Word8\word8auto.dpr
和
......\Delphi5\Demos\Activex\Oleauto\SrvCOMp\Word\pwordCOMp.dpr
3、一般情况下会同时提供很多COM Server,
应该使用什么对象、使用什么方法、使用什么属性
需要参考帮助文件,上面的例子中M$Word8.olb的帮助文件为:
....\Microsoft Office\Office\VBAWRD8.HLP
在没有帮助文件的情况下就需要研究类型库中的信息了
4、关于类型库本身
类型库包含非常丰富的信息,包括: Interface、DispInterface、CoClass、Enumeration、
Alias、Record、Union、Module等等 这些是类型库的基本信息,此外还包括:
指定的帮助文件、所依赖的其它类型库等等 类型库一般以单独的类型库文件(*.TLB)提供,或包含在Server程序中(*.EXE、*.DLL)
类型库信息包含在EXE中的例子有:
....\Delphi5\Demos\Activex\Oleauto\Autoserv\memoedit.dpr
在DLL中的例子有:
....\Delphi5\Bin\StdVcl40.DLL
这两种情况下,实际上类型库信息都包含在EXE/DLL中的名为"TypeLib"的资源中 查看M$Word8.OLB可以看到,它实际上是一个DLL格式文件 5、关于类型库的Register和Unregister
Windows下有注册类型库的程序RegSvr32.exe,Borland自己也有TRegSvr.exe
除此之外,在Delphi IDE中打开类型库后,可以使用菜单Run|Register ActiveX Server
或Run|Unregister ActiveX Server0D
那么类型库的Register和Unregister具体是怎么实现的呢, 打开....\Delphi5\Demos\Activex\TRegSvr\TRegSvr.dpr,查看源代码,我们可以看到:
(1)对于*.tlb:
调用OleAut32.DLL中的LoadLibrary函数,得到一个ITypeLib接口,
调用ITypeLib的GetLibAttr方法,得到tagTLibAttr结构,其中包括
GUID、LCID、Major Version、Minor Version、SysKind信息
Register的方法是:
调用OleAut32.DLL中RegisterTypeLib函数
Unregister的方法是:
调用OleAut32.DLL中UnregisterTypeLib函数,参数由前面的tagTLibAttr结构中各域指定 详见TRegSvr.dpr中的RegisterTLB过程 (2)对于*.dll:
调用LoadLibrary函数载入dll
Register的方法是:
调用DLL中的DllRegisterServer函数
Unregister的方法是:
调用DLL中的DllUnregisterServer函数
(3)对于*.exe
Register的方法是:
调用EXE,命令行参数为"/RegServer"
Unregister的方法是:
调用EXE,命令行参数为"/UnregServer"
也就是说,对于DLL和EXE,应该实现自注册(Self Register),
即ActiveX Server本身完成Register和Unregister动作。 对于Delphi编写的ActiveX Server,这些工作都在COMServ.pas完成,
详细的过程比较罗嗦,有兴趣可以去看看,
主要的代码在RegisterTypeLibrary和UnregisterTypeLibrary过程中
和上面的TRegSvr.dpr中对TLB的注册过程大致一样 经过上面的分析可以看到,最终都是通过OleAut32.DLL中的
RegisterTypeLib和UnregisterTypeLib完成的, 我们注意到一点奇怪的现象:
上面提到的源代码在调用RegisterTypeLib时都是直接调用,
该函数的声明在ActiveX.pas中,指定到OleAut32.DLL中的RegisterTypeLib函数
就在相同的地方,我们也看到了UnregisterTypeLib的声明,
但是,上面提到的源代码在调用UnregisterTypeLib时都没有直接调用,
而是先GetModuleHandle('OLEAut32.DLL'),然后用GetProcAddress查找UnregisterTypeLib,
再根据查找的结果进行调用
而且所有相关的地方都是这样进行,估计不是失误,这样看来,
似乎Borland在写这段程序时考虑到了OLEAut32.DLL中不包括UnregisterTypeLib函数的情况,
难道OLEAut32.DLL的早期版本中的确不包括UnregisterTypeLib函数??
但M$DN对UnregisterTypeLib的说明没有提到 6、关于打开类型库时符号重命名(symbol rename)
类型库中某些符号在生成声明单元时被重命名,
大部分是因为符号名与Pascal关键字重名,因此Delphi必须重命名 但前面说到的几个符号的重命名显然不是这个原因,我们注意到:
(1)这几个符号都是CoClass,而且是类型库中几乎全部的CoClass,
只有一个CoClass:"Global"不在其中
(2)这几个符号被重命名后都加上了"Word"前缀,
而这个类型库的名称正好就是"Word"
其中是否存在联系?? 7、对于任意的一个CoClass,从类型库中可以得到其中的interface信息,
因此创建和释放COM对象的代码可以自动生成,
对于所有的interface,也可以从类型库中得到其属性、方法信息,
因此访问这些属性、方法的代码也可以自动生成 由此,Delphi 5 将在声明单元中为所有的CoClass
创建相应的代理类(OLE Server Proxy class),
这些代理类以Delphi类的形式提供封装,而内部实现了对COM对象的全部操作,
包括创建、释放以及访问各种属性和方法
另外,Delphi 5还会将这些代理类作为组件注册到组件板的'Server'页面上
详情请在xxx_TLB.pas中查找"OLE Server Proxy class" 通过这些代理类,我们可以很方便地使用COM对象,
而不必向上面所说的那样一切都通过自己实现,
当然,前面所说的是一切的基础,应该作为原理了解
================================================================
一颗红心向前看,为了革命两茫然,不好意思才囊尽,只能说上一点点。
★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆
★ 我踢 我踢 我踢 我踢 我踢 我踢 我踢 我踢 我踢 ★
★ 你UP 你UP 你UP 你UP 你UP 你UP 你UP 你UP 你UP ★
★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆
===================