转自 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。
- >> info=actxcontrollist%看看PC上有那些ActiveX控件,返回n*3的cell,每行对应一个控件的名称、ProgID和路径
- info =
- [1x31 char] [1x24 char] [1x31 char]
- [1x32 char] [1x25 char] [1x31 char]
- \'AGMEvents Class\' [1x22 char] [1x61 char]
- [1x29 char] [1x21 char] [1x57 char]
- [1x20 char] [1x20 char] [1x64 char]
- %由于太多,限于版面,我这里只是列出一部分
- %下面看看第3个控件的详细信息
- >> inf0{3,:}%不要与我说cell数据不会操作,如果是,查看帮助文档
- ans =
- AGMEvents Class%控件名称
- ans =
- AGApplet.AGMEvents.110%控件ProgID
- ans =
- C:\Program Files\Ansys Inc\v110\AISOL\AGP\intel\AGAppletU.dll%控件路径,可以看出是ansys的一个东东
复制代码
2、actxcontrolselect
在Matlab中输入actxcontrolselect,将以GUI的形式展现PC上所有的ActiveX,并可直接创建相关ActiveX的COM组件
<ignore_js_op>
3、优化大师ActiveX搜索
<ignore_js_op>
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
- >>s=get(0,\'screensize\');
- >>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\');
- >>ch=actxcontrol(\'mscal.calendar\',[0 0 s(3)/2 s(4)/2],fh)
复制代码
此时创建了一个位于windows屏幕中央的figure(ActiveX的容器),figure中装载着\'mscal.calendar\'(微软日历)控件
<ignore_js_op>
(2)使用actxcontrolselect命令
在Matlab中输入actxcontrolselect,将以GUI的形式展现PC上所有的ActiveX,并可直接创建相关ActiveX的COM组件
<ignore_js_op>
2、创建COM自动化服务
sh=actxserver(\'ProgID\',\'pcname\')
progid:应用程序(服务进程)的ID,通过厂商获取 pcname:当使用远程应用程序时,需要输入远程计算机名或者IP地址 sh:返回创建的服务的句柄
- >>sh=actxserver(\'excel.application\');
- >>sh.visible=1;
复制代码
此时会启动MS的Excel应用程序
注意:我们常遇到的在word或者excel中调用Matlab的,那是Matlab是服务器了,不是现在的客户端
<ignore_js_op>
|
|
3、COM对象属性设置和获取
现在终于进入到Matlab COM客服端的核心内容了,前面的知识都是铺垫而已。从现在开始正式对COM组件进行操作!
在这里我们主要涉及下面三个内容: (1)属性的查询 (2)属性获取和设置 (3)添加和删除自定义属性
由于的COM ActiveX控件和COM自动化服务的属性设置、方法条用和事件触发大同小异,没有太大的区别,在没有特殊说明的情况下,则基本完全一致。故在下面的教程中,我们大部分以ActiveX控件进行举例说明,希望大家能举一反三。
为了好下面的说明,我们先建立两个COM对象,图像参见3#
- %创建一个ActiveX控件
- s=get(0,\'screensize\');
- 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\');
- ch=actxcontrol(\'mscal.calendar\',[0 0 s(3)/2 s(4)/2],fh);%control handle
- %创建一个自动化服务
- >>sh=actxserver(\'excel.application\');%server handle
- >>sh.visible=1;
复制代码
1、属性查询
要进行属性设置和获取,当然先要知道我们的ActiveX控件到底有那些属性了,在这里我们只要有两种方法:
(1)inspect(ch) 使用Matlab的属性查看器(Properties Inspector)打开控件的属性页,在这里我们不光可以直接进行查询还可以属性设置。其实,在工作空间中双击ActiveX对象句柄也可以打开该属性面板。
<ignore_js_op>
(2)propedit(ch) 打开控件自带(内建)的属性设页,同样我们可以进行属性获取和设置。注意不是所有的COM对象都有内建属性页的
<ignore_js_op>
其实我们还可以通过其他非正式方法获取对象属性,比如在使用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熟悉的网友来说这个是会很顺眼的。
- >> get(ch)%由于版面这里只列出一部分
- BackColor: 2147483663
- Day: 5
- DayFont: [1x1 Interface.Standard_OLE_Types.Font]
- DayFontColor: 0
- DayLength: 1
- FirstDay: 7
- >> set(ch)
- ans =
- BackColor: {}
- Day: {}
- DayFont: {}
- DayFontColor: {}
- DayLength: {}
- FirstDay: {}
- >>get(ch,{\'value\',\'year\',\'month\',\'day\'})%使用cell类型,同时获取控件ch的4个属性
- ans =
- \'2009-4-16\' [2009] [4] [16]
- >>set(ch,{\'month\',\'day\'},{12,5})%同时设置月份和日期两个属性,现在应该是12月5号
复制代码
看看下面两幅图的日期是否改变了,设置后是不是2009.12.5
<ignore_js_op>
下面再演示下,同时获取和设置多个对象的属性,set/get的更多应用以参考Matlab的帮助文档
- f=figure(\'position\',[100 100 500 400],\'name\',\'Multi-Pros Demo——by Matlabsky\');
- h1=actxcontrol(\'mscal.calendar\',[0 200 250 200],f);
- h2=actxcontrol(\'mscal.calendar\',[250 200 250 200],f);
- h3=actxcontrol(\'mscal.calendar\',[0 0 250 200],f);
- h4=actxcontrol(\'mscal.calendar\',[250 0 250 200],f);
- H=[h1,h2,h3,h4];
- set(H,\'day\',15);
复制代码
<ignore_js_op>
(2)VB经典的结构体点连接格式 ch.pro:属性获取 ch.pro=value:属性设置
该格式是VB的经典结构体形式,使用过VB的网友一定会比较熟悉。同样此时的pro不区分大小写,但是每次只能设置和获取一个属性
- >> [ch.day ch.DAY ch.dAy]%参数获取,我们可以看出,pro不区分大小写
- ans =
- 5 5 5
- >> ch.day=10%直接赋值就将日期设置为10,注意此时返回的是ch的类型不是日期
- ch =
- COM.mscal_calendar
- >> ch.day%看看日期是不是修改了
- ans =
- 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命令进行查询和编辑
- >>ch.addproperty(\'copyright\');%或者addproperty(ch,\'copyright\')
- >>ch.set(\'copyright\',\'by matlabsky\');%或者set(ch,\'copyright\',\'by matlabsky\')或者ch.copyright=\'by matlabsky\'
- ans =
- by matlabsky
- >>ch.copyright%或者get(ch,\'copyright\')或者ch.get(\'copyright\')
- >>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界面完整的显示所有方法
- >> methods(ch)
- Methods for class COM.mscal_calendar:
- AboutBox NextYear PreviousYear constructorargs get move send
- NextDay PreviousDay Refresh delete interfaces propedit set
- NextMonth PreviousMonth Today deleteproperty invoke release
- NextWeek PreviousWeek addproperty events load save
- >> methods(ch,\'-full\')%由于较多我这里只是列出一些
- Methods for class COM.mscal_calendar:
- HRESULT AboutBox(handle)
- HRESULT NextDay(handle)
- 。。。。。。。
- addproperty(handle, string)
- MATLAB array constructorargs(handle)
- delete(handle, MATLAB array)
- MATLAB array get(handle)
- 。。。。。。
- >> methodsview(ch)
复制代码
<ignore_js_op>
从列表中可以看到,那些以HRESULT作为返回类型的方法,就是控件自带的,而其余都是Matlab自定义的。其实只有列表前头的那些方法才是真正控制对象实现某个功能的。Matlab自定义的只是为了方面执行这些自带的方法。
2、COM对象方法执行(方法很多,但是这里我们只说明使用invoke)
ch.invoke或者invoke(ch) ch.invoke(\'methodsname\',var1,var2...)或者invoke(ch,\'mothodesname\',var1,var2...)
第一种形式是返回控件所有自带的方法及具体参数格式,这个与methods函数返回的内容不同 第二种就是执行带输入参数的某个方法
- >> ch.invoke
- NextDay = HRESULT NextDay(handle)
- NextMonth = HRESULT NextMonth(handle)
- NextWeek = HRESULT NextWeek(handle)
- NextYear = HRESULT NextYear(handle)
- PreviousDay = HRESULT PreviousDay(handle)
- PreviousMonth = HRESULT PreviousMonth(handle)
- PreviousWeek = HRESULT PreviousWeek(handle)
- PreviousYear = HRESULT PreviousYear(handle)
- Refresh = HRESULT Refresh(handle)
- Today = HRESULT Today(handle)
- AboutBox = HRESULT AboutBox(handle)
- >> ch.invoke(\'previousweek\')%前移一个礼拜
- ans =
- NaN
复制代码
|
5、COM对象事件触发
所谓事件,就是触发某种回调的手段,通常通过控件与用户交互的手段触发,响应某些用户的特殊操作。在Matlab中国COM对象能够响应多种事件,比如鼠标单击、改变对象某个属性等等。
当某个事件发生时,需要调用事件的回调函数,在Matlab中的事件发生的时候,Matlab自动调用某个M文件或者Matlab函数来响应。
1、获取对象事件列表(events是Matlab自动添加的方法)
events(ch) ch.events ch.invoke(\'events\')或者invoke(ch,\'events\') 上面三种方式可以达到同样的效果,显示对象ch的所有事件,但是返回的结果有些不同,大家可以比较下
- >> events(ch)
- Click = void Click()
- DblClick = void DblClick()
- KeyDown = void KeyDown(int16 KeyCode, int16 Shift)
- KeyPress = void KeyPress(int16 KeyAscii)
- KeyUp = void KeyUp(int16 KeyCode, int16 Shift)
- BeforeUpdate = void BeforeUpdate(int16 Cancel)
- AfterUpdate = void AfterUpdate()
- NewMonth = void NewMonth()
- NewYear = void NewYear()
- >> invoke(ch,\'events\')
- ans =
- Click: \'void Click()\'
- DblClick: \'void DblClick()\'
- KeyDown: \'void KeyDown(int16 KeyCode, int16 Shift)\'
- KeyPress: \'void KeyPress(int16 KeyAscii)\'
- KeyUp: \'void KeyUp(int16 KeyCode, int16 Shift)\'
- BeforeUpdate: \'void BeforeUpdate(int16 Cancel)\'
- AfterUpdate: \'void AfterUpdate()\'
- NewMonth: \'void NewMonth()\'
- NewYear: \'void NewYear()\'
复制代码
2、注册事件的响应回调函数
ch.registerevent({\'eventname\',event_hanle}) registerevent(ch,{\'eventname\',event_handle}) 上面的命令就是给对象的eventname事件,添加回调。注意如果eventname不指定或者为空的话,那默认给ch所有事件添加同一个回调 比如给ch添加如下回调: 先编写单击回调函数click(单击时日历控件会自动将日期切换到那一天):
- function click(handles,eventID,eventName,varargin)%输入参数格式必须这么写
- %hanles就是COM对象的句柄
- %eventID事件的ID
- %eventName事件的详细信息包括Type、Source和EventsID
- %varargin其它输入参数
- disp(\'执行的是单击(click),日期已改变!\')
- disp([\'您选中的日期为:\' handles.value])%会自动切换到点击的那一天
复制代码
再编写双击回调函数dblclick(日历控件没有定义双击,我们设置为前移一个礼拜):
- function click(handles,eventID,eventName,varargin)%输入参数格式必须这么写
- %hanles就是COM对象的句柄
- %eventID事件的ID
- %eventName事件的详细信息包括Type、Source和EventsID
- disp(\'执行的是单击(click),日期已改变!\')
- disp([\'您选中的日期为:\' handles.value])
复制代码
现在注册两个回调函数:
- >>registerevent(ch,{\'click\',@click,\'dblclick\',@dblclick})%单击双击分开注册,没有注册的为空
- %现在双击和单击试试看看有什么效果
- %这里是点击的效果
- 执行的是单击(click),日期已改变!
- 您选中的日期为:2009-2-16
- %这里是双击的效果,注意此时会先执行单击再执行双击回调,因为双击可以分为按下和弹起
- 执行的是单击(click),日期已改变!
- 您选中的日期为:2009-2-24
- 执行的是双击(dblclick),日期后移一个礼拜!
- 双击后日期为:2009-2-17
- >>registerevent(ch,@click)%此时将所有没有注册事件回调函数设置为click,注意刚才注册双击不会被覆盖
- %我们在日历控件上点击、敲下键盘看是不是得到一样的反应,结果如下
- %鼠标单击的效果,其实同时执行了多个回调
- 执行的是单击(click),日期已改变!
- 您选中的日期为:2009-2-11
- 执行的是单击(click),日期已改变!
- 您选中的日期为:2009-2-11
- 执行的是单击(click),日期已改变!
- 您选中的日期为:2009-2-11
- %敲键盘的效果,其实同时执行了多个回调
- 执行的是单击(click),日期已改变!
- 您选中的日期为:2009-2-12
- 执行的是单击(click),日期已改变!
- 您选中的日期为:2009-2-12
- 执行的是单击(click),日期已改变!
- 您选中的日期为:2009-2-12
复制代码
3、已注册事件查询
有时我们需要知道到底那些事件已注册了,恩,Matlab提供了eventlisteners函数 eventlisteners(ch)或者ch.eventlisteners
- >> ch.eventlisteners
- ans =
- \'click\' @click
- \'dblclick\' @dblclick
- \'DblClick\' @click
- \'KeyDown\' @click
- \'KeyPress\' @click
- \'KeyUp\' @click
- \'BeforeUpdate\' @click
- \'AfterUpdate\' @click
- \'NewMonth\' @click
- \'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的位置和尺寸
|
|
请发表评论