应用COM和接口.docx

上传人:b****6 文档编号:8670972 上传时间:2023-02-01 格式:DOCX 页数:48 大小:39.15KB
下载 相关 举报
应用COM和接口.docx_第1页
第1页 / 共48页
应用COM和接口.docx_第2页
第2页 / 共48页
应用COM和接口.docx_第3页
第3页 / 共48页
应用COM和接口.docx_第4页
第4页 / 共48页
应用COM和接口.docx_第5页
第5页 / 共48页
点击查看更多>>
下载资源
资源描述

应用COM和接口.docx

《应用COM和接口.docx》由会员分享,可在线阅读,更多相关《应用COM和接口.docx(48页珍藏版)》请在冰豆网上搜索。

应用COM和接口.docx

应用COM和接口

第六讲应用COM和接口

前面我们已经说明,.NET战略的一个重要方面,就是弱化COM的应用,这似乎是说,我们不再需要研究COM了,但事实并非如此,其中一个重要的原因,是COM已经流行了十年,而且,COM也是微软和其它众多软件开发的基础,更不用说,.NET平台本身还使用了COM+技术。

基于这一系列的原因,我们不得不来研究在.NET中应用COM和接口的有关问题。

在这一讲里,我们将首先对COM做一个简要的回顾,其实COM的问题并不太复杂,但是令人费解的是,很多软件方面的著作,都把COM作为一个重要的主题来研究,其实这是没有太多的必要的。

我们研究这一讲的内容的时候,首先要记住的是,在很大程度上.NET是从COM演变来的,按照进化的观点,COM类似于Lucy(古埃塞俄比亚的南猿),所以如果它显得比较笨的话,你不要太介意,因为没有笨拙的COM,就没有流畅的.NET。

一、COM简介

COM(ComponentObjectModel)也就是组件对象模型,是微软为编程创建语言独立性所做的第一次好的尝试。

COM是一种用于说明如何建立软件组件的规范,由于使用了统一的接口规范,不同的开发人员创建的COM组件,可被组合进不同的应用程序中,而且这些COM组件所使用的语言,可以是完全不同的。

例如,你可以在VC++程序中调用VB组件,反之亦然。

这对于一个开发软件的集体来说,是有很大的意义的。

DCOM(DistributedComponentObjectModel)分布式组件对象模型,这是一种分布式应用程序集成到网络的技术,一个分布式应用程序由多个进程组成,这些进程协作完成一项工作。

DCOM为COM组件之间的通信透明的提供可靠、安全和有效的支持,这些组件包括ActiveX,脚本和Java小程序。

DCOM可将其应用程序分布到最适合于其顾客和应用程序的位置。

在很大程度上,DCOM是带宽、部署和防火墙问题的综合,所以也就决定了它不会为太多的人所认可。

际上并不知道自己在开发COM对象。

讨论这个问题的意义在于,假定一个企业的系统,已经长期的很好的使用一个COM对象,现在,企业系统要用.NET升级,这就面另两个选择:

第一种,一切重新开始,用新的平台特性,开发新的内容,当然这是很好的,但有时候并不一定合算。

第二种,一些经过考验被认为合理的组件,还可以在.NET平台上使用,这将会大大减少开发时间和难度,我们下面要讨论的就是这种方法。

我们首先在VC++中开发一个COM组件,然后讨论在.NET上的应用问题。

二、在C++中开发COM组件

VC++一直是专业开发人员最青睐的语言之一,现在的VC++.NET,不但保留了原来的VC++6.0的能力,而且还提供的平台托管代码的编写能力,可谓如虎添翼。

这里主要利用VC++开发标准的COM组件,然后用C#调用。

开发COM组件,首先必须生成四个标准函数:

DllRegisterServer:

实现在注册表中注册COM服务的功能。

DllUnregisterServer:

和上面的功能刚好相反,实现在注册表中注销的功能。

DllCanUnloadNow:

用来检测是否可以从内存中卸载COM服务器。

如果COM客户第一个调用COM服务,系统会自动把COM服务载入内存,但又有客户访问COM服务的时候,只是增加COM服务被调用的计数,当计数为0时,则自动卸载。

DllGetClassObject:

返回COM类对象的指针。

