使用MFC开发ActiveX控件(3)
属性、方法以及事件的添加

图5 属性的添加

图6 方法的添加
对ActiveX控件属性、方法和事件的添加均有库存和自定义两种。其中对属性和方法的添加在MFC ClassWizard对话框的Automation页中通过按钮"Add Property…"和"Add Method…"弹出如图5和图6所示的添加属性和添加方法的对话框来完成。对于库存属性和方法,可以直接从External name组合框的下拉列表中选取,Implementation项将自动设置为Stock。对于自定义属性和方法的添加与在自动化对象中为接口添加属性和方法的过程一样,ClassWizard将在.odl文件和控件类生成相应的代码,下面给出的是在控件类中实现的部分分发映射代码:
在这里共添加了一个自定义方法MessageLen()和三种库存属性BackColor、Caption和ForeColor(分别表示控件的背景色、标题和前台色)、两个以Get/Set方式获取的自定义属性XPos、YPos和一个以成员变量方式实现的自定义属性Message。这几个自定义属性分别表示要显示字符串的x、y坐标和要显示的内容。对于采取Get/Set方式获取的属性,应当在控件类中为其添加相应的成员函数,并修改其Get、Set成员函数的实现过程:
对于以成员变量方式创建的属性Message,向导还为其生成了一个消息响应函数:
只要该属性的值被更改,OnMessageChanged()函数即会被调用。
为了使上述属性设置如背景色、前景色等能够与控件实际联系起来,需要替换控件类OnDraw()函数中由向导生成的那部分代码。例如,下面这段代码即以前面添加的属性设置作为参数值,在控件中显示一串字符:
为了使属性设置更改后,其效果能够立即在控件上显示出来,应当在与属性设置相关的函数实现中调用InvalidateControl()以更新控件的显示。
可以编译程序并在ActiveX Control Test Container工具中对其进行测试。在插入控件后,通过"Invoke Methods…"菜单项弹出如图7所示的对话框。在Method Name组合框中可以选择要测试的属性和方法。其中,对于属性的测试分别有ProgGet和ProgSet的说明以指出是对属性值的获取与设置。在Parameter编辑框中输入要设置的参数及其对应的参数类型,点击SetValue按钮将把该参数值添加到参数列表框,最后点击Invoke按钮将在控件应用设置的属性并执行指定的方法。对于有返回值的方法,其执行结果将在Return编辑框中显示。如果出现了异常操作,在Exception编辑框中将会显示出相应的异常错误信息。图8给出了经过属性设置的控件界面。

图7 对属性、方法的测试

图8 设置了属性后的控件
对于控件属性的添加,在MFC ClassWizard对话框的ActiveX Events页中通过"Add Event…"按钮弹出如图9所示的"Add Event"事件添加对话框。与方法、属性的添加类似,在External name组合框中可以输入要添加的自定义事件名称,也可以从下拉列表选择库存事件。Implementation项将根据所要添加的事件类型而自动设置Stock或Custom选项。ActiveX控件将通过添加的事件来通知容器程序有特定的事件发生,库存事件多为键盘、鼠标事件,将由COleControl自动进行处理。对于自定义事件,则只是在.odl文件和控件类中添加了事件映射表等必要的代码(代码附下),至于应当在何种条件下触发该事件须由开发人员自行编写代码。

图9 事件的添加
上述代码添加了一个MsgOut的自定义事件,可以在通过调用FireMsgOut()来激发。下面对Message属性的OnMessageChanged()消息响应函数进行修改,每当Message属性内容被更改都会调用该函数,在该函数中调用此前添加的MessageLen()方法以确定更改后的Message属性的字符串长度,在长度大于10时调用FireMsgOut()触发MsgOut事件:

图10 选择要记录的事件
在用ActiveX Control Test Container对刚添加的事件进行测试时,首先通过"Control"菜单下的"Logging…"菜单项弹出如图10所示的对话框,并从"Events"属性页中选中要跟踪记录的事件。当通过Invoke Methods对话框设置Message属性的内容超过10个字符后,位于程序框架下方的分割视图将记录控件所触发的MsgOut事件(如图11所示)。

