如何创建和使用ATL控件

如何创建和使用ATL控件,第1张

(一) 创建工程

(1) 打开VC6集成开发环境,按新建按钮,选择PROJECT标签。

(2) 选择ATL COM AppWizard。

(3) 在右侧Project Name下面的空白处输入"Polygon"。

按下OK按钮,出现如下对话框:

按Finish按钮,接受默认设置,出现如下对话框:

按下OK按钮,ATL COM AppWizard将生成一系列的文件,现在描述如下:

Polygon.cpp:

包含了DllMain,DllCanUnloadNow, DllGetClassObject,DllRegisterServer,DllUnregisterServer的实现,

同时它也包含object map:

BEGIN_OBJECT_MAP(ObjectMap)

//这里将列出你的工程中将会用到的ATL对象,这里最初为空,

//因为我们目前还没有创建新的ATL对象

END_OBJECT_MAP()

Polygon.def DLL便准模块定义文件

Polygon.dsw 项目工作区文档

Polygon.dsp 项目设置文档

Polygon.idl 接口定义语言文件, 它详细的描述了您的工程中所有的接口

Polygon.rc 资源文件, 它包含了版本信息和工程名称字符串

Resource.h 资源文件的头文件

Polygonps.mk 这个就是make file,它能被用来创建代理存根DLL

Polygonps.def 代理存根DLL的模块定义文件

StdAfx.cpp 此文件包含ATL的执行档

StdAfx.h 此文件包含ATL的头文件

为了使它(Polygon DLL)变得有用,我们需要用ATL Object Wizard给它添加一个控件(control)。

(二)添加一个控件

(1) 打开INSERT菜单,选择New ATL Object项,出现如下对话框:

(2) 我们在左边选择"Controls",右边选择Full Control,按下NEXT按钮,出现如下所示对话框:

(3) 我们在Names标签页,"Short Name"后面的空白中输入"PolyCtl",这时你将注意到其他的空白将会自动完成。

Class域显示控件将会使用的类名称。

CoClass是控件的组件类ID

Interface是接口名称,我们将会在此接口中实现一些方法和属性

Type是控件描述

ProgID是易记的类ID名称,用它可以得到控件的CLSID

(4) 为了激活错误提示信息和connection points支持,我们选择Attributes标签页,选择Support ISupportErrorInfo和Support Connection Points,结果如下图所示:

(5) 由于我们将会在多变形内部染色,所以我们需要增加一个Fill Color属性支持。我们选择stock property标签页,在左边的列表框中双击Fill Color,结果如下图所示:

(6) 按下“确定”按钮,结束创建控件。

VC6将会生成如下新的文件:

PolyCtl.h/cpp:包含了C++类CPolyCtl的实现

PolyCtl.rgs:一个包含了注册控件所需要的注册信息的文本文件

PolyCtl.htm:一个HTML文件,其中有关于这个控件的引用的代码。例如在我这个例子中有:

同时Wizard也改变了以下几处:

a)在StdAfx.h和StdAfx.cpp文件中增加了一条include语句,它把控件必需的ATL文件包含进来了

b)注册脚本文件PolyCtl.rgs被增加到工程资源中。

c)Polygon.idl被修改以便包括新的控件细节信息。

文件PolyCtl.h是最有趣的,因为它包含实现你的控件主要的代码。

现在,你已经准备好了建立你的控件:

1.在Build菜单点击Build Polygon.dll。

2.一旦你的控件已经完成Build,你就可以点击在Tools菜单上的ActiveX Control Test Container,控件测试容器工具将启动。

3.在ActiveX Control Test Container中,选择Edit菜单的Insert New Control,Insert Control会话框出现。如下所示:

4.从Insert Control会话框的列表框中选择 PolyCtl class,按下OK,你将看到ActiveX Control Test Container客户区出现一个长方形,在其中央显示了本文" ATL 3.0: PolyCtl",如下所示:

5.关闭ActiveX Control Test Container。

然后,你将会在控件中加入定制属性。

(三)为控件添加一个属性

(1) IPolyCtl是包含你定制的方法和属性的接口。 要把属性加入这一个接口的最容易的方法是在ClassView中右击它,而且选择Add Property。如下所示:

(2) Add Property to Interface会话框出现,允许你加入你的属性细节:

1.在属性类型的下拉列表框中选择short。

2.输入"Sides"作为我们的属性名称。当你编辑属性名字域的时候,Implementation下面的编辑框将会出现一些信息,这些信息将被增加到你的IDL文件。如下所示:

3.按下OK按钮。

MIDL(编译idl文件的程序)定义了一个Get和一个Put方法,他们将分别取得和设定属性。 当MIDL编译文件的时候,它对属性名字加前缀put_ 和get_, 在接口中自动地定义那二个方法。

