如何:处理 COM 源引发的事件

更新:2007 年 11 月

如果您不熟悉 .NET Framework 提供的基于委托的事件模型,请参见处理和引发事件。有关适用于本节的特定详细信息,请参见同一节中的使用事件

.NET 客户端(事件接收器)可以接收现有 COM 服务器(事件源)所引发的事件。COM 互操作将在元数据中生成必需的委托,这些委托将包括在托管客户端中。导入的委托签名包括接收事件接口、下划线、事件名称和 EventHandler 一词:SinkEventInterface_EventNameEventHandler。

请注意,在 .NET 客户端中引发事件的 COM 对象在被释放前需要执行两次垃圾回收器 (GC) 回收。 这是由于在 COM 对象和托管客户端之间发生的引用循环导致的。 如果需要显式释放 COM 对象,应该调用两次 Collect 方法。

与现有 COM 事件源互用

  1. 如果 COM 类型将由其他应用程序共享,请获取 COM 服务器的主 interop 程序集。主 interop 程序集包含表示已转换的类型库的元数据,它由发行者签名。

    说明:

    如果主 Interop 程序集不可用或者程序集将以专有方式来使用,则可使用类型库导入程序 (Tlbimp.exe) 或等效的 API 来导入类型库。

    转换过程将为每个事件生成一个委托;不过,您只需接收自己感兴趣的事件。

  2. 可以使用元数据浏览器(如 MSIL 反汇编程序 (Ildasm.exe))来标识事件委托。

  3. 按照从托管事件源使用事件的相同方式从 COM 对象源使用事件。

示例

下面的示例将说明如何打开 Internet Explorer 窗口,并将 InternetExplorer 对象所引发的事件连接到在托管代码中实现的事件处理程序。Internet Explorer 类型(包括事件委托)的定义作为元数据从 SHDocVw.dll 导入。下面的示例会接收 TitleChange 事件。

Option Explicit
Option Strict

Imports System
Imports System.Runtime.InteropServices
Imports SHDocVw

Namespace InternetExplorer
    Public Class Explorer
        Public Shared Sub Main()
            Dim explorer As New Explorer()
            explorer.Run()
        End Sub
      
        Public Sub Run()
            Dim o As Object = Nothing
            Dim s As String
         
            Try
                ' Starts the browser.
                m_IExplorer = New SHDocVw.InternetExplorer()
            Catch e As Exception
                Console.WriteLine("Exception when creating Internet 
                Explorer object {0}", e)
                Return
            End Try
         
            ' Wires your event handlers to m_IExplorer.
            SetAllEvents()
         
            Try
                ' Goes to the home page.
                m_WebBrowser = CType(m_IExplorer, IWebBrowserApp)
                m_WebBrowser.Visible = True
                m_WebBrowser.GoHome()
            
                ' Starts navigating to different URLs.
                Console.Write("Enter URL (or enter to quit): ")
                s = Console.ReadLine()
                While s <> "" And Not (m_IExplorer Is Nothing) _
                And Not (m_WebBrowser Is Nothing)
                    m_WebBrowser.Navigate(s, o, o, o, o)
                    Console.Write("Enter URL (or enter to quit): ")
                    s = Console.ReadLine()
                End While
                m_WebBrowser.Quit()
            Catch sE As Exception
                If m_IExplorer Is Nothing And m_WebBrowser Is Nothing Then
                    Console.WriteLine("Internet Explorer has gone away")
                Else
                    Console.WriteLine("Exception happens {0}", sE)
                End If
            End Try
        End Sub
      
        ' Uses the AddHandler for adding delegates to events.
        Sub SetAllEvents()
            If Not (m_IExplorer Is Nothing) Then
                ' Title Change event
                ' DWebBrowserEvents2 is the name of the sink event interface.
                ' TitleChange is the name of the event.
                ' DWebBrowserEvents2_TitleChangeEventHandler is the delegate 
                ' name assigned by TlbImp.exe.
                Dim DTitleChangeE As New _
DWebBrowserEvents2_TitleChangeEventHandler(AddressOf OnTitleChange)
                AddHandler m_IExplorer.TitleChange, DTitleChangeE
            End If
        End Sub
      
        '----------------------------------------------------------------
        ' Defines event handlers.
        ' Document title changed
        Shared Sub OnTitleChange(sText As String)
            Console.WriteLine("Title changes to {0}", sText)
        End Sub
      
      
        End Sub
        '----------------------------------------------------------------
        ' The following are class fields.
        Private Shared m_IExplorer As SHDocVw.InternetExplorer = Nothing
        Private Shared m_WebBrowser As IWebBrowserApp = Nothing
    End Class
End Namespace
namespace InternetExplorer
{
    using System;
    using System.Runtime.InteropServices;
    using SHDocVw;

    public class Explorer 
    {
        public static void Main()
        {
            Explorer explorer = new Explorer();
            explorer.Run();
        }
        public void Run()
        {
            Object o = null;
            String s;

            try
            {
                // Starts the browser.
                m_IExplorer = new SHDocVw.InternetExplorer();
            }
            catch(Exception e)
            {
                Console.WriteLine("Exception when creating Internet 
                Explorer object {0}", e);
                return;
            }

            // Wires your event handlers to m_IExplorer.
            SetAllEvents();

            try
            {  
                // Goes to the home page.
                m_WebBrowser = (IWebBrowserApp) m_IExplorer;
                m_WebBrowser.Visible = true;
                m_WebBrowser.GoHome();

                // Starts navigating to different URLs.
                Console.Write("Enter URL (or enter to quit): ");
                s = Console.ReadLine();
                while (s != "" && m_IExplorer != null &&
                    m_WebBrowser != null)
                {
                    m_WebBrowser.Navigate(s, ref o, ref o, ref o,
                          ref o);
                    Console.Write("Enter URL (or enter to quit): ");      
                    s = Console.ReadLine();
                }

                m_WebBrowser.Quit();
            }
            catch(Exception sE)
            {
                if (m_IExplorer == null && m_WebBrowser == null)
                {
                    Console.WriteLine("Internet Explorer has gone away");
                }
                else
                {
                    Console.WriteLine("Exception happens {0}", sE);
                }
            }
        }
        // Uses the += syntax for adding delegates to events.
        void SetAllEvents()
        {
            if (m_IExplorer != null)
            {
                // Title Change event
                // DWebBrowserEvents2 is the name of the sink event
                //interface.
                // TitleChange is the name of the event.
                // DWebBrowserEvents2_TitleChangeEventHandler is the 
                // delegate name assigned by TlbImp.exe.
                DWebBrowserEvents2_TitleChangeEventHandler 
                   DTitleChangeE = new DWebBrowserEvents2_TitleChangeEventHandler(OnTitleChange);
                m_IExplorer.TitleChange += DTitleChangeE;
            }
        }
///////////////////////////////////////////////////////////////////////
        // Define event handlers.
        // Document title changed
        static void OnTitleChange(String Text)
        {
            Console.WriteLine("Title changes to {0}", Text);
        }
   
//////////////////////////////////////////////////////////////////////////
        // The following are class fields.
        static private SHDocVw.InternetExplorer m_IExplorer = null;
        static private IWebBrowserApp m_WebBrowser = null;
    }
}

请参见

任务

如何:引发 COM 接收器所处理的事件

概念

向 .NET Framework 公开 COM 组件

参考

MSIL 反汇编程序 (Ildasm.exe)

其他资源

托管和非托管事件