COM技术的原理是比较复杂的,好在VC++提供了活动模板库(ATL),可以帮组我们完成标准的框架部分,我们只要关心我们必需处理的属性和方法就可以了。

下面讨论一个最简单的例子,但是这个例子表达了VC++生产COM组件最重要的要素,通过这个例子,更复杂的东西也能够做出来。

首先生成一个ATL项目。

名字为:

myCom

因为要处理字符串(CString),所以选择支持MFC。

这里不需要属性化。

添加一个类。

选择:

ALT简单对象。

给对象恰当的名字。

注意,对象可以有多个。

名字为:

MyShow

添加一个属性:

Name,返回值为BSTR。

这是可以在COM对象之间传递的字符串格式。

添加方法:

HelloiWorld。

主要目的是把Name属性的字符串处理以后输出。

参数为:

BSTR*,这表达一个输出的字符串指针。

加入一个求和方法:

Sum

注意:

返回类型必须是HRESULT,真正的返回值是在参数属性中选择“类型*”(指针),然后,选择retval。

不选则为void。

in,表达为传入值,一般用值类型。

out为参数表的传出值(out),调用的时候必须out,

retval为返回值。

乘法:

Multiply

同样的方法,加入乘法的方法:

Multiply

处理代码,文档:

MyShow.cpp

//保留属性的值。

//因为要处理汉字,这里使用CStringW

//此外还有CString、CStringA

CStringWstrName;

STDMETHODIMPCMyShow:

:

get_Name(BSTR*pVal)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

//TODO:

在此添加实现代码

//返回值,注意CString向BSTR的转换

*pVal=strName.AllocSysString();

returnS_OK;

}

STDMETHODIMPCMyShow:

:

put_Name(BSTRnewVal)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

//传入值

strName=newVal;

//TODO:

在此添加实现代码

returnS_OK;

}

STDMETHODIMPCMyShow:

:

HelloWorld(BSTR*s)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

//TODO:

在此添加实现代码

//注意,字符串是如何拼接的

CStringWmessage("你好,你的名字是:

");

message+=strName;

*s=message.AllocSysString();

returnS_OK;

}

STDMETHODIMPCMyShow:

:

Sum(DOUBLEx,DOUBLEy,DOUBLE*s)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

//TODO:

在此添加实现代码

//注意,如何把处理的结果返回

*s=x+y;

returnS_OK;

}

STDMETHODIMPCMyShow:

:

Multiply(DOUBLEx,DOUBLEy,DOUBLE*s)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

//TODO:

在此添加实现代码

//同样要把处理的结果返回

*s=x*y;

returnS_OK;

}

生成的时候同时注册。

必要的时候,可以人工注册和卸载:

Regsvr32/s\.DLL----注册

Regsvr32/u\.DLL----注销

在.NET中应用。

myComLib.IMyShowobj=newmyComLib.MyShowClass();

//加法

privatevoidbutton1_Click(objectsender,System.EventArgse)

{

textBox3.Text=obj.Sum(double.Parse(textBox1.Text),double.Parse(textBox2.Text)).ToString();

}

//减法

privatevoidbutton2_Click(objectsender,System.EventArgse)

{

textBox3.Text=obj.Multiply(double.Parse(textBox1.Text),double.Parse(textBox2.Text)).ToString();

}

//写属性

privatevoidbutton3_Click(objectsender,System.EventArgse)

{

obj.Name=textBox1.Text;

}

//读属性

privatevoidbutton4_Click(objectsender,System.EventArgse)

{

textBox3.Text=obj.Name;

}

//调HelloWorld

privatevoidbutton5_Click(objectsender,System.EventArgse)

{

textBox3.Text=obj.HelloWorld();

}

结果应该是没有问题的。

三、在Delphi中开发COM组件

很多语言都有生成COM组件的能力,下面做一个Delphi的例子。

1〉新建ActiveX库

file->new->other->ActiveX->ActiveXLibray

OK

产生一个项目文件

DllGetClassObject,

DllCanUnloadNow,

DllRegisterServer,

DllUnregisterServer;

2〉创建COM对象

File->new->Other->ActiveX->COMobject

OK

类对话框:

输入类名:

比如MyShow

出现一个统一的类生成器:

IMyShow----接口

MyShow----实现这个接口的对象

在IMyShow右键-〉New->Property

