应用COM和接口.docx
- 文档编号:8670972
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:48
- 大小:39.15KB
应用COM和接口.docx
《应用COM和接口.docx》由会员分享,可在线阅读,更多相关《应用COM和接口.docx(48页珍藏版)》请在冰豆网上搜索。
应用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
Regsvr32/u
在.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
Regsvr32/u
比如上面的例子:
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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 应用 COM 接口
![提示](https://static.bdocx.com/images/bang_tan.gif)