Matlab与COM应用(三)——Matlab COM客户端支持

转自 http://www.matlabsky.com/forum.php?mod=viewthread&tid=1165

将Matlab作为客户端应用程序,就是编写M语言或者在Matlab命令行中利用Matlab提供的COM客户端函数来实现COM对象的创建、属性的访问、方法的执行和事件的响应。从而实现应用程序的集成。

在matlab天空中,我们讲到Matlab作为客户端的时候,有两种进程:
内进程:Matlab调用DLL文件或者ActiveX控件(比如MSCal.Calendar)
外进程:Matlab调用EXE文件或者应用程序(比如Excel)

由于两者是不同的东西,故需要使用不同的创建函数
ActiveX控件:actxcontrol
Application程序:actxserver

但是对两者的所有操作(属性、方法和事件)都是一致的,故在下面的所有讲解中,我们都会只是以ActiveX控件为例子说明,至于应用程序(外进程)的操作没有特殊说明,则与ActiveX完全一致

在本节我们主要讲到下面的内容:

1.ProgID查询
2.创建COM对象
3.COM对象属性
4.COM对象方法
5.COM对象事件
6.COM相关其他函数
7.COM应用实例
    a.Matlab调用ActiveX控件——MWsamp
    b.Matlab调用Excel软件编程
    c.将Matlab图像和Simulink框图保存到Powerpoint


在正式讲解之前我想说明下三个在COM中经常用到的概念(如果说学过VB的网友应该不会太陌生):

属性:就是对象保存的数据或者信息,可以直接访问或赋值,比如颜色、位置
方法:对象定义的函数,用来实现对象的某一种动作或行为,比如添加、删除
事件:触发某种回调的手段,相当于Matlab的callback,比如单击、双击

1、ProgID的查询

 
 
 
 
 
 
每个COM组件都由唯一的标识符ProgID区别,它是字符串,由商家定义。在编程时,我们需要通过这个唯一的标识符来调用相关组件。

但是我的PC上到底有哪些COM对象和它们的ProgID到底是多少,是进行COM客户端编程的前提。

下面我们讲解下如何查询PC中现有的COM组件:

注意:只有ActiveX可以查询,应用程序的ProgID是没法直接查询的,你只能从厂商那里获取,或者网上找找,故下面的方法只是针对ActiveX而言的。

1、actxcontrollist

此时获取PC中所有ActiveX列表,返回的是一个n*3的cell行数据,每行对应一个COM对象(ActiveX控件)的具体信息,包括名称、ProgID和路径。其实我们需要的就是那个ProgID。
  1. >> info=actxcontrollist%看看PC上有那些ActiveX控件,返回n*3的cell,每行对应一个控件的名称、ProgID和路径
  2. info = 
  3.               [1x31 char]              [1x24 char]    [1x31 char]
  4.               [1x32 char]              [1x25 char]    [1x31 char]
  5.     'AGMEvents Class'                  [1x22 char]    [1x61 char]
  6.               [1x29 char]              [1x21 char]    [1x57 char]
  7.               [1x20 char]              [1x20 char]    [1x64 char]
  8. %由于太多,限于版面,我这里只是列出一部分
  9. %下面看看第3个控件的详细信息
  10. >> inf0{3,:}%不要与我说cell数据不会操作,如果是,查看帮助文档
  11. ans =
  12. AGMEvents Class%控件名称
  13. ans =
  14. AGApplet.AGMEvents.110%控件ProgID
  15. ans =
  16. C:\Program Files\Ansys Inc\v110\AISOL\AGP\intel\AGAppletU.dll%控件路径,可以看出是ansys的一个东东
复制代码

2、actxcontrolselect

在Matlab中输入actxcontrolselect,将以GUI的形式展现PC上所有的ActiveX,并可直接创建相关ActiveX的COM组件

<ignore_js_op>select.jpg 

3、优化大师ActiveX搜索

<ignore_js_op>yhds.jpg

2、创建COM对象

