利用ATL技术创建ActiveX控件CircleCtl

  1) 创建ATL项目

  使用ATL COM AppWizard 创建ATL框架为该项目命名为Circle,按照向导提示向下做,采用默认设置,即Server Type类型为Dynamic Link Library(DLL)。

  2) 向ATL项目添加ActiveX控件

  首先从Insert菜单项中选择New ATL Object…调出 ATL Object Wizard对话框,然后左边Category列表选择Object,右边相应地选择Full Control,如图(1)所示。按Next继续,出现 ATL Object Wizard属性对话框,如图(2),在Names选项卡中,我们只需要在Short Name 编辑框输入CircleCtl即可,其它系统就会自动给定,也可以修改,我们这里保持系统给定状态;在Attributes 选项卡中,选择 Support ISupportErrorInfo 和 Support Connection Points 两个复选框,这两项分别支持出错信息和连接点;Miscellaneous选项卡保持默认设置;Stock Properties中我们把FillColor添加到支栏中,确定之后就把该控件加到项目中了。

  利用ATL技术创建ActiveX控件CircleCtl 。简单介绍 VC2003 使用 ATL 开发 ActiveX 控件(转)利用ATL技术创建ActiveX控件CircleCtl 。简单介绍 VC2003 使用 ATL 开发 ActiveX 控件(转)

  图1 图2

  3)为ActiveX控件添加自定义属性

  现在来添加Circle控件的一个基本属性——Radius。

  在Workspace Windows中Class View状态下,右击 ICircleCtl接口,选择Add Property,属性类型为short,名为Radius,参数为空。系统会自动生成get_Radius和put_Radius两个成员函数。在CCircleCtl中添加m_radius变量,用来存储半径。在CCircleCtl的构造函数中将其初始化为50,并在get_Radius函数中添加*pVal=m_radius; 在put_Radius函数中添加m_radius=newVal; FireViewChange();用来及时更新视图。对于Radius的属性,我们通过修改控件的绘制代码来使它起作用。

  4) 修改ActiveX控件的绘制代码实现属性交换

  首先,在CCircleCtl的构造函数中对绘制圆的填充色进行初始化,将它的初始值设为红色,即m_clrFillColor=RGB(255,0, 0)。

  接下来,我们需要几个全局变量来保存控件区域的信息,在CircleCtl.h中添加如下变量:

  static POINT CenterPt;
  static long RectHt = 0;
  static long RectWd = 0;

  然后修改OnDraw函数,在该绘制函数中,使用 Windows API中标准的HDC、HPEN、HBRUSH以及SelectObject、Ellipse等结构和函数来实现绘制的。例如:

  // 创建画笔和画刷并选中颜色画圆

  hPen = (HPEN)GetStockObject(BLACK_PEN);

  hOldPen = (HPEN)SelectObject(hdc, hPen);

  hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);

  hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);

  hBrush = CreateSolidBrush(colFore);

  SelectObject(hdc, hBrush);

  Ellipse (hdc, (CenterPt.x - m_radius), (CenterPt.y - m_radius), (CenterPt.x +m_radius),(CenterPt.y+ m_radius));

  5) 为ActiveX控件添加事件

  现在将向ATL控件中添加Click和RClick事件。如果用户在矩形区内点击,则会激发相应事件。现在要向ICircleCtlEvents接口添加Click方法,首先在“ClassView”中选中“ICircleCtlEvents”右击,选择Add Method,出现如下对话框,并按下图设置,最后点“OK”按钮就可以添加Click事件的实现方法。用同样的方法添加RClick事件,参数与Click事件一致。接下来我们要为控件实现连接点接口IConnectionPoint和连接点容器接口IConnectionPointContainer。编译好Circle.idl文件,生成对应的Circle.tlb,在“ClassView”中选中“CCircleCtl”,右击,在Popup菜单中选择“Implement Connection Point”命令,在弹出的对话框中选中“_ICircleCtlEvents”接口。在类中定义了以两个坐标为参数的Fire_Click和Fire_RClick方法,调用这两个方法就可以在控件中激发响应的事件。

  最后,添加激发事件的代码,我们分别在鼠标左键和右键按下的消息响应中进行处理,激发响应的事件,例如OnLButtonDown函数部分代码如下:

  WORD xPos = LOWORD(lParam); //鼠标水平坐标
  WORD yPos = HIWORD(lParam); // 鼠标垂直坐标
  Fire_Click (xPos, yPos); //执行触发函数

  至此,可以在ActiveX Control Test Container中测试该控件。

  网页中使用ActiveX控件

  在控件生成时,系统同时生成了一个CircleCtl.htm文件,在VC编辑环境下打开该文件,在和之间加上如下的VBScript:

<SCRIPT LANGUAGE="VBScript">
<!--
Sub CircleCtl_Click(x, y)
 If CircleCtl.Radius <100 Then
  CircleCtl.Radius = CircleCtl.Radius+1 ‘半径加1
 Else
  MsgBox(“Radius must be less than 100!”)
 End If
End Sub
Sub CircleCtl_RClick(x, y)
 If CircleCtl.Radius >=1 Then
  CircleCtl.Radius = CircleCtl.Radius-1 ‘半径减1
 Else
  MsgBox(“Radius mustn’t be less than 0!”)
 End If
End Sub
-->
</SCRIPT>


  注意保存。然后在“我的电脑”中打开该htm文件,用鼠标单击圆,半径变大,右击圆半径变小。

  结束语

  本文介绍了基于ATL技术以及使用该技术实现了一个简单的圆的控件CircleCtl并且介绍了其在网页中的使用。ActiveX控件作为可重用的代码组件,不仅应用广泛,还可节约开发时间。它将大量的实现细节隐藏起来,以简明的接口与用户名交互,易于使用。对ActiveX技术的研究已经成为当今软件业的热点和潮流。

----------------------------------------------------------------------------------------------------------------------------------------------------------------

简单介绍 VC2003 使用 ATL 开发 ActiveX 控件

文章出处:飞诺网(www.diybl.com):http://www.diybl.com/course/3_program/c++/cppsl/2008130/98079.html

 

第一步:创建ATL项目
  使用新建项目->VC++项目->ATL,选择 ATL 项目,输入项目名字,进入创建项目向导,选择好对应的属性(动态链接库),VC2003将自动生成一个框架,内含:
  项目代码(.c, .cpp),模块定义文件(.def),接口定义语言文件(.idl),注册脚本(.rgs),以及其他的资源文件等

第二步:添加一个 ATL 对象(Class)
  在类视图中,在项目上点击右键,选择“添加->添加类”,在类选择框中,选择 VC++ ->ATL 中的“ATL 控件”,出现 ATL 控件向导对话框,在向导的“名称”选项卡,“简称”(Short name)中,填写你的 ActiveX 控件的名字,如PolyCtl,这个名字就是控件注册后使用的名字。其他选项基本选择默认。如果想使用,可以用鼠标悬停在相应项上查看简单说明。

  在“选项”里面,选择支持“连接点”,可以让生成的控件调用外部实现接口,即执行特定页面函数的实现。

  VC6 中,需要手工选择支持 IError 等接口。
第三步:设置控件的属性和实现
  例程的控件是实现绘出一个正多边形,多边形的边数可以调整。并能够响应鼠标左键点击事件,点击事件将判断鼠标点击的位置,并根据情况调用两个外部实现函数。
  在类视图的 IPolyCtl 上点击右键,选择“添加->添加属性”,添加一个 short 类型的属性,名字为 Sides,其他属性选默认,点击完成,向导将自动添加 get_Sides 和 put_Sides 的实现函数,这两个函数是外界取得 ActiveX 控件属性的时候被隐式调用的。


为控件类添加一个成员变量 short m_nSides 来存储多边形的边数。在类构造函数中将其初始化为 3。
在 get_Sides 和 put_Sides 中分别实现存取:
STDMETHODIMP CPolyCtl::get_Sides(short *pVal)
{
   *pVal = m_nSides;
   return S_OK;
}
STDMETHODIMP CPolyCtl::put_Sides(short newVal)
{
   if (newVal > 2 && newVal < 101)
   {
      m_nSides = newVal;
      FireViewChange(); // 立即更新窗口
      return S_OK;
   }
   else
     return Error(_T("Shape must have between 3 and 100 sides"));
}
第四步:实现绘图
  为了实现绘出多边形,这里用到了 sin 和 cos 函数,这两个函数包含在 C 头文件 math.h 中,所以需要添加引用 #include <math.h>
  由于使用 Polygon 函数进行绘图,需要在类中添加一个点数组 POINT m_arrPoint[100];
  在类中添加一个函数,用来计算指定矩形区域中多边形每个顶点的位置:
void CalcPoints(const RECT& rc);
void CPolyCtl::CalcPoints(const RECT& rc)
{
   const double pi = 3.14159265358979;
   POINT   ptCenter;
   double  dblRadiusx = (rc.right - rc.left) / 2;
   double  dblRadiusy = (rc.bottom - rc.top) / 2;
   double  dblAngle = 3 * pi / 2;          // Start at the top
   double  dblDiff  = 2 * pi / m_nSides;   // Angle each side will make
   ptCenter.x = (rc.left + rc.right) / 2;
   ptCenter.y = (rc.top + rc.bottom) / 2;

   // Calculate the points for each side
   for (int i = 0; i < m_nSides; i++)
   {
      m_arrPoint[i].x = (long)(dblRadiusx * cos(dblAngle) + ptCenter.x + 0.5);
      m_arrPoint[i].y = (long)(dblRadiusy * sin(dblAngle) + ptCenter.y + 0.5);
      dblAngle += dblDiff;
   }
}
  修改控件类的 OnDraw 函数,实现绘出多边形的效果:

 


