在 VB.NET 中初始化 ExtendedWebBrowser,从 C# 到 VB.Net 的解析问题
Initialize ExtendedWebBrowser in VB.NET, problem parsing from C# to VB.Net
根据之前的回答 open link in new tab WebBrowser control。
感谢 Mauricio Rojas 用 C# 发布了一个很好的例子:
Extended WebBrowser Control for C#.
我正在尝试将为 C# 提供的代码转换为 VB.NET,但我遇到了问题:
我不明白为什么,当我尝试在 WebBrowserExtendedEvents
Class 中实现 DWebBrowserEvents2
接口时,Visual Studio 给我一个错误:
Class WebBrowserExtendedEvents must implements Sub NewWindow2(ByRef pDisp As Object, ByRef cancel As Boolean) for the Interface
DWebBrowserEvents2
在我看来,我已经在 Class 和界面中正确地实现了该方法。
Note: I though about removing parts of code not related to the question, as jmcilhinney suggested, but since I didn't find, in the Web, clear examples of ExtendedWebBrowser
for VB.Net, I decided to leave the full code, for the benefit of others.
此处完整代码翻译为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 flags As Object, ByRef targetFrameName As Object, ByRef postData 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
class 定义了实现,但其成员缺少 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(), Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"), [...]
Public Interface DWebBrowserEvents2
'[...]
<DispId(251)>
Sub NewWindow2(<MarshalAs(UnmanagedType.IDispatch)> ByRef pDisp As Object, ByRef cancel As Boolean)
End Interface
▶ 请注意,当您收到 通知时,class 必须实施...,您可以 select 带下划线的成员和按 ALT+ENTER 让 Visual Studio 为您实现界面。
根据之前的回答 open link in new tab WebBrowser control。
感谢 Mauricio Rojas 用 C# 发布了一个很好的例子:
Extended WebBrowser Control for C#.
我正在尝试将为 C# 提供的代码转换为 VB.NET,但我遇到了问题:
我不明白为什么,当我尝试在 WebBrowserExtendedEvents
Class 中实现 DWebBrowserEvents2
接口时,Visual Studio 给我一个错误:
Class WebBrowserExtendedEvents must implements Sub NewWindow2(ByRef pDisp As Object, ByRef cancel As Boolean) for the Interface DWebBrowserEvents2
在我看来,我已经在 Class 和界面中正确地实现了该方法。
Note: I though about removing parts of code not related to the question, as jmcilhinney suggested, but since I didn't find, in the Web, clear examples of
ExtendedWebBrowser
for VB.Net, I decided to leave the full code, for the benefit of others.
此处完整代码翻译为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 flags As Object, ByRef targetFrameName As Object, ByRef postData 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
class 定义了实现,但其成员缺少 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(), Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"), [...]
Public Interface DWebBrowserEvents2
'[...]
<DispId(251)>
Sub NewWindow2(<MarshalAs(UnmanagedType.IDispatch)> ByRef pDisp As Object, ByRef cancel As Boolean)
End Interface
▶ 请注意,当您收到 通知时,class 必须实施...,您可以 select 带下划线的成员和按 ALT+ENTER 让 Visual Studio 为您实现界面。