在1#和http://www.matlabsky.com/thread-1164-1-1.html我们讲过
Matlab作为客户端的时候,有两种进程:
内进程:Matlab调用DLL文件或者ActiveX控件(比如MSCal.Calendar)
外进程:Matlab调用EXE文件或者应用程序,其实也可以叫自动化服务(比如Excel)

由于两者是不同的东西,故需要使用不同的创建函数
ActiveX控件:actxcontrol
Application程序:actxserver

1、创建COM ActiveX控件

(1)使用actxcontrol命令

ch = actxcontrol('progid',position,fig_handle,event_handler)

progid:控件的ID,可以通过actxcontrollist查询
position:控件的位置,在figure中的相对位置,[Left Botton Length Height]
fig_handle:句柄,表示在哪个figure中显示,也就是指定控件的装载“容器”
event_handle:事件句柄,就是控件的回调函数的句柄
ch:创建的控件的句柄

注意:由于应用程序没法在figure上显示,故progid必须是控件的ProgID
  1. >>s=get(0,'screensize');
  2. >>fh=figure('position',[s(3)/4 s(4)/4 s(3)/2 s(4)/2],'menubar','none','name','ActiveX Control Demo——by Matlabsky','numbertitle','off','resize','off');
  3. >>ch=actxcontrol('mscal.calendar',[0 0 s(3)/2 s(4)/2],fh)
复制代码
此时创建了一个位于windows屏幕中央的figure(ActiveX的容器),figure中装载着'mscal.calendar'(微软日历)控件

<ignore_js_op>cal.jpg 

(2)使用actxcontrolselect命令

在Matlab中输入actxcontrolselect,将以GUI的形式展现PC上所有的ActiveX,并可直接创建相关ActiveX的COM组件

<ignore_js_op>select.jpg 


2、创建COM自动化服务

sh=actxserver('ProgID','pcname')

progid:应用程序(服务进程)的ID,通过厂商获取
pcname:当使用远程应用程序时,需要输入远程计算机名或者IP地址
sh:返回创建的服务的句柄
  1. >>sh=actxserver('excel.application');
  2. >>sh.visible=1;
复制代码
此时会启动MS的Excel应用程序

注意:我们常遇到的在word或者excel中调用Matlab的,那是Matlab是服务器了,不是现在的客户端

<ignore_js_op>exc.jpg 
2009-4-16 11:52:12 上传
下载附件 (40.5 KB)
 


 

3、COM对象属性设置和获取

现在终于进入到Matlab COM客服端的核心内容了,前面的知识都是铺垫而已。从现在开始正式对COM组件进行操作!

在这里我们主要涉及下面三个内容:
(1)属性的查询
(2)属性获取和设置
(3)添加和删除自定义属性

由于的COM ActiveX控件和COM自动化服务的属性设置、方法条用和事件触发大同小异,没有太大的区别,在没有特殊说明的情况下,则基本完全一致。故在下面的教程中,我们大部分以ActiveX控件进行举例说明,希望大家能举一反三。

为了好下面的说明,我们先建立两个COM对象,图像参见3#
  1. %创建一个ActiveX控件
  2. s=get(0,'screensize');
  3. fh=figure('position',[s(3)/4 s(4)/4 s(3)/2 s(4)/2],'menubar','none','name','ActiveX Control Demo——by Matlabsky','numbertitle','off','resize','off');
  4. ch=actxcontrol('mscal.calendar',[0 0 s(3)/2 s(4)/2],fh);%control handle
  5. %创建一个自动化服务
  6. >>sh=actxserver('excel.application');%server handle
  7. >>sh.visible=1;
复制代码
1、属性查询

要进行属性设置和获取,当然先要知道我们的ActiveX控件到底有那些属性了,在这里我们只要有两种方法:

(1)inspect(ch)
使用Matlab的属性查看器(Properties Inspector)打开控件的属性页,在这里我们不光可以直接进行查询还可以属性设置。其实,在工作空间中双击ActiveX对象句柄也可以打开该属性面板。

<ignore_js_op>inspec.jpg 