图11 对事件的测试

图5 属性的添加

图6 方法的添加
对ActiveX控件属性、方法和事件的添加均有库存和自定义两种。其中对属性和方法的添加在MFC ClassWizard对话框的Automation页中通过按钮"Add Property…"和"Add Method…"弹出如图5和图6所示的添加属性和添加方法的对话框来完成。对于库存属性和方法,可以直接从External name组合框的下拉列表中选取,Implementation项将自动设置为Stock。对于自定义属性和方法的添加与在自动化对象中为接口添加属性和方法的过程一样,ClassWizard将在.odl文件和控件类生成相应的代码,下面给出的是在控件类中实现的部分分发映射代码:
…… // Dispatch maps //{{AFX_DISPATCH(CSample68Ctrl) CString m_message; afx_msg void OnMessageChanged(); afx_msg short GetXPos(); afx_msg void SetXPos(short nNewValue); afx_msg short GetYPos(); afx_msg void SetYPos(short nNewValue); afx_msg short MessageLen(); //}}AFX_DISPATCH DECLARE_DISPATCH_MAP() // Dispatch and event IDs public: enum { //{{AFX_DISP_ID(CSample68Ctrl) dispidMessage = 1L, dispidXPos = 2L, dispidYPos = 3L, dispidMessageLen = 4L, //}}AFX_DISP_ID }; …… BEGIN_DISPATCH_MAP(CSample68Ctrl, COleControl) //{{AFX_DISPATCH_MAP(CSample68Ctrl) DISP_PROPERTY_NOTIFY(CSample68Ctrl, "Message", m_message, OnMessageChanged, VT_BSTR) DISP_PROPERTY_EX(CSample68Ctrl, "XPos", GetXPos, SetXPos, VT_I2) DISP_PROPERTY_EX(CSample68Ctrl, "YPos", GetYPos, SetYPos, VT_I2) DISP_FUNCTION(CSample68Ctrl, "MessageLen", MessageLen, VT_I2, VTS_NONE) DISP_STOCKPROP_BACKCOLOR() DISP_STOCKPROP_CAPTION() DISP_STOCKPROP_FORECOLOR() //}}AFX_DISPATCH_MAP END_DISPATCH_MAP() …… |
在这里共添加了一个自定义方法MessageLen()和三种库存属性BackColor、Caption和ForeColor(分别表示控件的背景色、标题和前台色)、两个以Get/Set方式获取的自定义属性XPos、YPos和一个以成员变量方式实现的自定义属性Message。这几个自定义属性分别表示要显示字符串的x、y坐标和要显示的内容。对于采取Get/Set方式获取的属性,应当在控件类中为其添加相应的成员函数,并修改其Get、Set成员函数的实现过程:
short m_nYPos; short m_nXPos; …… short CSample68Ctrl::GetXPos() { return m_nXPos; } void CSample68Ctrl::SetXPos(short nNewValue) { m_nXPos = nNewValue; SetModifiedFlag(); } short CSample68Ctrl::GetYPos() { return m_nYPos; } void CSample68Ctrl::SetYPos(short nNewValue) { m_nYPos = nNewValue; SetModifiedFlag(); } |
对于以成员变量方式创建的属性Message,向导还为其生成了一个消息响应函数:
void CSample68Ctrl::OnMessageChanged() { SetModifiedFlag(); } |
只要该属性的值被更改,OnMessageChanged()函数即会被调用。
为了使上述属性设置如背景色、前景色等能够与控件实际联系起来,需要替换控件类OnDraw()函数中由向导生成的那部分代码。例如,下面这段代码即以前面添加的属性设置作为参数值,在控件中显示一串字符:
// 用背景色设置画刷 CBrush Brush(TranslateColor(GetBackColor())); // 用前台色设置字体颜色 pdc->SetTextColor(TranslateColor(GetForeColor())); // 绘制背景 pdc->FillRect(rcBounds, &Brush); // 设置字体背景透明 pdc->SetBkMode(TRANSPARENT); // 显示字符 pdc->TextOut(m_nXPos, m_nYPos, m_message); |
为了使属性设置更改后,其效果能够立即在控件上显示出来,应当在与属性设置相关的函数实现中调用InvalidateControl()以更新控件的显示。
可以编译程序并在ActiveX Control Test Container工具中对其进行测试。在插入控件后,通过"Invoke Methods…"菜单项弹出如图7所示的对话框。在Method Name组合框中可以选择要测试的属性和方法。其中,对于属性的测试分别有ProgGet和ProgSet的说明以指出是对属性值的获取与设置。在Parameter编辑框中输入要设置的参数及其对应的参数类型,点击SetValue按钮将把该参数值添加到参数列表框,最后点击Invoke按钮将在控件应用设置的属性并执行指定的方法。对于有返回值的方法,其执行结果将在Return编辑框中显示。如果出现了异常操作,在Exception编辑框中将会显示出相应的异常错误信息。图8给出了经过属性设置的控件界面。

