(孙鑫 十八)ActiveX 控件

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()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值