(2)propedit(ch)
打开控件自带(内建)的属性设页,同样我们可以进行属性获取和设置。注意不是所有的COM对象都有内建属性页的

<ignore_js_op>prope.jpg 

其实我们还可以通过其他非正式方法获取对象属性,比如在使用actxcontrolselect创建控件的时候就可以直接设置属性,还有get/set(ch)就可以直接获取所有属性。

2、属性获取和设置

这里提供三种方法,具体使用那种可以根据自己的偏爱,但是各种方法的优缺点和实质,我在下面都进行了详细分析。

(1)Matlab经典格式get(ch)/set(ch)
get(ch,'pro')或者get(ch):属性获取
set(ch,'pro','value')或者set(ch):属性设置

当pro属性为空的时候,get(ch)返回控件ch的所有属性的当前值;set(ch)返回ch的所有属性,此时属性值全部为空

此时的get/set函数是Matlab的内部函数,该方法同时设置和获取多个控件、多个属性并且属性名大小写无所谓,但必须使用“'”封闭,对Matlab句柄对象或者GUI熟悉的网友来说这个是会很顺眼的。
  1. >> get(ch)%由于版面这里只列出一部分
  2.              BackColor: 2147483663
  3.                    Day: 5
  4.                DayFont: [1x1 Interface.Standard_OLE_Types.Font]
  5.           DayFontColor: 0
  6.              DayLength: 1
  7.               FirstDay: 7
  8. >> set(ch)
  9. ans = 
  10.              BackColor: {}
  11.                    Day: {}
  12.                DayFont: {}
  13.           DayFontColor: {}
  14.              DayLength: {}
  15.               FirstDay: {}
  16. >>get(ch,{'value','year','month','day'})%使用cell类型,同时获取控件ch的4个属性
  17. ans = 
  18.     '2009-4-16'    [2009]    [4]    [16]
  19. >>set(ch,{'month','day'},{12,5})%同时设置月份和日期两个属性,现在应该是12月5号
复制代码
看看下面两幅图的日期是否改变了,设置后是不是2009.12.5

<ignore_js_op>get2.JPG    

下面再演示下,同时获取和设置多个对象的属性,set/get的更多应用以参考Matlab的帮助文档
  1. f=figure('position',[100 100 500 400],'name','Multi-Pros Demo——by Matlabsky');
  2. h1=actxcontrol('mscal.calendar',[0 200 250 200],f);
  3. h2=actxcontrol('mscal.calendar',[250 200 250 200],f);
  4. h3=actxcontrol('mscal.calendar',[0 0 250 200],f);
  5. h4=actxcontrol('mscal.calendar',[250 0 250 200],f);
  6. H=[h1,h2,h3,h4];
  7. set(H,'day',15);
复制代码
<ignore_js_op>muset.jpg 


(2)VB经典的结构体点连接格式
ch.pro:属性获取
ch.pro=value:属性设置

该格式是VB的经典结构体形式,使用过VB的网友一定会比较熟悉。同样此时的pro不区分大小写,但是每次只能设置和获取一个属性
  1. >> [ch.day ch.DAY ch.dAy]%参数获取,我们可以看出,pro不区分大小写
  2. ans =
  3.      5     5     5
  4. >> ch.day=10%直接赋值就将日期设置为10,注意此时返回的是ch的类型不是日期
  5. ch =
  6.         COM.mscal_calendar
  7. >> ch.day%看看日期是不是修改了
  8. ans =
  9.     10
复制代码
(3)点连接和函数调用综合使用形式
ch.get('pro')或者ch.get():属性获取
ch.set('por','value')或者ch.set():属性设置

由于使用方法和(1)的一致,只是将那个ch放在前面并使用“.”连接而已,具体使用就不再重复了

注意此时的get/set不再是Matlab的那个get/set了,这个是Matlab自动在所有ActiveX控件中添加的方法,也即是说它们是控件ch的一个方法,但是该方法具有Matlab中get/set的所有功能,故该格式综合VB和Matlab的性质。VB的结构体点连接和Matlab的多个属性同时调用


