为什么我在atl控件添加m

 我来答
匿名用户
推荐于2016-10-23
展开全部
(1) 打开VC6集成开发环境,按新建按钮,选择PROJECT标签。
(2) 选择ATL COM AppWizard。
(3) 在右侧Project Name下面的空白处输入"Polygon"。
如下图所示:

图1

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

图2

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

图3

按下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项,出现如下对话框:

图4

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

图5

(3) 我们在Names标签页,"Short Name"后面的空白中输入"PolyCtl",这时你将注意到其他的空白将会自动完成。
Class域显示控件将会使用的类名称。
CoClass是控件的组件类ID
Interface是接口名称,我们将会在此接口中实现一些方法和属性
Type是控件描述
ProgID是易记的类ID名称,用它可以得到控件的CLSID

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

图6

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

图7

(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会话框出现。如下所示:

图8

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

图9

5.关闭ActiveX Control Test Container。

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

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

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

图10

(2) Add Property to Interface会话框出现,允许你加入你的属性细节:
1.在属性类型的下拉列表框中选择short。
2.输入"Sides"作为我们的属性名称。当你编辑属性名字域的时候,Implementation下面的编辑框将会出现一些信息,这些信息将被增加到你的IDL文件。如下所示:

图11

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 = 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;
}
}

现在初始化变量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;
姑娘丶说爱我丶
2016-03-05 · TA获得超过822个赞
知道答主
回答量:449
采纳率:85%
帮助的人:79.7万
展开全部
1) 打开VC6集成开发环境,按新建按钮,选择PROJECT标签。
(2) 选择ATL COM AppWizard。
(3) 在右侧Project Name下面的空白处输入"Polygon"。
如下图所示:

图1

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

图2

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

图3

按下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项,出现如下对话框:

图4

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

图5

(3) 我们在Names标签页,"Short Name"后面的空白中输入"PolyCtl",这时你将注意到其他的空白将会自动完成。
Class域显示控件将会使用的类名称。
CoClass是控件的组件类ID
Interface是接口名称,我们将会在此接口中实现一些方法和属性
Type是控件描述
ProgID是易记的类ID名称,用它可以得到控件的CLSID

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

图6

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

图7

(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会话框出现。如下所示:

图8

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

图9

5.关闭ActiveX Control Test Container。

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

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

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

图10

(2) Add Property to Interface会话框出现,允许你加入你的属性细节:
1.在属性类型的下拉列表框中选择short。
2.输入"Sides"作为我们的属性名称。当你编辑属性名字域的时候,Implementation下面的编辑框将会出现一些信息,这些信息将被增加到你的IDL文件。如下所示:

图11

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 = 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;
}
}

现在初始化变量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;
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
帐号已注销
2016-02-26 · TA获得超过517个赞
知道答主
回答量:173
采纳率:0%
帮助的人:93.8万
展开全部
ALT为描述性文件
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(1)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式