ActiveX控件的应用与工作原理。ActiveX控件的编写,如何为控件安排属性,方法,事件,属性页,持久性存储,控件如何通知容器自身属性的改变。如何注册控件与取消控件注册。在VB和VC中访问ActiveX控件。 1.基本概念 容器和服务器程序 容器应用程序是可以嵌入或链接对象的应用程序。Word就是容器应用程序。 服务器应用程序是创建对象并且当对象被双击时,可以被启动的应用程序。Excel就是服务器应用程序。 ActiveX相当于不能独立运行的服务器程序,可用VB6来测试VC编写的ActiveX控件,OCX是ActiveX控件的后缀名(也有其他的后缀名)。ActiveX开发后可提供给VB/VC/Delphi使用。 一个ActiveX控件一般会提供方法、属性和事件三种特性。它底层是COM……我还不懂的 2.新建一个MFC ActiveX ControlWizard的工程,Clock时钟控件。在一个ocx文件中可包含多个ActiveX控件,如VB中的Common Controls 6.0。可以添加许可文件runtime license。 默认有App-COleControlModule--CWinApp、Ctrl-COleControl--CWnd和PropPage-COlePropertyPage--CDialog类。 两外还有两个接口:_DClock _DClockEvents,供容器程序使用。 调试的时候,选择系统的ActiveX Control Test Container,然后插入Insert控件,按c l可定为到Clock控件。这个是画一个椭圆。 VC中调试运行ocx控件的时候,会注册ActiveX控件,用RegSvr32程序把信息写入注册表中。VB/VC都从注册表中去搜寻ocx控件信息,然后都列出来。ActiveX控件使用之前都需要注册。 若想取消ocx的注册:可运行regsvr32 /u 文件名(可输入前面指令,然后把文件拖到运行对话框中)。 当我们用regsvr32 /u的时候,它加载此ocx,并调用其中的STDAPI DllUnregisterServer(void)全局函数。 若直接regsvr32 文件名,就是注册控件。这时调用的是其中的STDAPI DllRegisterServer(void)全局函数。 3.在Ctrl类的OnDraw函数中,注释掉默认那两句话(话椭圆用的),在OnDraw函数中输入: CTime time=CTime::GetCurrentTime(); CString str=time.Format("%H:%M:%S"); pdc->TextOut(0,0,str); //这时就可输出当前时间 为了让时间动起来,可加一个计时器;在Ctrl中增加消息处理:WM_CREATE; 在OnCreate函数中:SetTimer(1,1000,NULL); //此函数的提示有误(前面没有hWnd) 再增加一个WM_TIMER消息,写时间响应:Invalidate(); //使窗口无效,然后重绘。 这样时间控件的时间就开始走动了。 也可调用COleControl::InvalidateControl void InvalidateControl( LPCRECT lpRect = NULL ); 添加背景色、前景色属性:选择ClassWizard类向导,选择AutoMation选项页,选择该类,增加属性,有标准属性可选。选择BackColor Stock;ForeColor Stock. ActiveX控件的四种属性 Stock:为每个控件提供的标准属性,如字体或颜色。 Ambient:围绕控件的环境属性——已被置入容器的属性。这些属性不能被更改,但控件可以使用它们调整自己的属性。 Extended:这些是由容器处理的属性,一般包括大小和在屏幕上的位置。 Custom:由控件开发者添加的属性。 获取设置颜色: COleControl::GetBackColor OLE_COLOR GetBackColor( ); COleControl::TranslateColor //转换颜色值 COLORREF TranslateColor( OLE_COLOR clrColor, HPALETTE hpal = NULL ); COleControl::SetBackColor //设置背景颜色的值(只是值而已) void SetBackColor( OLE_COLOR dwBackColor ); //注意SetBkColor设置文本背景 在OnDraw函数中添加: CBrush brush(TranslateColor(GetBackColor())); pdc->FillRect(rcBounds, &brush); pdc->SetTextColor(TranslateColor(GetForeColor())); pdc->SetBkMode(TRANSPARENT); //设置背景透明(否则文字的背景和控件背景不一样) 4.属性页 在Ctrl类的PROPPAGEIDS映射中,修改添加为: BEGIN_PROPPAGEIDS(CClockCtrl,2) PROPPAGEID(CClockPropPage::guid) PROPPAGEID(CLSID_CColorPropPage) END_PROPPAGEIDS(CClockCtrl) 添加时间间隔属性(自定义属性),外部名称External name:Interval,类型是short。产生一个OnIntervalChanged函数,在此属性被修改的时候调用。还可选择成员变量或Get/Set方法。 这时m_Interval和OnIntervalChanged的声明在调度映射DISPATCH中,调度映射是声明给外部使用的属性和方法。 CWnd::KillTimer BOOL KillTimer( int nIDEvent ); //关闭定时器事件。销毁先前的定时器。 在OnIntervalChanged函数中添加: if(m_interval<0 || m_interval>6000) { m_interval=1000; } else { m_interval=m_interval/1000*1000; //取整 KillTimer(1); SetTimer(1,m_interval,NULL); } 调试的时候可在ContainerTest中使用Control中的mothods方法测试参数。但这时在VB中设置了之后,运行的时候 参数没有起作用。??&& 编辑默认的属性页,删除之前的标签,添加一个静态文本Interval: IDC_EDIT_INTERVAL,再添加一个编辑框Edit,输入要设置的间隔值。给Edit关联成员变量 m_updateInterval value short 还可关联属性,名称为外部名称Interval。但这时设置了之后,VB运行窗体仍没有改变设置。 5.添加方法:类向导--automation属性页 Ctrl类,增加方法--外部名称Hello,内部名称(控件中使用),参数用void。 然后在Ctrl类的Hello函数中添加 MessageBox("Hello World!"); 编译后可在Control Test Container中用invoke methods来测试方法,也可在VB中添加一个按钮,来调用控件的方法(这时在代码中修改Interval就能生效了) 添加事件:方法类似上面--选择ActiveX Events,添加事件(有标准事件)——先添加一个Click事件 Stock。 这时在DClockEvents添加了这个Click事件。DClockEvents是一个源接口,通过这个接口来向容器发送事件消息,然后容器实现相应代码。 再添加一个自定义事件:可在DClockEvents右键--添加事件:外部名NewMinute,内部名FireNewMinute。 在OnDraw函数中添加判断:在GetCurrentTime后面 if(!time.GetSecond()) { FireNewMinute(); //发出事件通知,调用DClockEvents发送给容器 } 6.这时设置的前景色和背景色都可以保存下来,而设置的Interval却不能保存。要使属性具有持久性。 在Ctrl类中有个DoPropExchange函数,其中有提示: // TODO: Call PX_ functions for each persistent custom property. 这里我们定义的是short型的,所以调用PX_Short,数据就有了持久性。 PX_Short BOOL PX_Short( CPropExchange* pPX, LPCTSTR pszPropName, short& sValue ); BOOL PX_Short( CPropExchange* pPX, LPCTSTR pszPropName, short& sValue, short sDefault); //pPX是CPropExchange对象的指针;交流的属性名称(外部);属性存储的指示(成员变量);属性的默认值 这里写入: PX_Short(pPX,"Interval",m_interval,1000); 但这时关闭打开工程后属性值已经持久了,但控件运行效果还是以前的。因为创建的时候用的是1000,我们将Create函数改写一下: SetTimer(1,m_interval,NULL); 自定义的属性值在发生改变的时候要发送改变信息给容器,这时要调用 COleControl::BoundPropertyChanged //Bound捆绑的 void BoundPropertyChanged( DISPID dispid ); //The dispatch ID of a bound property of the control. 在DClock中定义了属性:如 [id(DISPID_BACKCOLOR), bindable, requestedit] OLE_COLOR BackColor; [id(DISPID_FORECOLOR), bindable, requestedit] OLE_COLOR ForeColor; [id(1)] short Interval; //前面就是调度ID号。(方法也有) 在OnIntervalChanged函数中,修改: if(m_interval<0 || m_interval>6000) { m_interval=1000; } else { m_interval=m_interval/1000*1000; //取整 KillTimer(1); SetTimer(1,m_interval,NULL); BoundPropertyChanged(0x1); //这里用十六进制,最好把这个拿到if外面去 } 7.让控件在设计时不运行: 获取周围属性:COleControl::AmbientUserMode BOOL AmbientUserMode( ); //觉得容器是设计时还是运行时。FALSE则为设计时 在OnTimer消息函数中添加判断: if(AmbientUserMode()) InvalidateControl(); 可以在MSDN输入COleControl浏览ActiveX Control的相关说明。 8.在VC中调用ActiveX控件: test container中可设置option去掉设计时的勾选,就是运行时了。当ocx编写好了,就可选择Win32 release版本发行了,这样文件就小些了,因为没有包含调试信息了。 再新建一个基于对话框的ClockTest工程:在窗体上点右键,插入ActiveX控件,选择时钟控件。可修改属性,点击左下角预览对话框。 也可选中工程--增加到工程--组件和控件--选择已注册的ActiveX控件。这时工具箱就增加了这个控件的图标。 添加此控件到窗体后,程序就增加了一个类,就可以动态产生时钟控件了。 给CClockTestDlg添加一个CClock m_clock private成员变量。在头文件中包含一个Clock.h. 添加一个按钮,调用此类对象的方法: m_clock.Create("Clock",WS_CHILD | WS_VISIBLE,CRect(0,0,100,50),this,123); //创建控件 m_clock.Hello(); //调用方法 m_clock.SetBackColor(RGB(0,0,225)); m_clock.SetForeColor(RGB(255,0,0)); //设置属性 事件的访问,对控件点右键选择类向导或直接选事件--可选择相应的消息:如这里就有Click和NewMinute。 要动态创建事件响应的话,可根据MFC自己创建的一些代码做事件响应。……例如: BEGIN_EVENTSINK_MAP(CClockTestDlg, CDialog) //{{AFX_EVENTSINK_MAP(CClockTestDlg) ON_EVENT(CClockTestDlg, IDC_CLOCKCTRL1, -600 /* Click */, OnClickClockctrl1, VTS_NONE) ON_EVENT(CClockTestDlg, IDC_CLOCKCTRL1, 1 /* NewMinute */, OnNewMinuteClockctrl1, VTS_NONE) ON_EVENT(CClockTestDlg, 123, -600 /* Click */, OnClickClockctrl1, VTS_NONE) //修改ID就可以了 ON_EVENT(CClockTestDlg, 123, 1 /* NewMinute */, OnNewMinuteClockctrl1, VTS_NONE) //}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP()
(孙鑫 十八)ActiveX 控件
最新推荐文章于 2021-02-17 11:24:52 发布