HRESULT CPolyCtl::OnDraw(ATL_DRAWINFO& di)
{
   RECT& rc = *(RECT*)di.prcBounds;
   HDC hdc  = di.hdcDraw;

   COLORREF    colFore;
   HBRUSH      hOldBrush, hBrush;
   HPEN        hOldPen, hPen;

   // Translate m_colFore into a COLORREF type
   OleTranslateColor(m_clrFillColor, NULL, &colFore);

   // Create and select the colors to draw the circle
   hPen = (HPEN)GetStockObject(BLACK_PEN);
   hOldPen = (HPEN)SelectObject(hdc, hPen);
   hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
   hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);

   Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);

   // Create and select the brush that will be used to fill the polygon
   hBrush    = CreateSolidBrush(colFore);
   SelectObject(hdc, hBrush);

   CalcPoints(rc);
   Polygon(hdc, &m_arrPoint[0], m_nSides);

   // Select back the old pen and brush and delete the brush we created
   SelectObject(hdc, hOldPen);
   SelectObject(hdc, hOldBrush);
   DeleteObject(hBrush);

   return S_OK;
}
  此时,编译运行,使用 ActiveX控件测试容器 (工具 菜单中可以直接打开)对 ActiveX 控件进行测试。
  注意:由于一般情况下,项目属性的“生成后”将自动注册控件,在 Vista 下,如果想要注册 ActiveX,需要以管理员身份启动编译环境,以管理员身份进行注册。

第五步:添加事件处理
  使控件响应鼠标点击并调用外部实现方法。
  在第二步里面,选择了“选项->支持 连接点”的话,类视图将有一个 _IPolyCtlEvent 接口,在上面点击右键,选择“添加->添加方法”,在添加方法向导中,将返回类型设置为 void,函数名设置为 ClickIn,参数设置为 [in]long x 和 [in]long y。用同样操作添加 ClickOut 方法。
  此时代码中的接口部分将类似如下代码:
__interface _IPolyCtlEvents
{
   properties:
   methods:
   [id(1), helpstring("方法 ClickIn")] void ClickIn([in]LONG x, [in] LONG y);
   [id(2), helpstring("方法 ClickOut")] void ClickOut([in] LONG x, [in] LONG y);
};
  在 VC6 中,此时需要重新编译 idl 文件,然后对类 CPolyCtl 进行右键菜单中的添加连接点(Implement Connection Points),VC2003 中,在此类创建时就已经自动绑定,不需要再次手工操作。

  在类 CPolyCtl 的属性对话框中,选择消息标签,重载 WM_LBUTTONDOWN 事件,添加如下代码:

LRESULT CPolyCtl::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
   HRGN hRgn;
   WORD xPos = LOWORD(lParam);  // horizontal position of cursor
   WORD yPos = HIWORD(lParam);  // vertical position of cursor

   CalcPoints(m_rcPos);

   // Create a region from our list of points
   hRgn = CreatePolygonRgn(&m_arrPoint[0], m_nSides, WINDING);

   // If the clicked point is in our polygon then fire the ClickIn
   //  event otherwise we fire the ClickOut event
   if (PtInRegion(hRgn, xPos, yPos))
      Fire_ClickIn(xPos, yPos);
   else
      Fire_ClickOut(xPos, yPos);

   // Delete the region that we created
   DeleteObject(hRgn);
   return 0;
}

  编译,再测试,可一看到 ActiveX控件测试容器中,鼠标点击时产生的 ClickIn 和 ClickOut 调用。
第六步:添加属性页(懒,没做,略)
第七步:在网页中的引用
  项目编译的时候,会自动产生一个文件,名字叫 PolyCtl.htm,编辑它:
<HTML>
<HEAD>
<TITLE>对象 PolyCtl 的 ATL 7.0 测试页</TITLE>
</HEAD>
<BODY>
<OBJECT ID="PolyCtl" CLASSID="CLSID:4CBBC676-507F-11D0-B98B-000000000000"></OBJECT>
<SCRIPT LANGUAGE="VBScript">
<!--
Sub PolyCtl_ClickIn(x, y)
   PolyCtl.Sides = PolyCtl.Sides + 1
End Sub
Sub PolyCtl_ClickOut(x, y)
   PolyCtl.Sides = PolyCtl.Sides - 1
End Sub
-->
</SCRIPT>
</BODY>
</HTML>
使用浏览器打开网页,点击其中的 ActiveX 控件,试试结果吧。


文章出处:飞诺网(www.diybl.com):http://www.diybl.com/course/3_program/c++/cppsl/2008130/98079.html

 

相关文章: