1、ActiveX控件:
1> 不能独立运行,必须嵌入到某个容器程序中,与该容器一起运行,可看成是一个极小的服务器应用程序。
2> 一个典型的ActiveX控件,它具有方法、属性、事件这三种特性
3> 一个文件中可以包含多个ActiveX控件
4> 在实际编程时,我们可以将常用的功能封装在一个ActiveX控件中
5> 对ActiveX来说,它的底层实际上是采用COM技术实现的
6> OCX是ActiveX控件的一种后缀名,但ActiveX控件对应的文件也可以是其他后缀名,例如DLL
7> 容器应用程序:可以嵌入或链接对象的应用程序。
服务器应用程序:是创建对象并且当对象被双击时,可以被启动的应用程序。
2、CClockApp:应用程序类,实际上代表了空间本身
CClockCtrl:视类(或主窗口类),对控件窗口进行的操作都将在此类中完成,它有一OnDraw函数,在重绘时调用
CClockPrepPage:对话框类
3、三个映射:
消息映射(Message maps)
调度映射(Dispatch maps):MFC提供的一种映射机制,主要是为了让外部应用程序可以方便地访问控件的属性和方法
事件映射(Event maps):MFC提供的一种映射机制,让控件可以向包含它的容器发送事件通
4、接口:是控件与外部程序进行通信的协议。可以把接口看成是函数的集合,外部程序通过这个接口所暴露出来的方法访问控件的属性和方法。实际上,可以把接口看作是一个抽象基类,在此接口中定义的所有函数都是纯虚函数,这些函数的实现在CClockCtrl类中完成的,所以通过该接口调用的函数实际上调用的是CClockCtrl类中真正实现的函数。
注:如果两个通信实体要通过接口进行通信,那么肯定是其中的的一个实体实现该接口所显露出来的方法,另一个实体通过接口调用这些方法。
5、ActiveX控件的注册和取消注册操作
1> 取消注册:regsvr32 /u 控件完整路径名,此命令实际上是调用DllUnregisterServer函数(该控件自身的一个函数)
2> 注册:regsvr32 控件完整路径名,次命令是调用DllRegisterServer函数(该控件自身的一个函数)
3> 编译时->regsvr32程序->DllRegisterServer函数(进行控件的注册)
6、获取系统当前时间:
1> OnDraw函数中:
CTime time=CTime::GetCurrentTime();
CString str=time.Format(_T("%H:%M:%S"));
pdc->TextOutW(0, 0, str);
2> 添加WM_CREATE消息的响应函数,并在其中设置定时器:
SetTimer(1, 1000, NULL);
3> 添加WM_CREATE消息的响应函数,并在其中进行窗口刷新:
Invalidate();
//或InvalidateControl(); 强制控件重绘自身,如果参数是NULL,那么整个控件都将被重绘
7、增加ActiveX空间的属性页
1> 增加属性:类视图-->ActiveX**Lib(接口)-->_DActiveX**-->右键“添加”-->添加属性
2> 在Ctrl类的OnDraw函数中编写相应代
CBrush brush(TranslateColor(GetBackColor())); //获得背景色画刷
pdc->FillRect(rcBounds, &brush); //设置背景色
pdc->SetBkMode(TRANSPARENT); //设置文字背景为透明模式
pdc->SetTextColor(TranslateColor(GetForeColor())); //设置文字颜色为前景色
CTime time=CTime::GetCurrentTime();
CString str=time.Format(_T("%H:%M:%S"));
pdc->TextOutW(0, 0, str);
3> TranslateColor函数:实现类型转换OLE_COLOR->COLORREF
4> 作为ActiveX控件来说,它会提供一个属性表单,用来对这个ActiveX空间进行设置
5> 增加属性页:通过使用CClockPropPage类的全局惟一标识符(guid)调用PROPPAGEID宏增加属性页
guid是一个128位的整数,用来唯一地标识一个组件,或者一个接口。
对ActiveX控件来说,其颜色属性页的guid值是CLSID_CColorPropPage
注:一定要相应的增加属性页的总数
6> 增加颜色属性页:
BEGIN_PROPPAGEIDS(CActiveX_clock3Ctrl, 2)
PROPPAGEID(CActiveX_clock3PropPage::guid)
PROPPAGEID(CLSID_CColorPropPage) //增加此行
END_PROPPAGEIDS(CActiveX_clock3Ctrl)
8、自定义属性:选择MemberVariable或Get/Set members
eg:增加时间间隔属性(当Interval这一外部属性被修改时,就会调用这个OnIntervalChanged函数)
void CActiveX_clock3Ctrl::OnIntervalChanged(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加属性处理程序代码
if(this->m_Interval<0 || m_Interval>6000)
{
m_Interval=1000;
}
else
{
m_Interval=m_Interval/1000*1000; //将用户的输入信息取整
KillTimer(1);
SetTimer(1, m_Interval, NULL);
}
SetModifiedFlag(); //用来设置属性被修改的标记
}
9、为ActiveX控件添加一个自定义的方法
1> 类视图-->ActiveX**Lib(接口)-->_DActiveX**-->右键“添加”-->添加方法
2> 两处改变:1)_DClock接口下增加了一个方法:Hello[eg]
2)在Ctrl类中提供了该方法的实现,可以在此方法中进行相应的操作
3> 添加方法时,外部名称(External name)是给外部程序使用控件的方法时使用的;内部名称(Internal name)是在控件内部使用的方法名称,它可以与外部名称不一样。
10、ActiveX控件有两种事件:标准事件和自定义事件
1> 添加标准事件:ctrl右键-->添加-->事件【stock事件,即标准事件】
源接口:表示控件将使用这个接口来发送通知事件,这个接口不是控件本身实现的接口。
[default, source] dispinterface _DActiveX_clock3Events;
_DClockEvents接口中的方法是由容器实现的。容器通过一种机制知道控件中定义了一个源接口,于是它就实现该接口。
容器的接口是由容器来定义还是由控件来定义是无所谓的,关键是痛惜的双方能够遵照同一个接口进行通信就可以了。
2>自定义事件:ctrl右键-->添加-->事件【添加External name和FireNewMinute】
Ctrl类中自动添加了FireNewMinute方法,用于向容器发出事件通知。
Ctrl的OnDraw函数中添加:
if(0==time.GetMinute()) //如果秒数为0
{
FireNewMinute(); //向容器发出NewMinute事件通知。而NewMinute事件是由容器实现的。
}
3>对标准事件来说,其触发过程由MFC底层实现。但对自定义事件来说,必须要在某个条件到来时,在代码中显式地调用某个函数发出该事件通知
11、在对话框上添加ActiveX控件:
1> 右键/插入ActiveX控件
2> 【工具/选择工具箱项/COM组件/勾选目标ActiveX/...】(此时,工具箱中自动添加了相应的控件)
3> 动态添加
12、在VC中,对ActiveX控件的属性和方法都是通过相应的函数来访问的。而对ActiveX控件的事件的访问,则通过为其添加事件响应函数来实现,具体操作如同给一个按钮添加消息响应函数一样。
13、属性的持久性
1> 每一个具有持久性的自定义属性调用以"PX_"开有的函数。如,可以将short型的属性,调用PX_Short函数,让其具有持久性。
2> 控件自定义属性值发生变化后,应调用函数BoundPropertyChanged函数,通知容器绑定的属性值已经发生了变化,从而让容器做出相应的调整。
14、环境属性
1> 在容器中使用ActiveX控件时,分为两种情况:一种是在设计模式下(design mode),一种是在运行模式下(user mode)。
2> 容器知道控件是处于设计模式还是处于运行模式;而在这两种模式下控件都已经产生,因此控件本身无法知道自己的状态。
3> AmbientUserMode函数:返回非0,说明控件是处于运行模式下;返回0,说明处于设计模式下。
4> 在编程中,有时可以根据控件的环境属性调整控件的行为。如果想得到环境属性,可以利用Ambient开头的函数去获取。