另外我们还可以在工作空间(workspace)中直接双击对象变量名,打开属性查看器,直接查看和编辑属性


3、属性添加和删除

有些情况下控件自带的属性不能够满足我们的需求,此时我们需要向控件添加自己的属性。恩,Matlab为我们呢提供了addproperty和deleteproperty函数,注意这两个函数同get/set一样,既是Matlab内函数,也是控件的方法(Matlab自动为每个控件添加的,而不是控件自带的),当然使用方法和注意事项和get/set很类似了,具体我就不累述了。

ch.addproperty('proname')或者addproperty(ch,'proname'):添加自定义属性
ch.deleteproperty('proname')或者addproperty(ch,'proname'):删除自定义属性

使用上面函数的创建的自定义属性,可以使用get/set命令进行查询和编辑
  1. >>ch.addproperty('copyright');%或者addproperty(ch,'copyright')
  2. >>ch.set('copyright','by matlabsky');%或者set(ch,'copyright','by matlabsky')或者ch.copyright='by matlabsky'
  3. ans =
  4. by matlabsky
  5. >>ch.copyright%或者get(ch,'copyright')或者ch.get('copyright')
  6. >>ch.deleteproperty('copyright');%或者deleteproperty(ch,'copyright')
复制代码

4、COM对象方法调用

所谓方法(methods),就是COM组件对象定义的函数(function),它用来执行对象的某一种动作和行为。

注意:在Matlab创建COM组件时,会自动向组件中添加写方法,比如get/set、invoke、delete等,因此此时控件的方法是有控件自带和Matlab创建的两部分构成的。

对于所有Matlab自动添加的方法,都可以两种执行方式:
(1)Matlab函数调用格式:methodname(ch,var1,var2...),ch是控件句柄,var是参数列表,比如get(ch,'day'),这个只有Matlab自动添加的才有效
(2)点连接函数调用混合方式:ch.methodname(var1,var2),注意大小写必须匹配,和属性的纯点连接形式不一样哦,属性是可以不区分大小写的哦,比如ch.get('day')
(3)使用invoke触发:ch.invoke('methodname',var2,var2...)或者invoke(ch,'methodname',var2,var2...),比如ch.invoke('get','day'),其实这个就是ch.day

对于控件自带的方法,只能使用(2)和(3),比如对于控件自带的NextDay方法,ch.NextDay(注意大小写)是有效的,而nextday(ch)是错误的,因为nextday不Matlab内部函数

因为methodname既是控件的方法,也是Matlab自带函数,因此会出现上面的三种调用格式都是合法的。比如在上一节提到的get/set,还有这一节的invoke等等

1、COM对象方法查询

methods(ch)    显示COM对象ch的所有方法
methods(ch,'-full')     包含每个方法的详细完整说明
methodsview(ch)    使用GUI界面完整的显示所有方法
  1. >> methods(ch)
  2. Methods for class COM.mscal_calendar:
  3. AboutBox         NextYear         PreviousYear     constructorargs  get              move             send             
  4. NextDay          PreviousDay      Refresh          delete           interfaces       propedit         set              
  5. NextMonth        PreviousMonth    Today            deleteproperty   invoke           release          
  6. NextWeek         PreviousWeek     addproperty      events           load             save             
  7. >> methods(ch,'-full')%由于较多我这里只是列出一些
  8. Methods for class COM.mscal_calendar:
  9. HRESULT AboutBox(handle)
  10. HRESULT NextDay(handle)
  11. 。。。。。。。
  12. addproperty(handle, string)
  13. MATLAB array constructorargs(handle)
  14. delete(handle, MATLAB array)
  15. MATLAB array get(handle)
  16. 。。。。。。
  17. >> methodsview(ch)
复制代码
<ignore_js_op>jietu.jpg 

从列表中可以看到,那些以HRESULT作为返回类型的方法,就是控件自带的,而其余都是Matlab自定义的。其实只有列表前头的那些方法才是真正控制对象实现某个功能的。Matlab自定义的只是为了方面执行这些自带的方法。

