在VB.NET中初始化ExtendedWebBrowser,将问题从C#解析为VB.Net

问题描述

遵循上一个答案open link in new tab WebBrowser control

感谢Mauricio Rojas在C#中发布了一个很好的例子:
Extended WebBrowser Control for C#

我正在尝试将C#提供的代码转换为VB.NET,但是我遇到了问题:
我不明白为什么,当我尝试在DWebBrowserEvents2类中实现WebBrowserExtendedEvents接口时,Visual Studio给我一个错误:

类WebBrowserExtendedEvents必须为接口实现Sub NewWindow2(ByRef pDisp为对象,ByRef取消为布尔值) DWebBrowserEvents2

在我看来,我已经在类和接口中正确实现了该方法。

注意:尽管我按照jmcilhinney的建议删除了与问题无关的部分代码,但是由于我没有在Web上找到VB.Net的ExtendedWebBrowser的清晰示例, ,为了其他人的利益,我决定保留完整的代码。

此处将完整代码翻译为VB.Net

'First define a new EventArgs class to contain the newly exposed data
Public Class NewWindow2EventArgs
    Inherits CancelEventArgs

    Private _ppDisp As Object
    Public Property PPDisp As Object
        Get
            Return _ppDisp
        End Get
        Set(value As Object)
            _ppDisp = value
        End Set
    End Property

    Public Sub New(ByRef ppDisp As Object,ByRef cancel As Boolean)
        MyBase.New()
        Me.ppDisp = Me.ppDisp
        Me.Cancel = cancel
    End Sub
End Class

Public Class DocumentCompleteEventArgs
    Inherits EventArgs

    Private _ppDisp As Object
    Public Property PPDisp As Object
        Get
            Return _ppDisp
        End Get
        Set(value As Object)
            _ppDisp = value
        End Set
    End Property

    Private _url As Object
    Public Property Url As Object
        Get
            Return _url
        End Get
        Set(value As Object)
            _url = value
        End Set
    End Property

    Public Sub New(ByVal ppDisp As Object,ByVal url As Object)
        MyBase.New()
        Me.ppDisp = Me.ppDisp
        Me.url = Me.url
    End Sub
End Class

Public Class CommandStateChangeEventArgs
    Inherits EventArgs

    Private _command As Long
    Public Property Command As Long
        Get
            Return _command
        End Get
        Set(value As Long)
            _command = value
        End Set
    End Property

    Private _enable As Boolean
    Public Property Enable As Boolean
        Get
            Return _enable
        End Get
        Set(value As Boolean)
            _enable = value
        End Set
    End Property

    Public Sub New(ByVal command As Long,ByRef enable As Boolean)
        MyBase.New()
        Me.command = Me.command
        Me.enable = Me.enable
    End Sub

End Class