连同把必需的信息加入.idl文件, Add Property to Interface对话框也在类定义文件PolyCtl.h中加入Get 和Put函数原型,并在类实现文件PolyCtl.cpp中加入相应的空的实现函数。

(3) 为了能设定并且取回属性值,我们需要一个地方来储存它。从FileView, 打开 PolyCtl.h,在类定义结尾即在m_clrFillColor定义之后加入如下一行代码:

short m_nSides

(4) 现在你能实现Get和Put方法。get_Sides和put_Sides函数定义已经被增加到 PolyCtl.h 。你把代码加入 PolyCtl.cpp如下列各项:

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

return S_OK

}

else

return Error(_T("Shape must have between 3 and 100 sides"))

}

get_Sides

函数只是通过pVal指针返回属性Sides的当前值。在put_Sides方法中,你确定使用者正在对Sides属性设定可接受的值。你需要超过2条

边, 而且由于你以后将会为每个边储存点的阵列,100是一个合理的最大值界限。如果有非法的值传递进来,你可以通过使用ATL

IErrorInfo接口的Error函数来设定详细的错误信息。

如果你的客户(container)需要比HRESULT更多的关于错误的资讯,这是有用的。

(5) 你为属性做的最后一件事是设定m_nSides初值。藉由把一行代码加入 PolyCtl.h 的构造函数中使一个三角形成为默认形状:

CPolyCtl()

{

m_nSides = 3

}

你现在拥有了一个叫做Sides的属性。 除非你对它做一些事情,否则它并没有什么用处,下一步我们将改变画图代码并使用该属性。

(四)变更画图代码

(1) 在画图编码中你将会使用sin和cos动作计算多边形顶点, 因此在 PolyCtl.h 的顶端包含 math.h:

#include <math.h>

#include "resource.h" // main symbols

在Release

builds时需要注意:当ATL COM AppWizard产生内定工程的时候,它定义了

_ATL_MIN_CRT宏。这个宏的作用是,在你不需要C Run-Time Library支持的时候, C Run-Time

Library不被带到你的代码之内。多角形控件需要C Run-Time Library start-up code设定浮点函数初值。 因此,

如果你建立一个释放版本,你需要除去_ATL_MIN_CRT宏。 为了要除去该宏,点击Project 菜单上的Settings。

在Settings For:下拉框中选择Multiple Configurations。在跳出来的Select project

configuration(s) to modify对话框中,为所有的四个释放版本按复选框, 如图所示:

图12

然后点击OK。在C/C++标签页,选择General, 除去Preprocessor definitions定义结尾的 ",_ATL_MIN_CRT"

图13

(2) 一旦多边形顶点计算出来了,你就可以通过增加一个POINT类型的数组来保存所有的点,在PolyCtl.h中:

OLE_COLOR m_clrFillColor

short m_nSides

POINT m_arrPoint[100]

(3)

现在改变 PolyCtl.h

的OnDraw函数。注意你需要除去对Rectangle和DrawText函数的调用。你需要明确地得到而且选择黑色的笔和白色的刷子。

这么做是,以防你的控件正在运行在无窗口环境中。 如果你没有你自己的窗口, 你不能假定具备绘制所需要的设备环境。

完成的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

}

你现在需要一个函数,叫做了CalcPoints, 它将会计算多边形顶点的坐标。这些计算将会以被获准进入函数的RECT变量为基础。首先你应该把CalcPoints的定义加入到PolyCtl.h中的IPolyCtl类的公众区段:

void CalcPoints(const RECT&rc)

公共区段看起来应该如下:

// IPolyCtl

public:

STDMETHOD(get_Sides)(/*[out, retval]*/ short *newVal)

STDMETHOD(put_Sides)(/*[in]*/ short newVal)

void CalcPoints(const RECT&rc)

接着在PolyCtl.cpp尾部添加函数CalcPoints的具体实现:

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 = 0i <m_nSidesi++)

{

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

}

}

现在初始化变量m_clrFillColor,选择绿色作为默认颜色并加如下语句到CPolyCtl类构造函数中:

m_clrFillColor = RGB(0, 0xFF, 0)

类CPolyCtl构造函数现在看起来如下:

CPolyCtl()

{

m_nSides = 3

m_clrFillColor = RGB(0, 0xFF, 0)

}

现在重新编译控件,如果发现如下重载函数模糊调用错误(一剑:"这可能是VC6的一个BUG,亦或是由于我的VC6没有打SP6包的缘故吧:)"):

f:\myprogram2\polygon1\polyctl.h(106) : error C2668: 'InlineIsEqualGUID' : ambiguous call to overloaded function

