第18章 Active控件

转自: https://blog.csdn.net/u014162133/article/details/46573873

 

 

容器和服务器程序

 

容器应用程序时可以嵌入或链接对象的应用程序。Word就是容器应用程序。

 

服务器应用程序是创建对象并且当对象被双击时,可以被启动的应用程序。Excel就是服务器应用程序。

 

ActiveX控件不能独立运行,它必须被嵌入容器应用程序中,和容器应用程序一起运行。

 

 

 

Dispatch maps调度映射,主要是MFC提供让外部应用程序可以访问控件的属性和方法

 

Event maps事件映射,控件向包含它的容器发送事件通知

 

 

 

接口是外部程序和控件进行通信的协议,可以把接口看作是函数的集合,外部程序通过接口提供的方法,去访问控件的属性和方法。接口中所定义的所有函数都是纯虚函数

 

 

 

regsvr32 ...注册控件  regsvr32 /u....卸载控件

 

 

 

STDAPI DllRegisterServer(void)将控件信息写入注册表中

 

STDAPI DllUnregisterServer(void)卸载注册信息。

 

 

 

制作一个时间控件,在

 

void CClockCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,

 

 const CRect& rcInvalid)中添加以下代码:

 

 CBrush brush(TranslateColor(GetBackColor()));

 

 pdc->FillRect(rcBounds,&brush);

 

 pdc->SetBkMode(TRANSPARENT);

 

 pdc->SetTextColor(TranslateColor(GetForeColor()));

 

 //为控件设置属性,必须在MFC ClassWizared中为控件添加属性,上面几行代码才有用

 

 

 

 CTime time=CTime::GetCurrentTime();

 

 CString str=time.Format("%H : %M : %S");

 

 pdc->TextOut(0,0,str);

 

这样就能做出一个静态的时间控件,如果我们想使控件实时显示时间,需要添加两个消息响应函数  WM_CREATE,WM_TIMER.

 

代码:

 

int CClockCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)

 

{

 

 if (COleControl::OnCreate(lpCreateStruct) == -1)

 

  return -1;

 

 

 

 // TODO:  在此添加您专用的创建代码

 

 

 

 SetTimer(1,1000,NULL);

 

 return 0;

 

}

 

 

 

void CClockCtrl::OnTimer(UINT nIDEvent)

 

{

 

 // TODO: 在此添加消息处理程序代码和/或调用默认值

 

 Invalidate();    //立即引起窗口重绘

 

   //也可以使用InvalidateControl();  //强制窗口重绘,效果相同

 

 COleControl::OnTimer(nIDEvent);

 

}

 

要修改控件的背景色前景色和字体颜色

 

在OnDraw中添加

 

 CBrush brush(TranslateColor(GetBackColor()));

 

 pdc->FillRect(rcBounds,&brush);

 

 pdc->SetBkMode(TRANSPARENT);

 

 pdc->SetTextColor(TranslateColor(GetForeColor()));

 

 

 

ActiveX控件的四种属性

 

Stock:为每个控件提供的标准属性,如字体或颜色。

 

Ambient:围绕控件的环境属性——已被置入容器的属性。这些属性不能被修改,但控件可以使用它们调整自己的属性。

 

Extended:这些是由容器处理的属性,一般包括大小和在屏幕上的位置。

 

Custom:由控件开发者添加的属性。

 

 

 

使控件具有多于一个属性页

 

首先在**ctl.cpp中找到Property Pages,代码如下:

 

BEGIN_PROPPAGEIDS(CClockCtrl, 2)

 

 PROPPAGEID(CClockPropPage::guid)

 

 PROPPAGEID(CLSID_CColorPropPage)

 

END_PROPPAGEIDS(CClockCtrl)

 

需要注意的是要显示几个属性页BEGIN_PROPPAGEIDS(CClockCtrl, 2)中的代码为几,如果没有修改或修改错误,会产生不可预料错误。

 

 

 

要增加标准属性,在_DClock上点击右键,选择增加属性,选中Stock,例如选择背景色和前景色

 

接下来会在Clock.odl下生成以下代码:

 

 dispinterface _DClock

 

 {

 

  properties:

 

  [id(DISPID_BACKCOLOR), helpstring("属性 BackColor")] OLE_COLOR BackColor;

 

  [id(DISPID_FORECOLOR), helpstring("属性 ForeColor")] OLE_COLOR ForeColor;

 

methods:

 

   [id(DISPID_ABOUTBOX)] void AboutBox();

 

 };

 

 

 

接下来新增自定义属性,方法同上,只是需选中“成员变量”或“get/put”

 

会自动生成成员变量:m_Interval,和成员函数OnIntervalChanged。

 

接下来添加代码:

 

void CClockCtrl::OnIntervalChanged(void)

 

{

 

 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 

 

 

 // TODO: 在此添加属性处理程序代码

 

 if(m_Interval<0 || m_Interval>6000)

 

 {

 

  m_Interval=2000;

 

 }

 

 KillTimer(1);

 

 SetTimer(1,m_Interval/1000*1000,NULL);

 

 

 

 SetModifiedFlag();

 

}

 

测试:运行ActiveX测试器,选择control---〉Invoke Methods对m_Interval进行修改。

 

 

 

为编辑框增加成员变量MFC ClassWizard-->Member Variables-->Add Member Variable-->

 

Optional  property  name:

 

选择自定义属性的外部名,这样我们不需要增加代码就能把控件和自定义属性相关联。

 

在void CClockPropPage::DoDataExchange(CDataExchange* pDX)中会生成下面代码:

 

 DDP_Text(pDX, ID_EDIT_INTERVAL, m_updateInterval, _T("Interval") );

 

 DDX_Text(pDX, ID_EDIT_INTERVAL, m_updateInterval);

 

 

 

在.NET2003下我始终找不到“Optional  property  name:”在哪,所以在我属性页上的编辑框无效,我只能选择control---〉Invoke Methods进行修改。

 

 

 

为控件增加函数,MFC ClassWizard-->Member Variables-->Add Method

 

Class Name要选择CClockCtrl

 

输入函数名,之后就可以在CClockCtrl类中找到了

 

 

 

我们选择MFC ClassWizard-->ActiveX Events--->Add Event

 

之后会在DClockEvents中增加一个事件,DClockEvents接口是源接口,控件将用这个接口发送通知事件,它不是控件本身实现的接口,这个接口是通过容器来实现的

 

 

 

 

 

如果要将自定义的控件属性保存下来,需要在

 

void CClockCtrl::DoPropExchange(CPropExchange* pPX)加入如下代码:

 

PX_Short(pPX,"Interval",m_interval,1000);

 

之后再在程序中修改代码:

 

 PX_Short(pPX,"Interval",m_interval,1000);

 

如果想使自定义控件属性实时地显示在容器属性列表中,

 

在void CClockCtrl::OnIntervalChanged() 中加入如下代码:

 

 BoundPropertyChanged(0x1);   //调度代码为1

 

如果希望用户在设计模式时时钟控件停止运行,而在用户模式下运行,可以

 

在void CClockCtrl::OnTimer(UINT nIDEvent)下修改代码如下:

 

 if(AmbientUserMode())   //查询环境属性

 

  InvalidateControl();

 

posted @ 2018-08-13 19:01  ~小小鸟~  阅读(265)  评论(0编辑  收藏  举报