添加一个属性,Name名字起为:

Name

再添加一个方法:

Method

Name名字起为:

HelloName

关于属性,一般的形式是:

protected

functionGet_name:

WideString;stdcall;

procedureSet_name(constValue:

WideString);stdcall;

end;

....

functionTMyShows.Get_name:

WideString;

begin

end;

procedureTMyShows.Set_name(constValue:

WideString);

begin

end;

也就是说返回的是function,进入的是procedure。

当使用字符串

的时候(WideString),对应的为BSTR。

为了达到这个目的,在建立属性的时候,要注意:

Get:

Type->BSTR

Parameters->删除

set:

Type->Void

Parameters->ValueBSTR[in]

这样就能造成上面的效果。

refresh--->刷新

形成程序的框架,并在框架中写入自己的内容:

具体处理的程序可以这样写:

varUsername:

string;

functionTMyShows.Get_name:

WideString;

begin

Result:

=WideString(Username);

end;

procedureTMyShows.Set_name(constValue:

WideString);

begin

Username:

=String(Value);

end;

关于方法,去掉返回值就是过程,否则是函数:

procedureTMyShows.helloName;

begin

showmessage('您的名字是:

'+Username);

end;

这里要注意一个问题,messagebox(0,'','',mb_ok)和showmessage('')

需要Dialogs库,需要把它Uses进来。

完成的源程序如下:

--------------------------------------------------------------

unitUnit1;

{$WARNSYMBOL_PLATFORMOFF}

interface

uses

Windows,ActiveX,Classes,ComObj,Project1_TLB,StdVcl,Dialogs;

type

TMyShows=class(TTypedComObject,IMyShows)

protected

functionGet_name:

WideString;stdcall;

procedureSet_name(constValue:

WideString);stdcall;

procedurehelloName;stdcall;

end;

implementation

usesComServ;

varUsername:

string;

functionTMyShows.Get_name:

WideString;

begin

Result:

=WideString(Username);

end;

procedureTMyShows.Set_name(constValue:

WideString);

begin

Username:

=String(Value);

end;

procedureTMyShows.helloName;

begin

showmessage('您的名字是:

'+Username);

end;

initialization

TTypedComObjectFactory.Create(ComServer,TMyShows,Class_MyShows,

ciMultiInstance,tmApartment);

end.

----------------------------------------------------------------

File->Saveall保存

Project->Build编译

Run->RegisterActiveXServer注册

3)注册和注销组件

使用COM组件以前,先要确认它在计算机上是可以使用的,所以必须注册,注册DLL有两种方法:

1.在delphi中编译DLL,编译的同时自动在所编译的计算机上注册,(文件-〉生成工程.DLL)。

2.使用Regsvr32.exe(在Windows\system中,或WINNT\system32中),方法:

Windows开始-〉运行

Regsvr32/s\.DLL----注册

Regsvr32/u\.DLL----注销

比如上面的例子:

Regsvr32“d:

\MyShow\Helloname.dll”

注册是注册在系统注册表中,所以也可以用regedit.exe来查看,对于注销组件,可以在系统注册表中删除该组件的引用,然后再删除该组件的DLL或EXE文件。

注意:

COM类的注册表条目位于系统注册表的HKEY_CLASSES_ROOT中。

四、在.NET中应用COM组件

首先建立一个Windows工程。

Project1.MyShowobj=newProject1.MyShowClass();

privatevoidForm1_Load(objectsender,System.EventArgse)

{

}

privatevoidbutton1_Click(objectsender,System.EventArgse)

{

obj.Name=textBox1.Text;

}

privatevoidbutton2_Click(objectsender,System.EventArgse)

{

obj.HelloName();

}

可以看出来,和普通的类使用上是一样的。

五、Activex控件

ActiveX控件是充分利用OLE和ActiveX技术的自定义控件。

ActiveX控件是基于与应用程序无关的思想而设计的。

可以简单的认为ActiveX控件合并了VBX技术和ActiveX标准。

VBX是VisualBasic提出的一个技术标准。

Microsoft的VisualBasic是第一个引入向市场供应软件组件构想。

但软件组件重复性使用的概念是早于VisualBasic提出的,而且它早已根植于面向对象编程的理论中。

VisualBasic提出了组件的概念,定义了建立与描述新控件的标准方式。

VisualBasic提出的第一个技术标准是VBX。

这是16位版本Delphi中完全可以使用的一个16位标准。

在32位的操作平台中,Microsoft使用了功能更强,更为开放的Activex控件来代替VBX标准。

ActiveX控件的结构

ActiveX控件的好处在于它的可编程性和可重用性。

它能够嵌入到目前大多数的开发环境中,包括Delphi、VisualBasic、Oracle、Developer2000等。

它在这些开发环境中的表现,和Delphi的组件在IDE环境中的表现完全相同,都有自己的属性、方法和事件。

ActiveX控件最理想的用途是在网上作为传送小型程序的载体。

何时使用ActiveX控件

没有可用的Delphi组件能满足你特殊的需要。

你想使用多中编程语言进行开发,想在多个开发平台之间共享一些控件。

ActiveX控件的缺点

最明显的问题是,Delphi组件能够直接内建到应用程序的可执行文件中,直接与应用程序和其他组件进行通信的;但ActiveX控件是通过COM与应用程序通信的。

ActiveX控件是一种“最小公分母”的解决方案,因而没有完全挖掘出开发工具的能力。

第一个自制的ActivX控件

希望做一个ActiveX控件,能显示系统时间,同时显示的周期可以由外部参数控制。

一、首先清空Form;

二、File--New--Other--ActiveX--ActiveForm--Ok

三、其中遇到NewActiveXName:

自己给控件起名;

比如这里写上Showtime。

下面的多选框选择可选可不选。

这样就产生了三个单元,其中第三个是类库(TLB),一般不要动。

四、在System页--加入Timer

Standard页--加入Label(改变字体和字号)

五、Timer的Interval属性定为1000,表示每隔1000毫秒触发一下。

给Timer的Timer1Timer事件加一句显示系统时间:

label1.Caption:

=timetostr(Time);

六、现在要给控件增加一个属性,用外部数据来控制触发间隔,也就是Timer的Interval属性。

菜单--Viwe--typeLibrary--可以看到Form的属性

增加属性:

Newproporty(注意是图标)--Name:

属性的名字。

如果是可读写的,就有两个属性函数,一个是Get,另一个是Set。

刷新(RefreshImplementation)后在ShowtimeImpl1单元里可以看到两个get函数和set过程,把相应的程序写进去。

vari:

integer;

procedureTShowtime.Button1Click(Sender:

TObject);

begin

ifi=1then

begin

Panel1.Color:

=clRed;

i:

=0;

end

else

begin

Panel1.Color:

=clGreen;

i:

=1;

end;

end;

functionTShowtime.Get_mytime:

Integer;

begin

result:

=timer1.interval;

end;

procedureTShowtime.Set_mytime(Value:

Integer);

begin

timer1.interval:

=value;

end;

七、在project--build进行编译、保存。

八、注册:

Run--RegisterActiveXServer--产生一个OCX文件。

实际上一个Activex已经完成了。

注意一下,ActiveX控件有个新的属性AxBorderstyle--边界风格:

另外:

mytime是自己给出的控制内部元件的属性,这里是时钟的触发周期。

在.NET中使用这个控件。

可以看出来,由于COM接口的标准化,不管你是用什么语言写的COM组件,都可以很好的用在.NET系统里面,所需要注意的就是由于COM组件的特点,这些组件使用以前必须经过注册,否则无法使用。

六、在.NET程序中使用Word

微软的Office,是一套功能强大的办公软件,更重要的,它也是一套COM自动化系统,你可以在任何支持COM的语言体系中调用它的功能。

首先引入Word的COM组件在MicrosoftWord9.0ObjectLibray。

DimWORAsNewWord.ApplicationClass()

'定义公文

DimWODAsNewWord.DocumentClass()

PrivateSubButton1_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesButton1.Click

WOD=WOR.Documents.Add

WOR.Caption="我的标题栏"

WOR.Options.CheckSpellingAsYouType=False

WOR.Options.CheckGrammarAsYouType=False

'WOD.Sentences.Last.Paste()

WOD.Range.InsertAfter("我的文字")

WOD.Range.InsertAfter("其它的文字")

'WOR.Visible=True

'WOR.PrintPreview()=True

'WOR.Pri

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1