• 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的位置和尺寸

  • 相关阅读:
    样式表中!important的用法
    ORA27101: shared memory realm does not exist问题的解决
    重置标识列的当前值
    ASP.NET Oracle数据库使用事务时注意事项
    Oracle中约束的添加方法总结
    HTML段落自动换行的样式设置
    ASP.NET应用程序中的服务器错误
    oracle中的rownum、order by与分页
    position:relative与float的区别
    Moss/Sharepoint 备份或还原时出错的处理(持续更新)
  • 原文地址:https://www.cnblogs.com/renly/p/2859812.html
Copyright © 2020-2023  润新知