65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 VC++ 和 ATL 的连接点入门教程

2002年4月11日

5分钟阅读

viewsIcon

175366

downloadIcon

1510

关于如何使用 VC++ 和 ATL 创建连接点的教程。

引言

本文的目的是提供一个使用 VC++ 和 ATL 实现连接点的入门教程。从简单化的角度来看,我倾向于将连接点视为 COM 的事件处理机制。因此,如果您创建了一个 ActiveX 控件,例如一个按钮,并且希望由控件的容器而不是控件本身来处理点击事件,您将使用连接点。然而,您也可以超越只处理 Windows 事件,创建自己的事件。我发现使用 VC++ 6.0 创建连接点有些令人困惑,而且不是很直观。我几年前在创建一些控件时做了这些,最近又不得不使用连接点,但完全记不起第一次是如何实现的。本教程旨在帮助您弄清楚如何使用 VC++ 创建连接点。

项目

这里的一些内容将与其他文章中的内容重复。我会尽量简洁,并假定您知道如何创建 ATL DLL 并在其中创建控件。让我们开始使用 VC++ 向导创建一个名为 Connection 的 ATL COM DLL。然后,我们创建一个复合控件。您可以创建任何控件或对象。复合控件只是允许我提供一个很好的示例。我不会展示如何创建这些,因为我假设您知道。如果您不知道如何这样做,您应该阅读这里发布的其他一些文章。将此控件命名为 ConnCtl。在创建控件时,选择属性选项卡,然后选择“支持连接点”复选框。然后单击“确定”。

Screenshot - Pic_1.jpg

VC++ 这将自动将您带到资源编辑器,用于放置控件并构建您的复合控件。首先,让我们在该控件上放置一个按钮。您可以双击按钮,或者在 ClassView 中右键单击 CConCtl ,然后选择“添加 Windows 消息处理程序”。我们添加一个处理程序来处理按钮的点击。这与我们在使用 VC++ 的常规 Windows 应用程序中添加 Windows 消息处理程序的方式没有不同。在消息处理函数中,让我们添加一个消息框来显示我们已处理了点击事件。

LRESULT CConnCtl::OnClickedButton(WORD wNotifyCode, WORD wID, 
    HWND hWndCtl, BOOL& bHandled) 
{
    ::MessageBox( hWndCtl, "Button was clicked"", 
        "Handled in Control", MB_OK" );
    return 0;
}

构建项目并测试控件。当您单击按钮时,您将看到我们添加的消息框。所以现在我们有了一个包含按钮的 ActiveX 控件,并且当您单击按钮时,您会收到我们的消息框。太棒了!您可以在任何 COM 容器中使用此控件。那么连接点在哪里呢?

现在,假设您想在容器中捕获按钮点击事件。或者更确切地说,如果您想让控件通知容器按钮已被点击。这时就需要实现连接点。

为此,首先转到类视图,右键单击 _IconnCtlEvents ,然后添加一个方法,该方法将表示您的控件将提供给容器的接口,告知按钮已被点击。我们将其命名为 OnControlButtonClicked 。我们传递一个 BSTR 。您可以传递任何内容。我想您应该传递与按钮点击相关的参数。嗯,您自己去想吧。

Screenshot - Pic_2.jpg

现在是棘手的部分。我总是在这里出错,并且倾向于忘记创建连接点需要做什么。您需要编译项目。我总是忘记做这件事,然后想知道为什么后续步骤不起作用。现在在类视图中右键单击 CConCtl ,然后选择“实现连接点”。您将看到一个对话框。

Screenshot - Pic_3.jpg

选中 IConnCtlEvents ,然后单击“确定”。现在 VC++ 会为您实现连接点。在类视图中,您将看到创建了 CProxy_IConnCtlEvents< class T>,并且它提供了 Fire_OnControlButtonClicked(BSTR someStr) 。接下来,为了使连接点工作,也就是说,为了让您的代码通知其容器按钮已被点击,我们将 Fire_OnControlButtonClicked(BSTR someStr) 添加到前面创建的 Windows 消息处理函数中。

LRESULT CConnCtl::OnClickedButton(WORD wNotifyCode, 
    WORD wID, HWND hWndCtl, BOOL& bHandled) 
{
    ::MessageBox( hWndCtl, "Button was clicked", 
        "Handled in Control", MB_OK );

    Fire_OnControlButtonClicked( CComBSTR( 
        "This message has been fired to the container" ) );

    return 0;
}

现在编译项目,如果一切按预期进行,您应该会收到一些编译错误,内容大致是找不到 IID__IConnCtlEvents 。如果出现这种情况,请将 ConnCTL.h 中的 IID__IconnCtlEvents 修改如下所示。我一直很奇怪这是否是我的 VC++ 安装问题还是 VC++ 的一个 bug。

BEGIN_CONNECTION_POINT_MAP(CConnCtl)
    CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
    CONNECTION_POINT_ENTRY(DIID__IConnCtlEvents)
END_CONNECTION_POINT_MAP()

现在您有了一个控件,它可以处理 Windows 按钮点击事件,并按照您的定义将其传递(这非常酷。您作为开发者可以决定如何触发此事件以及向容器发送什么信息)。如果您将此控件放在 VB 表单中,您将能够像这样捕获 ConnCtl 触发的按钮点击事件

Private Sub ConnCtl1_OnControlButtonClicked( ByVal someStr As String )
    'Now the container can do further processing once the button is clicked.
End Sub

只处理 Windows 消息?

连接点是否仅用于传递 Windows 消息?不。连接点是一种 COM 对象、服务器或控件提供接口的方式,通过该接口,其他对象、应用程序等可以接收事件通知。您可以阅读 Brent Rector 和 Chris Sells 的 ATL Internals。

那么,假设我们不仅想让控件容器知道我们何时点击了按钮,还想知道我们何时第 10 次点击了它。设置此过程非常简单。再次在类视图中右键单击 _IconnCtlEvents ,然后选择添加方法的选项。我们将其命名为 OnTenthClick 。再次编译项目。然后右键单击 CConCtl ,然后选择“实现连接点”。按照上述步骤进行。现在您就可以为容器提供一个接口,该接口将在用户点击 10 次时通知容器。嗯,实际上并非如此。您所做的只是创建了一个具有该名称的接口。现在您必须计算点击次数,当达到十次时,您必须调用 Fire_OnTenthClick()

LRESULT CConnCtl::OnClickedButton(WORD wNotifyCode, 
     WORD wID, HWND hWndCtl, BOOL& bHandled) 
{
    ::MessageBox( hWndCtl, "Button was clicked", 
        "Handled in Control", MB_OK );

    Fire_OnControlButtonClicked( CComBSTR( 
        "This message has been fired to the container" ) );

    ClickCounter();  //Do stuff with how many times 
                     //the button has been clicked

    return 0;
}
void CConnCtl::ClickCounter() 
{
    _clickCount++;

    if( 10 == _clickCount ) 
    {
        Fire_OnTenthClick( CComBSTR( "Button has been clicked 10 times" ) );
    }
}

结论

连接点是处理事件的绝佳机制,使用 ATL 在 VC++ 中实现它们非常容易(除了一些不直观的步骤)。请注意,连接点可以为任何 COM 对象创建,而不仅仅是控件。

© . All rights reserved.