'Extend the WebBrowser control
Public Class ExtendedWebBrowser
    Inherits WebBrowser

    Private cookie As AxHost.ConnectionPointCookie

    Private Shadows events As WebBrowserExtendedEvents

    'This method will be called to give you a chance to create your own event sink
    Protected Overrides Sub CreateSink()
        'MAKE SURE TO CALL THE BASE or the normal events won't fire
        MyBase.CreateSink()
        Me.events = New WebBrowserExtendedEvents(Me)
        Me.cookie = New AxHost.ConnectionPointCookie(Me.ActiveXInstance,Me.events,GetType(DWebBrowserEvents2))
    End Sub

    Public ReadOnly Property Application As Object
        Get
            Dim axWebBrowser As IWebBrowser2 = CType(Me.ActiveXInstance,IWebBrowser2)
            If (Not (axWebBrowser) Is Nothing) Then
                Return axWebBrowser.Application
            Else
                Return Nothing
            End If

        End Get
    End Property

    Protected Overrides Sub DetachSink()
        If (Not (Me.cookie) Is Nothing) Then
            Me.cookie.Disconnect()
            Me.cookie = Nothing
        End If

        MyBase.DetachSink()
    End Sub

    'This new event will fire for the NewWindow2
    Public Event NewWindow2 As EventHandler(Of NewWindow2EventArgs)

    Protected Sub OnNewWindow2(ByRef ppDisp As Object,ByRef cancel As Boolean)
        'Dim h As EventHandler(Of NewWindow2EventArgs) = NewWindow2

        Dim args As NewWindow2EventArgs = New NewWindow2EventArgs(ppDisp,cancel)
        If Not IsNothing(NewWindow2Event) Then
            RaiseEvent NewWindow2(Me,args)
        End If

        'Pass the cancellation chosen back out to the events
        'Pass the ppDisp chosen back out to the events
        cancel = args.Cancel
        ppDisp = args.PPDisp
    End Sub

    'This new event will fire for the DocumentComplete
    Public Event DocumentComplete As EventHandler(Of DocumentCompleteEventArgs)

    Protected Sub OnDocumentComplete(ByVal ppDisp As Object,ByVal url As Object)
        'Dim h As EventHandler(Of DocumentCompleteEventArgs) = DocumentComplete
        Dim args As DocumentCompleteEventArgs = New DocumentCompleteEventArgs(ppDisp,url)
        If Not IsNothing(DocumentCompleteEvent) Then
            RaiseEvent DocumentComplete(Me,args)
        End If

        'Pass the ppDisp chosen back out to the events
        ppDisp = args.PPDisp
        'I think url is readonly
    End Sub

    'This new event will fire for the CommandStateChange
    Public Event CommandStateChange As EventHandler(Of CommandStateChangeEventArgs)

    Protected Sub OnCommandStateChange(ByVal command As Long,ByRef enable As Boolean)
        'Dim h As EventHandler(Of CommandStateChangeEventArgs) = CommandStateChange
        Dim args As CommandStateChangeEventArgs = New CommandStateChangeEventArgs(command,enable)
        If Not IsNothing(CommandStateChangeEvent) Then
            RaiseEvent CommandStateChange(Me,args)
        End If

    End Sub

    'This class will capture events from the WebBrowser
    Public Class WebBrowserExtendedEvents
        Inherits System.Runtime.InteropServices.StandardOleMarshalObject

        '******************* HERE THE ERROR ********************
        Implements DWebBrowserEvents2
        '*******************************************************

        Private _Browser As ExtendedWebBrowser

        Public Sub New(ByVal browser As ExtendedWebBrowser)
            MyBase.New()
            Me._Browser = browser
        End Sub

        'Implement whichever events you wish
        Public Sub NewWindow2(ByRef pDisp As Object,ByRef cancel As Boolean)
            Me._Browser.OnNewWindow2(pDisp,cancel)
        End Sub

        'Implement whichever events you wish
        Public Sub DocumentComplete(ByVal pDisp As Object,ByRef url As Object)
            Me._Browser.OnDocumentComplete(pDisp,url)
        End Sub

        'Implement whichever events you wish
        Public Sub CommandStateChange(ByVal command As Long,ByVal enable As Boolean)
            Me._Browser.OnCommandStateChange(command,enable)
        End Sub

    End Class

    <ComImport(),_
     Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"),_
     InterfaceType(ComInterfaceType.InterfaceIsIDispatch),_
     TypeLibType(TypeLibTypeFlags.FHidden)> _
    Public Interface DWebBrowserEvents2

        <DispId(105)> _
        Sub CommandStateChange(ByVal command As Long,ByVal enable As Boolean)

        <DispId(259)> _
        Sub DocumentComplete(ByVal pDisp As Object,ByRef URL As Object)

        <DispId(251)> _
        Sub NewWindow2(ByRef pDisp As Object,ByRef cancel As Boolean)

    End Interface

    <ComImport(),_
     Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E"),_
     TypeLibType((TypeLibTypeFlags.FOleAutomation _
                Or (TypeLibTypeFlags.FDual Or TypeLibTypeFlags.FHidden)))> _
    Public Interface IWebBrowser2

        <DispId(100)> _
        Sub GoBack()

        <DispId(101)> _
        Sub GoForward()

        <DispId(102)> _
        Sub GoHome()

        <DispId(103)> _
        Sub GoSearch()

        <DispId(104)> _
        Sub Navigate(ByVal Url As String,ByRef flags As Object,ByRef targetFrameName As Object,ByRef postData As Object,ByRef headers As Object)

        <DispId(-550)> _
        Sub Refresh()

        <DispId(105)> _
        Sub Refresh2(ByRef level As Object)

        <DispId(106)> _
        Sub [Stop]()

        <DispId(200)> _
        ReadOnly Property Application As Object

        <DispId(201)> _
        ReadOnly Property Parent As Object

        <DispId(202)> _
        ReadOnly Property Container As Object

        <DispId(203)> _
        ReadOnly Property Document As Object

        <DispId(204)> _
        ReadOnly Property TopLevelContainer As Boolean

        <DispId(205)> _
        ReadOnly Property Type As String

        <DispId(206)> _
        Property Left As Integer

        <DispId(207)> _
        Property Top As Integer

        <DispId(208)> _
        Property Width As Integer

        <DispId(209)> _
        Property Height As Integer

        <DispId(210)> _
        ReadOnly Property LocationName As String

        <DispId(211)> _
        ReadOnly Property LocationURL As String

        <DispId(212)> _
        ReadOnly Property Busy As Boolean

        <DispId(300)> _
        Sub Quit()

        <DispId(301)> _
        Sub ClientToWindow(ByRef pcx As Integer,ByRef pcy As Integer)

        <DispId(302)> _
        Sub PutProperty(ByVal _property As String,ByVal vtValue As Object)

        <DispId(303)> _
        Function GetProperty(ByVal _property As String) As Object

        <DispId(0)> _
        ReadOnly Property Name As String

        <DispId(-515)> _
        ReadOnly Property HWND As Integer

        <DispId(400)> _
        ReadOnly Property FullName As String

        <DispId(401)> _
        ReadOnly Property Path As String

        <DispId(402)> _
        Property Visible As Boolean

        <DispId(403)> _
        Property StatusBar As Boolean

        <DispId(404)> _
        Property StatusText As String

        <DispId(405)> _
        Property ToolBar As Integer

        <DispId(406)> _
        Property MenuBar As Boolean

        <DispId(407)> _
        Property FullScreen As Boolean

        <DispId(500)> _
        Sub Navigate2(ByRef URL As Object,ByRef headers As Object)

        <DispId(503)> _
        Sub ShowBrowserBar(ByRef pvaClsid As Object,ByRef pvarShow As Object,ByRef pvarSize As Object)

        <DispId(-525)> _
        ReadOnly Property ReadyState As WebBrowserReadyState

        <DispId(550)> _
        Property Offline As Boolean

        <DispId(551)> _
        Property Silent As Boolean

        <DispId(552)> _
        Property RegisterAsBrowser As Boolean

        <DispId(553)> _
        Property RegisterAsDropTarget As Boolean

        <DispId(554)> _
        Property TheaterMode As Boolean

        <DispId(555)> _
        Property AddressBar As Boolean

        <DispId(556)> _
        Property Resizable As Boolean
    End Interface
