一、使用向导工具搭建控件程序框架
如上图所示,使用向导工具创建Activex程序框架。在创建过程中一直选择默认配置。
向导工具自动生成的程序文件如下图所示。其中包括应用程序类文件DrawLine.cpp、控件类文件DrawLineCtl.cpp、控件属性页文件 DrawLinePpg.cpp文件等。需要指出的是DrawLine.odl文件中包含了控件及其接口等的全局唯一标识符字串uuid,如图所示。系统 将使用该uuid,作为控件的ClassID记录到注册表中。
二、为控件添加工具条
为了用户能够选择绘制不同图形,需要为Activex控件添加工具条。
如下图所示,在工具主菜单或资源视图右键菜单中选择添加工具条,点击new按钮将添加一个空的工具条。选中工具条名称,点击右键(或者在工具主菜单View中选择Property)可以编辑工具条控件的编号。
工具条的设计如下图所示,包括绘制折线、矩形等的按钮:
如下图所示,在类视图中选择控件类CdrawLineCtl,在右键菜单中选择添加WM_CREATE消息处理函数。当然也可以在主菜单View中选择类 向导ClassWizard来完成(在类名称中选择CdrawLineCtl,在消息栏选择WM_CREATE)。系统将生成 CDrawLineCtrl::OnCreate()函数框架。
为了显示和使用工具条,还需要为控件定义一个工具条类型的成员变量变量。如下图所示:
在前面生成的CDrawLineCtrl::OnCreate()消息函数中添加如下加载工具条控件对象的代码:
int CDrawLineCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
m_ToolBar.Create(this);
m_ToolBar.LoadToolBar(IDR_TOOLBAR1);
return 0;
}
在CDrawLineCtrl::OnDraw()消息函数中添加如下定位工具条控件位置的代码:
void CDrawLineCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
// TODO: Replace the following code with your own drawing code.
CRect rect(5,10,115,40);//将工具条控件放置在Activex控件窗口顶部
m_ToolBar.MoveWindow(rect,TRUE);
}
至此,编译程序后,系统将自动注册Activex控件,可以使用如下HTML页面代码测试工具条是否能够正常显示:
<HTML><HEAD><TITLE>Test page for object DrawLine Control</TITLE></HEAD>
<BODY>
<OBJECT ID="DrawLineCtl" CLASSID="CLSID:1D388D32-9D43-4891-BFEE-A775F78B9FBD"
HEIGHT=300 WIDTH=300>//Height和Width为Activex控件窗口大小
</OBJECT>
</BODY>
</HTML>
Activex控件窗口大小也可以在CDrawLineCtrl类的构造函数中设置:
CDrawLineCtrl::CDrawLineCtrl()
{
InitializeIIDs(&IID_DDrawLine, &IID_DDrawLineEvents);
// TODO: Initialize your control's instance data here.
SetInitialSize( 200, 75 );//Control window size
}
三、在控件中画图
为了绘制不同图形需要为CDrawLineCtrl类定义记录图形类型的成员变量m_DrawType。点击工具条的不同按钮将为m_DrawType设 置不同的值。首先为工具条按钮添加点击消息处理函数。以折线按钮为例,在工具条资源图形中选择折线按钮,选择View菜单的ClassWizard打开类 向导。如下图所示,选择在CDrawLineCtrl类中创建按钮消息处理函数:
图中折线按钮的编号使用了系统自动生成的值,你也可以在资源视图中编辑按钮编号。
另外,为了捕获鼠标点击事件,还需要为CDrawLineCtrl类添加系统消息WM_LBUTTONDOWN的处理函数,方法与添加WM_CREATE消息类似,不再赘述。
为了绘制折线(多线段)还需要为CDrawLineCtrl类定义记录折线点坐标的成员变量等。下图定义了记录折线点坐标的成员变量 m_MutiLine。m_MutiLine为CArray类型,这是一个模板类。由于使用向导定义时不允许设置模板参数,需要在代码中进一步修改,而且 要在DrawLineCtrl.h文件中添加包含CArray类定义的头文件的语句:#include<Afxtempl.h>。
成员变量及绘制图形的函数代码如下所示:
// DrawLineCtl.h
......
#include<Afxtempl.h>
......
class CDrawLineCtrl : public COleControl
{
DECLARE_DYNCREATE(CDrawLineCtrl)
// Constructor
public:
CDrawLineCtrl();
......
private:
CArray<CPoint,CPoint> m_MutiLine;//记录折线的点坐标
CString m_DrawType;//绘制的图形类型
CToolBar m_ToolBar;//工具条类对象
};
......
// OcxToolBarCtl.cpp
......
CDrawLineCtrl::CDrawLineCtrl()
{
InitializeIIDs(&IID_DDrawLine, &IID_DDrawLineEvents);
// TODO: Initialize your control's instance data here.
SetInitialSize( 300, 300 );// Control window size
}
......
void CDrawLineCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
// TODO: Replace the following code with your own drawing code.
CRect rect(5,10,115,40);//将工具条控件放置在Activex控件窗口顶部
m_ToolBar.MoveWindow(rect,TRUE);
CPen pen;
CPen* pOldPen;
//绘制绘图区边框
pen.CreatePen( PS_DOT, 1, RGB(231,101,26));
pOldPen = pdc->SelectObject( &pen );
pdc->MoveTo(0,40);
pdc->LineTo(299,40);
pdc->LineTo(299,299);
pdc->LineTo(0,299);
pdc->LineTo(0,40);
//改变画笔颜色
pen.DeleteObject();//释放画笔资源
pen.CreatePen( PS_SOLID, 1, TranslateColor( GetForeColor()));
pdc->SelectObject( &pen );
//画折线
for(int i=0;i<m_MutiLine.GetSize();i++)
{
if(i ==0)
pdc->MoveTo(m_MutiLine[0]);
else
pdc->LineTo(m_MutiLine[i]);
}
pdc->SelectObject( pOldPen );
}
......
int CDrawLineCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
m_ToolBar.Create(this);
m_ToolBar.LoadToolBar(IDR_TOOLBAR1);
return 0;
}
......
void CDrawLineCtrl::OnButton32768()
{
// TODO: Add your command handler code here
m_DrawType="mutiline";
}
void CDrawLineCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(m_DrawType == "mutiline")
{
if(point.y <= 40)//在工具条处不能画图形
return;
m_MutiLine.Add(point);
InvalidateControl();//重绘控件,将触发OnDraw()函数
}
COleControl::OnLButtonDown(nFlags, point);
}