1、COM组件教程步骤 1:创建项目Visual Studio .NET 2003 本教程将带领您逐步骤通过一个非属性化 ATL 项目,该项目创建一个显示多边形的 ActiveX 对象。此对象包括使用户得以更改组成多边形的边数的选项以及刷新显示的代码。注意 本教程创建与 Polygon(多边形)示例相同的源代码。如果您希望避免手动输入源代码,则可以从多边形示例摘要下载源代码。然后,您可以一边参考 Polygon 源代码一边阅读教程,或者用它来检查自己的项目中是否有错误。使用“ATL 项目向导”创建初始 ATL 项目 1. 在 Visual Studio 开发环境中,在“文件”菜单上单击“新建”,然
2、后单击“项目”。 2. 单击“Visual C+ 项目”文件夹并选择“ATL 项目”。 3. 键入 Polygon 作为项目名称: 源代码的位置通常默认为 My DocumentsVisual Studio Projects,并且将自动创建一个新文件夹。 4. 单击“确定”,“ATL 项目向导”随即打开。 5. 单击“应用程序设置”以查看可用选项: 6. 在创建控件时,如果控件必须是进程内服务器,则将“服务器类型”保留为 DLL。 7. 本教程中将不使用属性,因此请确保没有选中“属性化”复选框。 8. 将其他选项保留在它们的默认值,然后单击“完成”。 “ATL 项目向导”将通过生成若干个文件来
3、创建项目。可以通过展开 Polygon 对象在解决方案资源管理器中查看这些文件。下面列出了这些文件。文件说明Polygon.cpp包含 DllMain、DllCanUnloadNow、DllGetClassObject、DllRegisterServer 和 DllUnregisterServer 的实现。还包含对象映射,该映射是项目中 ATL 对象的列表。它最初是空白的。Polygon.def此模块定义文件为链接器提供有关 DLL 所需的导出的信息。Polygon.idl接口定义语言文件,描述特定于对象的接口。Polygon.rgs此注册表脚本包含用于注册程序的 DLL 的信息。Polygo
4、n.rc资源文件,最初包含版本信息和含有项目名称的字符串。Resource.h资源文件的头文件。Polygonps.def此模块定义文件为链接器提供有关代理所需的导出和支持跨单元调用的存根 (stub) 代码的信息。有关详细信息,请参见 COM+ 单元模型。stdafx.cpp将包括 (#include) ATL 实现文件的文件。stdafx.h将包括 (#include) ATL 头文件的文件。在下一步骤中,您将向项目添加控件。步骤 2:添加控件Visual Studio .NET 2003 在此步骤中,您将向项目添加控件,生成此控件,并在 Web 页中对其进行测试。向 ATL 项目添加对象
5、 1. 在“类视图”中,右击“Polygon”项目。 2. 指向快捷菜单上的“添加”,然后单击“添加类”。 即会出现“添加类”对话框。左侧的树结构中列出了不同的对象类别: 3. 展开树结构并单击“ATL”文件夹。 4. 从右侧的模板列表选择“ATL 控件”。单击“打开”。“ATL 控件向导”将打开,从中可以配置控件: 5. 键入 PolyCtl 作为简称,并注意其他字段将自动完成。先不要单击“完成”,因为需要做一些更改。 “ATL 控件向导”的“名称”页包含以下字段:字段内容简称为控件输入的名称。类为了实现控件而创建的 C+ 类名。.h 文件为了包含 C+ 类的定义而创建的文件。.cpp 文件
6、为了包含 C+ 类的实现而创建的文件。CoClass此控件的组件类的名称。接口接口的名称,控件将在此接口上实现它的自定义方法和属性。类型对控件的说明。ProgID可用于查找控件的 CLSID 的可读名称。需要在“ATL 控件向导”中另外进行几个设置。启用对多格式错误信息和连接点的支持 1. 单击“选项”打开“选项”页。 2. 选择“连接点”复选框。这将创建对 IDL 文件中输出接口的支持。 还可以使控件成为可插入的,这意味着它可以嵌入到支持嵌入对象的应用程序中,如 Excel 或 Word。使控件成为可插入的1. 单击“外观”打开“外观”页。2. 选择“可插入”复选框,默认情况下该复选框会被清
7、除。对象显示的多边形将具有纯填充颜色,因此需要添加“填充颜色”常用属性。添加“填充颜色”常用属性并创建控件 1. 单击“常用属性”打开“常用属性”页。 2. 在“不支持”下,向下滚动可能常用属性的列表。双击“Fill Color”以将其移动到“支持”列表: 3. 这将完成控件的选项。单击“完成”。 在向导创建控件时,有若干代码改变了并添加了一些文件。创建了以下文件:文件说明PolyCtl.h包含 C+ 类 CPolyCtl 的大部分实现。PolyCtl.cpp包含 CPolyCtl 的其余部分。PolyCtl.rgs一个文本文件,包含用于注册控件的注册表脚本。PolyCtl.htm一个 Web
8、 页,包含对新创建的控件的引用。向导还执行了以下代码更改: 向 stdafx.h 和 stdafx.cpp 文件添加了 #include 语句,以包含支持控件所必需的 ATL 文件。 更改了 Polygon.idl 以包含新控件的详细信息。 将新控件添加到了 Polygon.cpp 中的对象映射。 现在可以生成控件,查看它的运行情况。生成和测试控件生成和测试控件 1. 在“生成”菜单上单击“生成 Polygon”。 2. 控件完成了生成后,在解决方案资源管理器中双击 PolyCtl.htm。将显示包含控件的 HTML Web 页。您应看到一个矩形和文本 ATL 7.0 : PolyCtl。这便
9、是您的控件。 注意 当完成本教程时,如果收到 DLL 文件无法创建的错误信息,请关闭 PolyCtl.htm 文件和“ActiveX 控件测试”容器并重新生成解决方案。如果仍无法创建 DLL,请重新启动计算机或注销(如果您使用的是“终端服务”)。下一步,您将向控件添加自定义属性。步骤 3:向控件添加属性Visual Studio .NET 2003 IPolyCtl 是包含控件的自定义方法和属性的接口,您将在其中添加属性。使用“添加属性向导”添加属性 1. 在“类视图”中右击 IPolyCtl(展开“Polygon”分支找到它)。 2. 在快捷菜单上单击“添加”,然后单击“添加属性”。 “添加
10、属性向导”随即出现。 3. 在属性类型的下拉列表中,选择“short”。 4. 键入 Sides 作为属性名: 5. 单击“完成”完成属性的添加。 将属性添加到接口时,MIDL(编译 .idl 文件的程序)定义检索其值的 Get 方法和设置新值的 Put 方法。这些方法的命名方式是在属性名的前面加上 put_ 和 get_。“添加属性向导”将必需的行添加到 .idl 文件。它还将 Get 和 Put 函数原型添加到 PolyCtl.h 中的类定义,并将一个空实现添加到 PolyCtl.cpp。您可以通过打开 PolyCtl.cpp 并查找函数 get_Sides 和 put_Sides 来进行
11、检查。虽然现在有了设置和检索属性的主干函数,但需要有地方存储属性。您将创建存储属性的变量,并相应地更新函数。创建存储属性的变量并更新 put 和 get 方法 1. 从解决方案资源管理器中,打开 PolyCtl.h 并在类定义末尾的 m_clrFillColor 定义后添加下行: 复制short m_nSides;2. 设置 m_nSides 的默认值。向 PolyCtl.h 中的构造函数添加一行,使默认形状成为三角形: 复制CPolyCtl() m_nSides = 3;3. 实现 Get 和 Put 方法。get_Sides 和 put_Sides 函数声明已经添加到 PolyCtl.h。
12、将以下代码添加到 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 指针返回
13、Sides 属性的当前值。在 put_Sides 方法中,代码确保用户将 Sides 属性设置为可接受的值。最小值必须是 2,而且由于对每个边都要使用一系列点,100 是合理的最大值限制。您现在有了一个名为 Sides 的属性。下一步,您将更改绘图代码以便使用它。步骤 5:添加事件Visual Studio .NET 2003 在此步骤中,您将把 ClickIn 和 ClickOut 事件添加到 ATL 控件。如果用户在多边形的内部单击,将激发 ClickIn 事件;如果用户在外部单击,将激发 ClickOut。添加事件的任务如下: 添加 ClickIn 和 ClickOut 方法 生成类型库
14、 实现连接点接口 添加 ClickIn 和 ClickOut 方法您在第 2 步中创建 ATL 控件时,选择了“连接点”复选框。这在 Polygon.idl 文件中创建了 _IPolyCtlEvents 接口。请注意,接口名称以下划线开头。此约定指示该接口是内部接口。这样,允许浏览 COM 对象的程序便可以选择不将此接口显示给用户。还请注意,选择“连接点”时在 Polygon.idl 文件中添加了下面的行,指示 _IPolyCtlEvents 是默认源接口:default, source dispinterface _IPolyCtlEvents;源属性指示控件为通知的源,因此它将对容器调用此
15、接口。现在将 ClickIn 和 ClickOut 方法添加到 _IPolyCtlEvents 接口。添加 ClickIn 和 ClickOut 方法 1. 在“类视图”中,展开 Polygon 和 PolygonLib 以显示 _IPolyCtlEvents。 2. 右击 _IPolyCtlEvents。在快捷菜单上单击“添加”,然后单击“添加方法”。 3. 选择 void 作为“返回类型”。 4. 在“方法名称”框中输入 ClickIn。 5. 在“参数属性”下,选中“in”框。 6. 选择“LONG”作为“参数类型”。 7. 键入 x 作为参数名,然后单击“添加”。 8. 重复第 5 步
16、到第 7 步,这次键入 y 作为参数名。 9. 单击“完成”。 10. 重复以上步骤,用相同的 LONG 参数 x 和 y,相同的“参数属性”和相同的 void 返回类型定义 ClickOut 方法。 检查 Polygon.idl 文件,查看代码是否添加到了 _IPolyCtlEvents 调度接口。Polygon.idl 文件中的 _IPolyCtlEvents 调度接口现在看起来应像这样:复制dispinterface _IPolyCtlEvents properties: methods: id(1), helpstring(method ClickIn) void ClickIn(in
17、LONG x, in LONG y); id(2), helpstring(method ClickOut) void ClickOut(in LONG x, in LONG y);ClickIn 和 ClickOut 方法接受单击点的 x 和 y 坐标作为参数。生成类型库现在请生成类型库,因为“连接点向导”将用它来获取构造控件的连接点接口和连接点容器接口所需的信息。生成类型库 重新生成项目。 - 或 - 在“解决方案资源管理器”中右击 Polygon.idl 文件,并在快捷菜单上单击“编译”。 这将创建 Polygon.tlb 文件,它就是您的类型库。从解决方案资源管理器中看不见 Polyg
18、on.tlb 文件,因为它是二进制文件,无法直接查看和编辑。实现连接点接口为您的控件实现一个连接点接口和一个连接点容器接口。在 COM 中,事件通过连接点机制来实现。为了从 COM 对象接收事件,容器建立一个到 COM 对象实现的连接点的报告连接。由于 COM 对象可以有多个连接点,COM 对象还实现连接点容器接口。通过该接口,容器可以确定哪些连接点受支持。实现连接点的接口称为 IConnectionPoint,实现连接点容器的接口称为 IConnectionPointContainer。为了帮助实现 IConnectionPoint,您将使用“实现连接点向导”。该向导通过读取类型库并为每个可
19、以激发的事件实现函数来生成 IConnectionPoint 接口。使用“实现连接点向导” 1. 在“类视图”中,右击控件的实现类 CPolyCtl。 2. 在快捷菜单上单击“添加”,然后单击“添加连接点”。 3. 从“源接口”列表中选择“_IPolyCtlEvents”并双击它,以将它添加到“实现连接点”列。单击“完成”。将生成连接点的代理类,这里是指 CProxy_IPolyCtlEvents。 如果在解决方案资源管理器中查看生成的 _IPolyCtlEvents_CP.h 文件,则将看到它包含一个名为 CProxy_IPolyCtlEvents 的类,该类是从 IConnectionPo
20、intImpl 派生的。_IPolyCtlEvents_CP.h 还定义了两个方法 Fire_ClickIn 和 Fire_ClickOut,它们接受两个坐标参数。当您需要从控件中激发事件时,将调用这些方法。向导还将 CProxy_PolyEvents 和 IConnectionPointContainerImpl 添加到了控件的多重继承列表。向导还通过将适当的项添加到 COM 映射,为您公开了 IConnectionPointContainer。您已完成了实现支持事件的代码。现在,添加一些代码以在适当的时候激发事件。记住,当用户在控件中单击左鼠标按钮时,您将激发 ClickIn 或 Clic
21、kOut 事件。若要了解用户何时单击按钮,请添加 WM_LBUTTONDOWN 消息的处理程序。为 WM_LBUTTONDOWN 消息添加处理程序 1. 在“类视图”中,右击 CPolyCtl 类,并在快捷菜单上单击“属性”。 2. 在“属性”窗口中,单击“消息”图标,然后从左边的列表中单击“WM_LBUTTONDOWN”。 3. 从出现的下拉列表中,单击“ OnLButtonDown”。OnLButtonDown 处理程序声明将添加到 PolyCtl.h 中,处理程序实现将添加到 PolyCtl.cpp 中。 接下来修改该处理程序。修改 OnLButtonDown 方法 更改 PolyCtl
22、.cpp 中包含 OnLButtonDown 方法的代码(删除向导所放置的任何代码),使它看起来像这样: 复制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); / Creat
23、e a region from our list of points hRgn = CreatePolygonRgn(&m_arrPoint0, 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
24、 the region that we created DeleteObject(hRgn); return 0;此代码利用在 OnDraw 函数中计算的点创建一个区域,以通过调用 PtInRegion 来检测用户的鼠标单击。uMsg 参数是所处理的 Windows 消息的 ID。这使您可以有一个处理消息范围的函数。wParam 和 lParam 参数是所处理消息的标准值。参数 bHandled 使您得以指定函数是否处理了消息。默认情况下,值设置为 TRUE,指示函数处理了消息,但也可以将其设置为 FALSE。这将使 ATL 继续查找要将消息发送到的其他消息处理程序函数。生成和测试控件现在尝试
25、您的事件。生成控件并再次启动“ActiveX 控件测试容器”。这次查看事件日志窗口。若要将事件路由到输出窗口,请从“选项”菜单中单击“记录”,然后选择“记录到输出窗口”。插入控件并试着在窗口中单击。请注意,在填充多边形的内部单击将激发 ClickIn,在它的外部单击将激发 ClickOut。接下来将添加属性页。步骤 6:添加属性页Visual Studio .NET 2003 属性页作为单独的 COM 对象实现,这使得可以在需要时共享属性页。在此步骤中,您将执行以下任务以将属性页添加到控件: 创建属性页资源 添加用来创建和管理属性页的代码 向控件添加属性页 创建属性页资源若要将属性页添加到控件
26、,请使用“ATL 添加类向导”。添加属性页 1. 在解决方案资源管理器中,右击“Polygon”。 2. 在快捷菜单上单击“添加”,然后单击“添加类”。 3. 从模板列表中,选择“ATL 属性页”并单击“打开”。 4. 当“ATL 属性页向导”出现时,输入 PolyProp 作为简称: 5. 单击“字符串”打开“字符串”页,然后输入 &Polygon 作为标题: 属性页的“标题”是在该页的选项卡中出现的字符串。“文档字符串”是属性框架用来放在状态栏或工具提示中的说明。请注意,标准属性框架目前不使用该字符串,因此可以将它保留为默认内容。此时将不生成“帮助文件”,因此请删除该文本框中的项。 6.
27、单击“完成”,将创建属性页对象。 创建了以下三个文件:文件说明PolyProp.h包含实现属性页的 C+ 类 CPolyProp。PolyProp.cpp包含 PolyProp.h 文件。PolyProp.rgs注册属性页对象的注册表脚本。还进行了以下代码更改: 新属性页被添加到 Polygon.cpp 中的对象项映射。 PolyProp 类被添加到 Polygon.idl 文件。 新注册表脚本文件 PolyProp.rgs 被添加到项目资源。 对话框模板被添加到属性页的项目资源。 您指定的属性字符串被添加到资源字符串表。 现在添加您希望出现在属性页上的字段。将字段添加到属性页 1. 在“解决
28、方案资源管理器”中,双击 Polygon.rc 资源文件。这将打开“资源视图”。 2. 在“资源视图”中,展开“Dialog”节点并双击“IDD_POLYPROP”。请注意,出现的对话框是空的,只有一个标签告诉您在此处插入控件。 3. 选择该标签,并将其显示文本改为 Sides:,方法是改变“属性”窗口中的“Caption”文本并调整标签框的大小: 4. 将工具箱中的一个编辑控件拖动到标签的右侧: 5. 最后,使用“属性”窗口将该编辑控件的“ID”更改为 IDC_SIDES。 这就完成了创建属性页资源的过程。添加用来创建和管理属性页的代码既然已经创建了属性页资源,现在需要编写实现代码了。首先,
29、启用 CPolyProp 类以设置在按“应用”按钮时对象中的边数。修改 Apply 函数以设置边数 像下面这样在 PolyProp.h 中更改 Apply 函数: 复制STDMETHOD(Apply)(void) USES_CONVERSION; ATLTRACE(_T(CPolyProp:Applyn); for (UINT i = 0; i m_nObjects; i+) CComQIPtr pPoly(m_ppUnki); short nSides = (short)GetDlgItemInt(IDC_SIDES); if FAILED(pPoly-put_Sides(nSides) C
30、ComPtr pError; CComBSTR strError; GetErrorInfo(0, &pError); pError-GetDescription(&strError); MessageBox(OLE2T(strError), _T(Error), MB_ICONEXCLAMATION); return E_FAIL; m_bDirty = FALSE; return S_OK;一次可以有不止一个客户端附加到属性页,因此 Apply 函数不断循环,并在每个客户端用从编辑框检索的值调用 put_Sides。您使用的是 CComQIPtr 类,此类对每个对象执行 QueryInterface,以从 IUnknown 接口(存储在 m_ppUnk 数组中)获取 IPolyCtl 接口。代码现在检查对 Sides 属性的设置是否真正有效。如果失败了,则代码显示一个消息框,其中显示了 IErrorInfo 接口中的错误详细信息。一般情况下,容器向对象请求 ISupportErrorInfo 接口并首先调用 InterfaceSupportsErrorInfo,以确定对象是否支持设置错误信息。您可以跳过此任务。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1