图7 对属性、方法的测试

图8 设置了属性后的控件
对于控件属性的添加,在MFC ClassWizard对话框的ActiveX Events页中通过"Add Event…"按钮弹出如图9所示的"Add Event"事件添加对话框。与方法、属性的添加类似,在External name组合框中可以输入要添加的自定义事件名称,也可以从下拉列表选择库存事件。Implementation项将根据所要添加的事件类型而自动设置Stock或Custom选项。ActiveX控件将通过添加的事件来通知容器程序有特定的事件发生,库存事件多为键盘、鼠标事件,将由COleControl自动进行处理。对于自定义事件,则只是在.odl文件和控件类中添加了事件映射表等必要的代码(代码附下),至于应当在何种条件下触发该事件须由开发人员自行编写代码。

图9 事件的添加
dispinterface _DSample68Events { properties: // Event interface has no properties methods: // NOTE - ClassWizard will maintain event information here. // Use extreme caution when editing this section. //{{AFX_ODL_EVENT(CSample68Ctrl) [id(1)] void MsgOut(); //}}AFX_ODL_EVENT }; …… // Event maps //{{AFX_EVENT(CSample68Ctrl) void FireMsgOut() {FireEvent(eventidMsgOut,EVENT_PARAM(VTS_NONE));} //}}AFX_EVENT DECLARE_EVENT_MAP() // Dispatch and event IDs public: enum { //{{AFX_DISP_ID(CSample68Ctrl) …… eventidMsgOut = 1L, //}}AFX_DISP_ID }; …… BEGIN_EVENT_MAP(CSample68Ctrl, COleControl) //{{AFX_EVENT_MAP(CSample68Ctrl) EVENT_CUSTOM("MsgOut", FireMsgOut, VTS_NONE) //}}AFX_EVENT_MAP END_EVENT_MAP() |
上述代码添加了一个MsgOut的自定义事件,可以在通过调用FireMsgOut()来激发。下面对Message属性的OnMessageChanged()消息响应函数进行修改,每当Message属性内容被更改都会调用该函数,在该函数中调用此前添加的MessageLen()方法以确定更改后的Message属性的字符串长度,在长度大于10时调用FireMsgOut()触发MsgOut事件:
void CSample68Ctrl::OnMessageChanged() { InvalidateControl(); if (MessageLen() >= 10) FireMsgOut(); SetModifiedFlag(); } |

图10 选择要记录的事件
在用ActiveX Control Test Container对刚添加的事件进行测试时,首先通过"Control"菜单下的"Logging…"菜单项弹出如图10所示的对话框,并从"Events"属性页中选中要跟踪记录的事件。当通过Invoke Methods对话框设置Message属性的内容超过10个字符后,位于程序框架下方的分割视图将记录控件所触发的MsgOut事件(如图11所示)。

图11 对事件的测试
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了