2、COM对象方法执行(方法很多,但是这里我们只说明使用invoke)

ch.invoke或者invoke(ch)
ch.invoke('methodsname',var1,var2...)或者invoke(ch,'mothodesname',var1,var2...)

第一种形式是返回控件所有自带的方法及具体参数格式,这个与methods函数返回的内容不同
第二种就是执行带输入参数的某个方法
  1. >> ch.invoke
  2.         NextDay = HRESULT NextDay(handle)
  3.         NextMonth = HRESULT NextMonth(handle)
  4.         NextWeek = HRESULT NextWeek(handle)
  5.         NextYear = HRESULT NextYear(handle)
  6.         PreviousDay = HRESULT PreviousDay(handle)
  7.         PreviousMonth = HRESULT PreviousMonth(handle)
  8.         PreviousWeek = HRESULT PreviousWeek(handle)
  9.         PreviousYear = HRESULT PreviousYear(handle)
  10.         Refresh = HRESULT Refresh(handle)
  11.         Today = HRESULT Today(handle)
  12.         AboutBox = HRESULT AboutBox(handle)
  13. >> ch.invoke('previousweek')%前移一个礼拜
  14. ans =
  15.    NaN
复制代码
 
 

5、COM对象事件触发

所谓事件,就是触发某种回调的手段,通常通过控件与用户交互的手段触发,响应某些用户的特殊操作。在Matlab中国COM对象能够响应多种事件,比如鼠标单击、改变对象某个属性等等。

当某个事件发生时,需要调用事件的回调函数,在Matlab中的事件发生的时候,Matlab自动调用某个M文件或者Matlab函数来响应。

1、获取对象事件列表(events是Matlab自动添加的方法)

events(ch)
ch.events
ch.invoke('events')或者invoke(ch,'events')
上面三种方式可以达到同样的效果,显示对象ch的所有事件,但是返回的结果有些不同,大家可以比较下
  1. >> events(ch)
  2. Click = void Click()
  3. DblClick = void DblClick()
  4. KeyDown = void KeyDown(int16 KeyCode, int16 Shift)
  5. KeyPress = void KeyPress(int16 KeyAscii)
  6. KeyUp = void KeyUp(int16 KeyCode, int16 Shift)
  7. BeforeUpdate = void BeforeUpdate(int16 Cancel)
  8. AfterUpdate = void AfterUpdate()
  9. NewMonth = void NewMonth()
  10. NewYear = void NewYear()
  11. >> invoke(ch,'events')
  12. ans = 
  13.            Click: 'void Click()'
  14.         DblClick: 'void DblClick()'
  15.          KeyDown: 'void KeyDown(int16 KeyCode, int16 Shift)'
  16.         KeyPress: 'void KeyPress(int16 KeyAscii)'
  17.            KeyUp: 'void KeyUp(int16 KeyCode, int16 Shift)'
  18.     BeforeUpdate: 'void BeforeUpdate(int16 Cancel)'
  19.      AfterUpdate: 'void AfterUpdate()'
  20.         NewMonth: 'void NewMonth()'
  21.          NewYear: 'void NewYear()'
复制代码
2、注册事件的响应回调函数

ch.registerevent({'eventname',event_hanle})
registerevent(ch,{'eventname',event_handle})
上面的命令就是给对象的eventname事件,添加回调。注意如果eventname不指定或者为空的话,那默认给ch所有事件添加同一个回调
比如给ch添加如下回调:
先编写单击回调函数click(单击时日历控件会自动将日期切换到那一天):
  1. function click(handles,eventID,eventName,varargin)%输入参数格式必须这么写
  2. %hanles就是COM对象的句柄
  3. %eventID事件的ID
  4. %eventName事件的详细信息包括Type、Source和EventsID
  5. %varargin其它输入参数
  6. disp('执行的是单击(click),日期已改变!')
  7. disp(['您选中的日期为:' handles.value])%会自动切换到点击的那一天