End Class

解决方法

VB.Net要求将Implements keyword添加到实现相应接口成员的成员。

您的WebBrowserExtendedEvents类定义了实现,但是其成员缺少Implements关键字,仅此而已。例如:

Public Sub NewWindow2(ByRef pDisp As Object,ByRef cancel As Boolean)
    Me._Browser.OnNewWindow2(pDisp,cancel)
End Sub

需要更改(由于不能将其写成两行,因此将其保留在一行中):

Public Sub NewWindow2(ByRef pDisp As Object,ByRef cancel As Boolean) Implements DWebBrowserEvents2.NewWindow2
    Me._Browser.OnNewWindow2(pDisp,cancel)
End Sub

我还建议保留在C#示例代码中找到的MarshalAs属性。
例如,在DWebBrowserEvents2接口定义中,更改:

<ComImport(),Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"),[...]
Public Interface DWebBrowserEvents2
    '[...]
    <DispId(251)> _
    Sub NewWindow2(ByRef pDisp As Object,ByRef cancel As Boolean)
End Interface

在:

<ComImport(),[...]
Public Interface DWebBrowserEvents2
    '[...]
    <DispId(251)>
    Sub NewWindow2(<MarshalAs(UnmanagedType.IDispatch)> ByRef pDisp As Object,ByRef cancel As Boolean)
End Interface

►请注意,当您收到该类必须实现... 的通知时,可以选择带下划线的成员,然后按ALT+ENTER以使Visual Studio实现接口为你。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...