zoukankan      html  css  js  c++  java
  • 利用ATL技术创建ActiveX控件CircleCtl 。简单介绍 VC2003 使用 ATL 开发 ActiveX 控件(转)

    利用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添加到支栏中,确定之后就把该控件加到项目中了。

      

      图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

  • 相关阅读:
    编程心得
    PC缺少一个或多个网络协议 qq可登录(win10)
    系统启动和内核管理
    实现Internet架构的dns解析
    文本处理三剑客之AWK
    SHELL脚本编程进阶
    网络协议和管理笔记
    基础知识
    进程和计划任务
    710
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/2544077.html
Copyright © 2011-2022 走看看