编写ActiveX控件


              (1)一是从MFC提供的控件类派生一个新类,通过合理地设计派生类,可以修改控件的行为和属性以达到用户的要求,但此类控件使用范围很小。

               (2)二是编写一个ActiveX控件,以后可以在不同的应用程序中重复使用。

             1、创建ActiveX控件框架:

                 (1)创建ActiveX控件工程

                        使用MFC ActiveX ControlWizard创建一个名为MyTime的ActiveX控件工程,使用默认设置。

                (2)MyTime控件的文件构成

                         查看MyTime工程的Class View页面,其中:

                        _DMyTime:一个dispinterface类型的结构,用来包含控件的属性和方法。

                       _DMyTimeEvents:也是一个dispinterface类型的结构,用来包含控件的事件。

                       CMyTimeApp:此类派生自COleControlModule,用于初始化控件。可以在该类的InitInstance函数中添加相应的初始化代码;在ExitInstance函数中添加清除代码。

                       CMyTimeCtrl:此类派生自COleControl类,主要处理控件的显示以及对消息的响应等,后面的大部分工作就是对这个类进行编程。

                       CMyTimePropPage:此类派生自COlePropertyPage类,这个类描述了控件属性对话框中的名为Control的选项卡。

                      全局对象DllRegisterServer函数用于注册控件,DllUnregisterServer用于移出注册。

            注意:使用ControlWizard产生的ActiveX控件都派生自COleControl类。

                (3)测试ActiveX控件

                       单击Tools|ActiveX Control Test Container菜单项,使用Visual C++6.0提供的ActiveX控件测试工具来测试MyTime控件。单击测试工具程序的Edit|Insert New Control菜单项,在Insert Control对话框中选择MyTime Control控件。

                  2、修改ActiveX控件的显示:

                        首先获取系统当前时间,然后将时间转换成文本在控件中输出。同时,还必须根据时、分、秒的数值将时钟画出来。

                      (1)显示时钟

                            1)修改CMyTimeCtrl类的构造函数CMyTimeCtrl如下:

                              CMyTimeCtrl::CMyTimeCtrl()
                             {
                                InitializeIIDs(&IID_DMyTime, &IID_DMyTimeEvents);

                                // TODO: Initialize your control's instance data here.
                                SetInitialSize(200, 230); //设置控件初始尺寸大小
                              }

                           2)修改CMyTimeCtrl类的OnDraw函数如下:

void CMyTimeCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,const CRect&  rcInvalid)
{

 // TODO: Replace the following code with your own drawing code.
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
// pdc->Ellipse(rcBounds);
pdc->SetBkMode(TRANSPARENT); //设置背景透明

CTime time;
time = CTime::GetCurrentTime(); //获取系统时间

double pi = 3.14159265; //圆周率
int cx = rcBounds.left + 100; //时钟的中心位置x坐标
int cy = rcBounds.top + 100; //时钟的中心位置y坐标

//使用循环画出时钟盘面
for(int i=0; i<60; i++)
{
int x = cx + 80*cos(i*pi/30) +0.5;
int y = cy + 80*sin(i*pi/30) +0.5;

if(i%5 == 0) pdc->Ellipse(x-3, y-3, x+3, y+3); //大刻度
else pdc->Ellipse(x-1, y-1, x+1, y+1); //小刻度
}

CString str = time.Format("%H:%M:%S"); //将时间写入字符串

//输出字符串,在时钟下面以数字方式显示时间
pdc->TextOut(rcBounds.left+70, rcBounds.top+200, str);

///
// 下面将使用三种不同粗细的画笔来画出时钟的时针、分针和秒针
///
CPen pen1(PS_SOLID, 4, RGB(0,0,0)); //时针画笔
CPen pen2(PS_SOLID, 2, RGB(0,0,0)); //分针画笔
CPen pen3(PS_SOLID, 1, RGB(0,0,0)); //秒针画笔

//根据当前时间计算时针的终点位置(x1,y1)
int x1 = cx + 40*cos((time.GetHour()-3)*pi/6 +
(time.GetMinute()/12)*pi/30) + 0.5;
int y1 = cx + 40*sin((time.GetHour()-3)*pi/6 +
(time.GetMinute()/12)*pi/30) + 0.5;
//根据当前时间计算分针的终点位置(x2,y2)
int x2 = cx + 60*cos((time.GetMinute()-15)*pi/30) + 0.5;
int y2 = cx + 60*sin((time.GetMinute()-15)*pi/30) + 0.5;
//根据当前时间计算秒针的终点位置(x3,y3)
int x3 = cx + 70*cos((time.GetSecond()-15)*pi/30) + 0.5;
int y3 = cx + 70*sin((time.GetSecond()-15)*pi/30) + 0.5;

CPen * pOldPen = pdc->SelectObject(&pen1);
pdc->MoveTo(cx, cy); //画出时针
pdc->LineTo(x1, y1);

pdc->SelectObject(&pen2);
pdc->MoveTo(cx, cy); //画出分针
pdc->LineTo(x2, y2);

pdc->SelectObject(&pen3);
pdc->MoveTo(cx, cy); //画出秒针
pdc->LineTo(x3, y3);

pdc->SelectObject(pOldPen); //落选画笔
}

                      3)由于使用了数学函数sin和cos,因此在MyTimeCtl.cpp文件中包含math.h:

                             #include "math.h"

                   (2)增加计时器

                           接下来,要让时钟能够动起来。类似在状态栏上显示时间一样,将要为MyTime添加WM_TIMER消息处理,并设置定时器。

                           1)使用ClassWizard为CMyTimeCtrl类添加三个消息处理,WM_CREATE消息处理函数Oncreate,WM_TIMER消息处理函数OnTimer,WM_CLOSE消息处理函数OnClose。

                          2)修改OnCreate函数如下:

int CMyTimeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
SetTimer(1, 1000, NULL); //设置计时器
return 0;
}

                        3)修改OnTimer函数如下:

void CMyTimeCtrl::OnTimer(UINT nIDEvent) 
{
// TODO: Add your message handler code here and/or call default
InvalidateControl(); //重画控件,相当于调用OnDraw函数
COleControl::OnTimer(nIDEvent);
}

                        4)修改OnClose函数如下:

void CMyTimeCtrl::OnClose() 
{
// TODO: Add your message handler code here and/or call default
KillTimer(1); //释放计时器
CWnd::OnClose();
}

                (3)修改控件示意图标

                       打开MyTime控件工程的资源,修改名为IDB_MYTIME的位图资源。

                      编译MyTime控件工程,将MyTime控件插入到Time工程。修改Time工程的IDD_TIME_DIALOG对话框模板,插入一个MyTime控件和一个分组框。

注意:(1)此时,查看MyTime控件的属性,会发现Control和All属性对话框都是空白的,因为此时还没有为MyTime控件添加任何属性。

           (2)此时,如果使用ClassWizard查看MyTime控件所能产生的事件时,会发现是空的,因为此时还没有为控件添加事件。

      3、添加属性:

      4、使用库存属性的对应方法:

      5、添加属性页:

      6、添加事件:

步骤总结:

1、使用MFC ActiveX Control Wizard创建控件工程框架

2、定制控件的界面和图标

3、为控件添加属性、事件和方法并进行相应的处理