我们可以在polyctl.h中出错位置修改如下:

if (::InlineIsEqualGUID(*arr[i], riid))

return S_OK

ATL简介 一. 什么是ATL 自从1993年Microsoft首次公布了COM技术以后,Windows平台上的开发模式发生了巨大的变化,以COM为基础的一系列软件组件化技术将Windows编程带入了组件化时代。广大的开发人员在为COM带来的软件组件化趋势欢欣鼓舞的同时,对于COM开发技术的难度和烦琐的细节也感到极其的不便。COM编程一度被视为一种高不可攀的技术,令人望而却步。开发人员希望能够有一种方便快捷的COM开发工具,提高开发效率,更好地利用这项技术。 针对这种情况,Microsoft公司在推出COM SDK以后,为简化COM编程,提高开发效率,采取了许多方案,特别是在MFC(Microsoft Foundation Class)中加入了对COM和OLE的支持。但是随着Internet的发展,分布式的组件技术要求COM组件能够在网络上传输,而又尽量节约宝贵的网络带宽资源。采用MFC开发的COM组件由于种种限制不能很好地满足这种需求,因此Microsoft在1995年又推出了一种全新的COM开发工具ATL。 ATL是ActiveX Template Library 的缩写,它是一套C++模板库。使用ATL能够快速地开发出高效、简洁的代码(Effective and Slim code),同时对COM组件的开发提供最大限度的代码自动生成以及可视化支持。为了方便使用,从Microsoft Visual C++5.0版本开始,Microsoft把ATL集成到Visual C++开发环境中。1998年9月推出的Visual Studio 6.0 集成了ATL 3.0版本。目前,ATL已经成为Microsoft标准开发工具中的一个重要成员,日益受到C++开发人员的重视。 ATL究竟给开发人员带来了什么样的益处呢?这还要先从ATL产生以前的COM开发方式说起。 在ATL产生以前,开发COM组件的方法主要有两种:一是使用COM SDK直接开发COM组件,另一种方式是通过MFC提供的COM支持来实现。 直接使用COM SDK开发COM组件是最基本也是最灵活的方式。通过使用Microsoft提供的开发包,我们可以直接编写COM程序。但是,这种开发方式的难度和工作量都很大,一方面,要求开发者对于COM的技术原理具有比较深入的了解(虽然对技术本身的深刻理解对使用任何一种工具都是非常有益的,但对于COM这样一整套复杂的技术而言,在短时间内完全掌握是很难的),另一方面,直接使用COM SDK要求开发人员自己去实现COM应用的每一个细节,完成大量的重复性工作。这样做的结果是,不仅降低了工作效率,同时也使开发人员不得不把许多精力投入到与应用需求本身无关的技术细节中。虽然这种开发方式对于某些特殊的应用很有必要,但这种编程方式并不符合组件化程序设计方法所倡导的可重用性,因此,直接采用COM SDK不是一种理想的开发方式。 使用MFC提供的COM支持开发COM应用可以说在使用COM SDK基础上提高了自动化程度,缩短了开发时间。MFC采用面向对象的方式将COM的基本功能封装在若干MFC的C++类中,开发者通过继承这些类得到COM支持功能。为了使派生类方便地获得COM对象的各种特性,MFC中有许多预定义宏,这些宏的功能主要是实现COM接口的定义和对象的注册等通常在COM对象中要用到的功能。开发者可以使用这些宏来定制COM对象的特性。 另外,在MFC中还提供对Automation 和 ActiveX Control的支持,对于这两个方面,Visual C++也提供了相应的AppWizard和ClassWizard支持,这种可视化的工具更加方便了COM应用的开发。 MFC对COM和OLE 的支持确实比手工编写COM程序有了很大的进步。但是MFC对COM的支持是不够完善和彻底的,例如对COM接口定义的IDL语言,MFC并没有任何支持,此外对于近些年来COM和ActiveX技术的新发展MFC也没有提供灵活的支持。这是由MFC设计的基本出发点决定的。MFC被设计成对Windows平台编程开发的面向对象的封装,自然要涉及Windows编程的方方面面,COM作为Windows平台编程开发的一个部分也得到MFC的支持,但是MFC对COM的支持是以其全局目标为出发点的,因此对COM 的支持必然要服从其全局目标。从这个方面而言,MFC对COM的支持不能很好的满足开发者的要求。

STDMETHODIMP Cchuli::split(BSTR bstr, char splitter, [OUT] BSTR* result)

{

    CString str = bstr

    //处理分割str,将结果字符串通过返回参数BSTR数组result返回,略

    return S_OK

}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/11490978.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-16
下一篇2023-05-16

发表评论

登录后才能评论

评论列表(0条)

    保存