复制代码
再编写双击回调函数dblclick(日历控件没有定义双击,我们设置为前移一个礼拜):
  1. function click(handles,eventID,eventName,varargin)%输入参数格式必须这么写
  2. %hanles就是COM对象的句柄
  3. %eventID事件的ID
  4. %eventName事件的详细信息包括Type、Source和EventsID
  5. disp('执行的是单击(click),日期已改变!')
  6. disp(['您选中的日期为:' handles.value])
复制代码
现在注册两个回调函数:
  1. >>registerevent(ch,{'click',@click,'dblclick',@dblclick})%单击双击分开注册,没有注册的为空
  2. %现在双击和单击试试看看有什么效果
  3. %这里是点击的效果
  4. 执行的是单击(click),日期已改变!
  5. 您选中的日期为:2009-2-16
  6. %这里是双击的效果,注意此时会先执行单击再执行双击回调,因为双击可以分为按下和弹起
  7. 执行的是单击(click),日期已改变!
  8. 您选中的日期为:2009-2-24
  9. 执行的是双击(dblclick),日期后移一个礼拜!
  10. 双击后日期为:2009-2-17
  11. >>registerevent(ch,@click)%此时将所有没有注册事件回调函数设置为click,注意刚才注册双击不会被覆盖
  12. %我们在日历控件上点击、敲下键盘看是不是得到一样的反应,结果如下
  13. %鼠标单击的效果,其实同时执行了多个回调
  14. 执行的是单击(click),日期已改变!
  15. 您选中的日期为:2009-2-11
  16. 执行的是单击(click),日期已改变!
  17. 您选中的日期为:2009-2-11
  18. 执行的是单击(click),日期已改变!
  19. 您选中的日期为:2009-2-11
  20. %敲键盘的效果,其实同时执行了多个回调
  21. 执行的是单击(click),日期已改变!
  22. 您选中的日期为:2009-2-12
  23. 执行的是单击(click),日期已改变!
  24. 您选中的日期为:2009-2-12
  25. 执行的是单击(click),日期已改变!
  26. 您选中的日期为:2009-2-12
复制代码
3、已注册事件查询

有时我们需要知道到底那些事件已注册了,恩,Matlab提供了eventlisteners函数
eventlisteners(ch)或者ch.eventlisteners
  1. >> ch.eventlisteners
  2. ans = 
  3.     'click'           @click   
  4.     'dblclick'        @dblclick
  5.     'DblClick'        @click   
  6.     'KeyDown'         @click   
  7.     'KeyPress'        @click   
  8.     'KeyUp'           @click   
  9.     'BeforeUpdate'    @click   
  10.     'AfterUpdate'     @click   
  11.     'NewMonth'        @click   
  12.     'NewYear'         @click   
复制代码
4、撤销事件回调

unregisterevent(ch,@event_callback)%注销回调函数为event_callback的事件回调
unregisterevent(ch,{'eventname',@event_callback})%注销指定事件的指定回调,注意一次只能撤销一个,如果输入多个那么只是撤销第一个
unregisterallevents(ch)%撤销ch的所有回调,一次性
 
 

6、COM相关其他函数介绍

 
 
其实前面的介绍已经将Matlab调用其他COM组件讲解的很详细了,并且教程都是按大家思维整理的,详细说明的共同点和差异。接下来就差实践了!

但是为了大家更好的读懂某些应用程序和充分应用COM技术,我再补充几个在COM涉及的函数。

在这里值说明该函数是干什么的,不做具体说明,感兴趣的网友可以直接查看Matlab帮助文档。

delete:程序结束时需要删除创建的COM对象
release:释放接口
interfaces:列出COM对象的自定义端口
isa:判断是不是属于某个类型
iscom:判断是不是COM对象
isevent:判断是否为COM对象的事件(callback)
ismethod:是否为方法
isinterface:是否为接口
isprop:是否为属性
save:将COM对象保存为mat文件
load:从mat文件中加载COM对象
move:移动和重设ActiveX的位置和尺寸

posted @ 2013-01-14 15:39  renly2013  阅读(2279)  评论(0编辑  收藏  举报