How to: Webbrowser NewWindow and Navigating equivalent to axWebbrowser
-
Friday, May 06, 2005 2:34 AM
At first, I enjoyed the new webbrowser control but then I noticed that the args provided by the events NewWindow3 and BeforeNavigate of the axWebBrowser had not been implemented in the new control. Arg.
Good news, the guys from Microsoft gave us the a workaround recently in C# and said they will publish a sample soon on MSDN.
In the mean time, here is some VB.net code inspired from Microsoft's C# that will give you 2 new events and the args people like me were crying for.
NavigatingExtended gives you the following args:
- Url as string
- Frame as string
- Headers as string
- Postdata as string
- PostdataByte() as byte
- Cancel as boolean (to cancel navigation)
NewWindowExtended gives you the following args:
- Url as string
- UrlContext as string
- Flags as NWMF (see NewWindow3 on MSDN for definition)
- Cancel as boolean (to cancel navigation to new window)
Ok let's go.
1. Create a new Windows form project.
2. Add a new Module and Copy/Paste the following:
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Module Module1
Public Enum NWMF
NWMF_UNLOADING = &H1&
NWMF_USERINITED = &H2&
NWMF_FIRST_USERINITED = &H4&
NWMF_OVERRIDEKEY = &H8&
NWMF_SHOWHELP = &H10&
NWMF_HTMLDIALOG = &H20&
NWMF_FROMPROXY = &H40&
End Enum
'First define a new EventArgs class to contain the newly exposed data
Public Class WebBrowserNavigatingExtendedEventArgs
Inherits CancelEventArgs
Private m_Url As String
Private m_Frame As String
Private m_Postdata() As Byte
Private m_Headers As String
Public ReadOnly Property Url() As String
Get
Return m_Url
End Get
End Property
Public ReadOnly Property Frame() As String
Get
Return m_Frame
End Get
End Property
Public ReadOnly Property Headers() As String
Get
Return m_Headers
End Get
End Property
Public ReadOnly Property Postdata() As String
Get
Return PostdataToString(m_Postdata)
End Get
End Property
Public ReadOnly Property PostdataByte() As Byte()
Get
Return m_Postdata
End Get
End Property
Public Sub New(ByVal url As String, ByVal frame As String, ByVal postdata As Byte(), ByVal headers As String)
m_Url = url
m_Frame = frame
m_Postdata = postdata
m_Headers = headers
End Sub
Private Function PostdataToString(ByVal p() As Byte) As String
'not sexy but it works...
Dim tabpd() As Byte, bstop As Boolean = False, stmp As String = "", i As Integer = 0
tabpd = p
If tabpd Is Nothing OrElse tabpd.Length = 0 Then
Return ""
Else
For i = 0 To tabpd.Length - 1
stmp += ChrW(tabpd(i))
Next
stmp = Replace(stmp, ChrW(13), "")
stmp = Replace(stmp, ChrW(10), "")
stmp = Replace(stmp, ChrW(0), "")
End If
If stmp = Nothing Then
Return ""
Else
Return stmp
End If
End Function
End Class
Public Class WebBrowserNewWindowExtendedEventArgs
Inherits CancelEventArgs
Private m_Url As String
Private m_UrlContext As String
Private m_Flags As NWMF
Public ReadOnly Property Url() As String
Get
Return m_Url
End Get
End Property
Public ReadOnly Property UrlContext() As String
Get
Return m_UrlContext
End Get
End Property
Public ReadOnly Property Flags() As NWMF
Get
Return m_Flags
End Get
End Property
Public Sub New(ByVal url As String, ByVal urlcontext As String, ByVal flags As NWMF)
m_Url = url
m_UrlContext = urlcontext
m_Flags = flags
End Sub
End Class
Public Class ExtendedWebBrowser
Inherits WebBrowser
Private cookie As AxHost.ConnectionPointCookie
Private wevents 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()
wevents = New WebBrowserExtendedEvents(Me)
cookie = New AxHost.ConnectionPointCookie(Me.ActiveXInstance, wevents, GetType(DWebBrowserEvents2))
End Sub
Protected Overrides Sub DetachSink()
If Not cookie Is Nothing Then
cookie.Disconnect()
cookie = Nothing
End If
MyBase.DetachSink()
End Sub
'This new event will fire when the page is navigating
Public Delegate Sub WebBrowserNavigatingExtendedEventHandler(ByVal sender As Object, ByVal e As WebBrowserNavigatingExtendedEventArgs)
Public Event NavigatingExtended As WebBrowserNavigatingExtendedEventHandler
'This event will fire when a new window is about to be opened
Public Delegate Sub WebBrowserNewWindowExtendedEventHandler(ByVal sender As Object, ByVal e As WebBrowserNewWindowExtendedEventArgs)
Public Event NewWindowExtended As WebBrowserNewWindowExtendedEventHandler
Protected Friend Sub OnNavigatingExtended(ByVal Url As String, ByVal Frame As String, ByVal Postdata As Byte(), ByVal Headers As String, ByRef Cancel As Boolean)
Dim e As WebBrowserNavigatingExtendedEventArgs = New WebBrowserNavigatingExtendedEventArgs(Url, Frame, Postdata, Headers)
RaiseEvent NavigatingExtended(Me, e)
Cancel = e.Cancel
End Sub
Protected Friend Sub OnNewWindowExtended(ByVal Url As String, ByRef Cancel As Boolean, ByVal Flags As NWMF, ByVal UrlContext As String)
Dim e As WebBrowserNewWindowExtendedEventArgs = New WebBrowserNewWindowExtendedEventArgs(Url, UrlContext, Flags)
RaiseEvent NewWindowExtended(Me, e)
Cancel = e.Cancel
End Sub
End Class
'This class will capture events from the WebBrowser
Class WebBrowserExtendedEvents
Inherits System.Runtime.InteropServices.StandardOleMarshalObject
Implements DWebBrowserEvents2
Private m_Browser As ExtendedWebBrowser
Public Sub New(ByVal browser As ExtendedWebBrowser)
m_Browser = browser
End Sub
'Implement whichever events you wish
Public Sub BeforeNavigate2(ByVal pDisp As Object, ByRef URL As String, ByRef flags As Object, ByRef targetFrameName As String, ByRef postData As Object, ByRef headers As String, ByRef cancel As Boolean) Implements DWebBrowserEvents2.BeforeNavigate2
m_Browser.OnNavigatingExtended(URL, targetFrameName, CType(postData, Byte()), headers, cancel)
End Sub
Public Sub NewWindow3(ByVal pDisp As Object, ByRef Cancel As Boolean, ByRef Flags As Object, ByRef UrlContext As String, ByRef Url As String) Implements DWebBrowserEvents2.NewWindow3
m_Browser.OnNewWindowExtended(Url, Cancel, CType(Flags, NWMF), UrlContext)
End Sub
End Class
<ComImport(), _
Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch), _
TypeLibType(TypeLibTypeFlags.FHidden)> _
Public Interface DWebBrowserEvents2
<DispId(250)> _
Sub BeforeNavigate2(<[In](), MarshalAs(UnmanagedType.IDispatch)> ByVal pDisp As Object, _
<InAttribute(), MarshalAs(UnmanagedType.BStr)> ByRef URL As String, _
<InAttribute()> ByRef flags As Object, _
<InAttribute(), MarshalAs(UnmanagedType.BStr)> ByRef targetFrameName As String, _
<InAttribute()> ByRef postdata As Object, _
<InAttribute(), MarshalAs(UnmanagedType.BStr)> ByRef headers As String, _
<InAttribute(), OutAttribute()> ByRef cancel As Boolean)
'Note: Postdata is a SafeArray but for some reason, if I do a proper declaration, the event will not be raised:
'<[In](), MarshalAs(UnmanagedType.SafeArray, safearraysubtype:=VarEnum.VT_UI1)> ByRef postdata() As Byte, _
<DispId(273)> _
Sub NewWindow3(<InAttribute(), MarshalAs(UnmanagedType.IDispatch)> ByVal pDisp As Object, _
<InAttribute(), OutAttribute()> ByRef cancel As Boolean, _
<InAttribute()> ByRef Flags As Object, _
<InAttribute(), MarshalAs(UnmanagedType.BStr)> ByRef UrlContext As String, _
<InAttribute(), MarshalAs(UnmanagedType.BStr)> ByRef Url As String)
End Interface
End Module
3. Now, Open your form1 in Code view
4. Copy/Paste the following to test your control
Public Class Form1
'Source from wilfridB
Private wb As New ExtendedWebBrowser
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
AddHandler wb.NavigatingExtended, AddressOf wb_NavigatingExtended
AddHandler wb.DocumentCompleted, AddressOf wb_DocumentCompleted
AddHandler wb.NewWindowExtended, AddressOf wb_NewWindowExtended
Me.Controls.Add(wb)
wb.Dock = DockStyle.Fill
wb.Navigate(New Uri("http://www.microsoft.com"))
End Sub
Private Sub wb_NavigatingExtended(ByVal sender As Object, ByVal e As module1.WebBrowserNavigatingExtendedEventArgs)
'This is a new event
Dim postdata As String = e.Postdata
Dim msg As String = "Navigating to : " & e.Url & ControlChars.CrLf
msg &= "Postdata : " & postdata & ControlChars.CrLf
msg &= "Headers : " & e.Headers & ControlChars.CrLf
msg &= "Frame : " & e.Frame & ControlChars.CrLf
msg &= "Continue ?"
Dim res As DialogResult = MessageBox.Show(msg, "NavigatingExtended", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If res = Windows.Forms.DialogResult.No Then e.Cancel = True
End Sub
Private Sub wb_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs)
'This is a standard event
MessageBox.Show("Document complete: " & e.Url.ToString, "DocumentCompleted", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Private Sub wb_NewWindowExtended(ByVal sender As Object, ByVal e As Module1.WebBrowserNewWindowExtendedEventArgs)
'This is a new event
Dim msg As String = "Navigation vers : " & e.Url & ControlChars.CrLf
msg &= "UrlContext : " & e.UrlContext & ControlChars.CrLf
msg &= "Flags : " & e.Flags.ToString & ControlChars.CrLf
msg &= "Continue ?"
Dim res As DialogResult = MessageBox.Show(msg, "NewWindowExtended", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If res = Windows.Forms.DialogResult.No Then e.Cancel = True
End Sub
End Class
That's it and it should work...
Any comment or additional event implementation is welcome...
And if somebody could give me the solution for properly retrieving the postdata using something like:
<[In](), MarshalAs(UnmanagedType.SafeArray, safearraysubtype:=VarEnum.VT_UI1)> ByRef postdata() As Byte, _
And converting an array of byte in a more decent way, that would be great.
wilfridB
All Replies
-
Saturday, May 14, 2005 11:20 AMAs for the daclaration question: no idea so far
But you could replace 'PostdataToString' with
Public ReadOnly Property Postdata() As String
Get 'Return PostdataToString(m_Postdata) Dim encode As System.Text.Encoding = System.Text.Encoding.UTF8 Return encode.GetString(m_Postdata) End Get End Property -
Monday, May 16, 2005 9:13 PMThanks for the reply, Orbit.
Actually, I wonder if the best solution is not to leave it as an array of byte and in the calling code to add to the sub mybrowser_NavigatingExtended something like
'do not forget to check if objects exist
Dim CurrentDoc as IHTMLDocument2 = Ctype(mybrowser.Document, IHTMLDocument2)
Dim PageEncoding as Encoding = Encoding.GetEncoding(CurrentDoc.defaultCharset)
Dim PostDataString as String = System.Web.HttpUtility.UrlDecode(CType(e.postData, Byte()), PageEncoding)
then, you get the right encoding.
------------------
By the way, does anybody have an idea how I could add the "Application" property to the WebbrowserExtended Class (similar to the one from axWebBrowser) so I can set ppDisp in NewWindow3 and redirect the new page to a custom browser ?
wilfridB -
Thursday, June 09, 2005 7:40 PM
"Good news, the guys from Microsoft gave us the a workaround recently in C# and said they will publish a sample soon on MSDN."
Is this work-around available to share ?
thanks, Bill -
Thursday, June 09, 2005 7:46 PM
-
Friday, November 04, 2005 9:46 PM
WilfridB wrote:
By the way, does anybody have an idea how I could add the "Application" property to the WebbrowserExtended Class (similar to the one from axWebBrowser) so I can set ppDisp in NewWindow3 and redirect the new page to a custom browser ?
wilfridB
Sorry, but I do not think this is possible. The reason for this is that the object "AxWebbrowser" (used internally by the webbrowser control) is not exposed, even not for inheritors. (It's declared "Private")Therefore the property is not available, since it's never called by any member of the class.
I also would like to use this functionality, but it seems that this will only be possible when you write your own (complete) control
-
Friday, November 04, 2005 10:20 PM
WilfridB wrote: Thanks for the reply, Orbit.
Actually, I wonder if the best solution is not to leave it as an array of byte and in the calling code to add to the sub mybrowser_NavigatingExtended something like
'do not forget to check if objects exist
Dim CurrentDoc as IHTMLDocument2 = Ctype(mybrowser.Document, IHTMLDocument2)
Dim PageEncoding as Encoding = Encoding.GetEncoding(CurrentDoc.defaultCharset)
Dim PostDataString as String = System.Web.HttpUtility.UrlDecode(CType(e.postData, Byte()), PageEncoding)
then, you get the right encoding.
------------------
By the way, does anybody have an idea how I could add the "Application" property to the WebbrowserExtended Class (similar to the one from axWebBrowser) so I can set ppDisp in NewWindow3 and redirect the new page to a custom browser ?
wilfridB
Oooops, it seems that I missed one. Here goes:
1: Declare an interface "IWebBrowser2"
2: Override "AttachInterfaces" and set a private field to the value of the parameter "nativeActiveXObject"
3: Override "DetachInterfaces" to set this private field back to "null"
3: Use this private field's "Application" property
That's all there's to it.
An example in c#:
internal static class UnsafeNativeMethods
{
[System.Runtime.InteropServices.ComImport(), System.Runtime.InteropServices.Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"),
System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch),
System.Runtime.InteropServices.TypeLibType(System.Runtime.InteropServices.TypeLibTypeFlags.FHidden)]
public interface DWebBrowserEvents2
{
[System.Runtime.InteropServices.DispId(250)]
void BeforeNavigate2(
[System.Runtime.InteropServices.In,
System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.IDispatch)] object pDisp,
[System.Runtime.InteropServices.In] ref object URL,
[System.Runtime.InteropServices.In] ref object flags,
[System.Runtime.InteropServices.In] ref object targetFrameName, [System.Runtime.InteropServices.In] ref object postData,
[System.Runtime.InteropServices.In] ref object headers,
[System.Runtime.InteropServices.In,
System.Runtime.InteropServices.Out] ref bool cancel);
[System.Runtime.InteropServices.DispId(273)]
void NewWindow3(
[System.Runtime.InteropServices.In,
System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.IDispatch)] object pDisp,
[System.Runtime.InteropServices.In, System.Runtime.InteropServices.Out] ref bool cancel,
[System.Runtime.InteropServices.In] ref object flags,
[System.Runtime.InteropServices.In] ref object URLContext,
[System.Runtime.InteropServices.In] ref object URL);
}[ComImport, SuppressUnmanagedCodeSecurity, TypeLibType(TypeLibTypeFlags.FOleAutomation | (TypeLibTypeFlags.FDual | TypeLibTypeFlags.FHidden)), Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")]
public interface IWebBrowser2
{
[DispId(100)]
void GoBack();
[DispId(0x65)]
void GoForward();
[DispId(0x66)]
void GoHome();
[DispId(0x67)]
void GoSearch();
[DispId(0x68)]
void Navigate([In] string Url, [In] ref object flags, [In] ref object targetFrameName, [In] ref object postData, [In] ref object headers);
[DispId(-550)]
void Refresh();
[DispId(0x69)]
void Refresh2([In] ref object level);
[DispId(0x6a)]
void Stop();
[DispId(200)]
object Application { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xc9)]
object Parent { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xca)]
object Container { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xcb)]
object Document { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xcc)]
bool TopLevelContainer { get; }
[DispId(0xcd)]
string Type { get; }
[DispId(0xce)]
int Left { get; set; }
[DispId(0xcf)]
int Top { get; set; }
[DispId(0xd0)]
int Width { get; set; }
[DispId(0xd1)]
int Height { get; set; }
[DispId(210)]
string LocationName { get; }
[DispId(0xd3)]
string LocationURL { get; }
[DispId(0xd4)]
bool Busy { get; }
[DispId(300)]
void Quit();
[DispId(0x12d)]
void ClientToWindow(out int pcx, out int pcy);
[DispId(0x12e)]
void PutProperty([In] string property, [In] object vtValue);
[DispId(0x12f)]
object GetProperty([In] string property);
[DispId(0)]
string Name { get; }
[DispId(-515)]
int HWND { get; }
[DispId(400)]
string FullName { get; }
[DispId(0x191)]
string Path { get; }
[DispId(0x192)]
bool Visible { get; set; }
[DispId(0x193)]
bool StatusBar { get; set; }
[DispId(0x194)]
string StatusText { get; set; }
[DispId(0x195)]
int ToolBar { get; set; }
[DispId(0x196)]
bool MenuBar { get; set; }
[DispId(0x197)]
bool FullScreen { get; set; }
[DispId(500)]
void Navigate2([In] ref object URL, [In] ref object flags, [In] ref object targetFrameName, [In] ref object postData, [In] ref object headers);
[DispId(0x1f5)]
NativeMethods.OLECMDF QueryStatusWB([In] NativeMethods.OLECMDID cmdID);
[DispId(0x1f6)]
void ExecWB([In] NativeMethods.OLECMDID cmdID, [In] NativeMethods.OLECMDEXECOPT cmdexecopt, ref object pvaIn, IntPtr pvaOut);
[DispId(0x1f7)]
void ShowBrowserBar([In] ref object pvaClsid, [In] ref object pvarShow, [In] ref object pvarSize);
[DispId(-525)]
WebBrowserReadyState ReadyState { get; }
[DispId(550)]
bool Offline { get; set; }
[DispId(0x227)]
bool Silent { get; set; }
[DispId(0x228)]
bool RegisterAsBrowser { get; set; }
[DispId(0x229)]
bool RegisterAsDropTarget { get; set; }
[DispId(0x22a)]
bool TheaterMode { get; set; }
[DispId(0x22b)]
bool AddressBar { get; set; }
[DispId(0x22c)]
bool Resizable { get; set; }
}}
and in your class:
private UnsafeNativeMethods.IWebBrowser2 axIWebBrowser2;protected override void AttachInterfaces(object nativeActiveXObject)
{
this.axIWebBrowser2 = (UnsafeNativeMethods.IWebBrowser2)nativeActiveXObject;
base.AttachInterfaces(nativeActiveXObject);
}protected override void DetachInterfaces()
{
this.axIWebBrowser2 = null;
base.DetachInterfaces();
}
-
Thursday, November 10, 2005 11:37 AMHi jlandheer,
Could you please post the full ExtendedWebBrowser (with the worknig ppDisp / Application part) class or send it to me by email ( gjunge AT gmail DOT com), since I cannot get it to work. This would help me enormously.
Thank you in advance,
Gidon -
Sunday, November 13, 2005 5:48 PMI'll send it over

I'm using it allready in one of my programs, there was one thing I needed to change on the interface declaration to get things going.
Here is the modified part:
public interface DWebBrowserEvents2
{
[System.Runtime.InteropServices.DispId(250)]
void BeforeNavigate2(
[System.Runtime.InteropServices.In,
System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.IDispatch)] object pDisp,
[System.Runtime.InteropServices.In] ref object URL,
[System.Runtime.InteropServices.In] ref object flags,
[System.Runtime.InteropServices.In] ref object targetFrameName, [System.Runtime.InteropServices.In] ref object postData,
[System.Runtime.InteropServices.In] ref object headers,
[System.Runtime.InteropServices.In,
System.Runtime.InteropServices.Out] ref bool cancel);
[System.Runtime.InteropServices.DispId(273)]
void NewWindow3(
[System.Runtime.InteropServices.In, System.Runtime.InteropServices.Out] ref object pDisp,
[System.Runtime.InteropServices.In, System.Runtime.InteropServices.Out] ref bool cancel,
[System.Runtime.InteropServices.In] ref object flags,
[System.Runtime.InteropServices.In] ref object URLContext,
[System.Runtime.InteropServices.In] ref object URL);
}
-
Saturday, November 26, 2005 5:27 AM
Can someone please send me the entire class/module/whatever
Which includes the full ppDisp implementation?
Also is there a reason you chose to omit the NewWindow2 event?
I need to use that in lieu of NewWindow3.
Any chance anyone has that?I'd prefer to use this over the AxWebBrowser (if I can)...
jshapcott AT MSN dot com -
Saturday, November 26, 2005 8:34 AMNever mind... I got it sorted out.
-
Saturday, November 26, 2005 6:08 PM
Nice that you figured this out. I've posted the complete source code on my weblog, you can download the file here: http://weblogs.servehttp.com/jeroen/files/extendedwebbrowser.zip
-
Monday, January 30, 2006 11:05 PM
OUTSTANDING! I'm not so good with translating C# (especially interop stuff) to VB, so this is great to have you spelling it out.
The plumbing was the hard part... now I have the entire interface built, just need to wire up some code.
So... dumb question: why hasn't anyone just wired up ALL of these events into one control? Why wouldn't MS have passed these events in the first place? So many of us spend our time wiring this stuff up...
Oh well, I feel like the doors are opening!
THANK YOU!!!
JR
-
Thursday, February 09, 2006 9:36 PM
Do you have an example in VB to declare this interface. I am interested in accessing the Application property.
Thanks
-
Tuesday, February 21, 2006 4:04 PM
In VS 2003, I was able to use pDisp to maintain session in a new window. I assume that there is some way of doing this with the module above, but I haven't been able to figure it out. (I'm working with Visual Basic .Net 2005)
Thanks for the code, and for any assistance.
-
Tuesday, February 21, 2006 6:24 PM
Hello CEisen.
Yes, there is. The way to do this is to override AttachInterfaces() and store the parameters in one of your own local class variables. (And use DetachInterfaces() to clear the memory used)
An example:
private UnsafeNativeMethods.IWebBrowser2 axIWebBrowser2;
/// <summary>
/// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code.
/// Called by the control when the underlying ActiveX control is created.
/// </summary>
/// <param name="nativeActiveXObject"></param>
[PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
protected override void AttachInterfaces(object nativeActiveXObject)
{
this.axIWebBrowser2 = (UnsafeNativeMethods.IWebBrowser2)nativeActiveXObject;
base.AttachInterfaces(nativeActiveXObject);
}/// <summary>
/// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code.
/// Called by the control when the underlying ActiveX control is discarded.
/// </summary>
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void DetachInterfaces()
{
this.axIWebBrowser2 = null;
base.DetachInterfaces();
}/// <summary>
/// Returns the automation object for the web browser
/// </summary>
public object Application
{
get { return axIWebBrowser2.Application; }
}The IWebBrowser2 interface:
[ComImport, SuppressUnmanagedCodeSecurity, TypeLibType(TypeLibTypeFlags.FOleAutomation | (TypeLibTypeFlags.FDual | TypeLibTypeFlags.FHidden)), Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")]
public interface IWebBrowser2
{
[DispId(100)]
void GoBack();
[DispId(0x65)]
void GoForward();
[DispId(0x66)]
void GoHome();
[DispId(0x67)]
void GoSearch();
[DispId(0x68)]
void Navigate([In] string Url, [In] ref object flags, [In] ref object targetFrameName, [In] ref object postData, [In] ref object headers);
[DispId(-550)]
void Refresh();
[DispId(0x69)]
void Refresh2([In] ref object level);
[DispId(0x6a)]
void Stop();
[DispId(200)]
object Application { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xc9)]
object Parent { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xca)]
object Container { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xcb)]
object Document { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
[DispId(0xcc)]
bool TopLevelContainer { get; }
[DispId(0xcd)]
string Type { get; }
[DispId(0xce)]
int Left { get; set; }
[DispId(0xcf)]
int Top { get; set; }
[DispId(0xd0)]
int Width { get; set; }
[DispId(0xd1)]
int Height { get; set; }
[DispId(210)]
string LocationName { get; }
[DispId(0xd3)]
string LocationURL { get; }
[DispId(0xd4)]
bool Busy { get; }
[DispId(300)]
void Quit();
[DispId(0x12d)]
void ClientToWindow(out int pcx, out int pcy);
[DispId(0x12e)]
void PutProperty([In] string property, [In] object vtValue);
[DispId(0x12f)]
object GetProperty([In] string property);
[DispId(0)]
string Name { get; }
[DispId(-515)]
int HWND { get; }
[DispId(400)]
string FullName { get; }
[DispId(0x191)]
string Path { get; }
[DispId(0x192)]
bool Visible { get; set; }
[DispId(0x193)]
bool StatusBar { get; set; }
[DispId(0x194)]
string StatusText { get; set; }
[DispId(0x195)]
int ToolBar { get; set; }
[DispId(0x196)]
bool MenuBar { get; set; }
[DispId(0x197)]
bool FullScreen { get; set; }
[DispId(500)]
void Navigate2([In] ref object URL, [In] ref object flags, [In] ref object targetFrameName, [In] ref object postData, [In] ref object headers);
[DispId(0x1f5)]
NativeMethods.OLECMDF QueryStatusWB([In] NativeMethods.OLECMDID cmdID);
[DispId(0x1f6)]
void ExecWB([In] NativeMethods.OLECMDID cmdID, [In] NativeMethods.OLECMDEXECOPT cmdexecopt, ref object pvaIn, IntPtr pvaOut);
[DispId(0x1f7)]
void ShowBrowserBar([In] ref object pvaClsid, [In] ref object pvarShow, [In] ref object pvarSize);
[DispId(-525)]
WebBrowserReadyState ReadyState { get; }
[DispId(550)]
bool Offline { get; set; }
[DispId(0x227)]
bool Silent { get; set; }
[DispId(0x228)]
bool RegisterAsBrowser { get; set; }
[DispId(0x229)]
bool RegisterAsDropTarget { get; set; }
[DispId(0x22a)]
bool TheaterMode { get; set; }
[DispId(0x22b)]
bool AddressBar { get; set; }
[DispId(0x22c)]
bool Resizable { get; set; }
}As you can see, the documentation of Microsoft isn't very clear on this... But it is still possible.
Best regards,
Jeroen Landheer. -
Tuesday, February 21, 2006 8:40 PM
Hello,
Thanks for your help. I believe I have that all translated into Visual Basic and added into my project in the correct places. However, I am unsure as to what I should have in the NewWindow(Exteneded?) event handler so that the session is carried over, and so that a new instance if IE is not opened.
Thanks again.
-
Wednesday, February 22, 2006 1:06 AM
Hi CEisen
What you have to do in the event handler from the NewWindow2/3 event, is the following:
- Create a new instance of the extended web browser, or any (user)control that consumes it.
- Pass to the object of the event, (called "pDisp" i believe) the "Application" property of the new web browser instance.
In your original post, you also mentioned if you should call AttachInterfaces() and DetachInterfaces(). The answer to this is "No". These methods are being called by the underlying WebBrowser control, which this piece of code is inherited from.
If you have any trouble, please let me know. I can provide you with a code sample if needed. (Maybe I'll put a nice article on the code project
)Best regards,
Jeroen Landheer. -
Thursday, February 23, 2006 7:06 PM
Hi,
Thanks for the help, but I seem to be having some problems getting this to work. I manage to pass "{System.__ComObject}" from Application:
Dim newbrowser As New frmWebBrowser
pDisp = newbrowser.Browser.Application
newbrowser.Visible = True
"Browser" is a readonly Property referencing the instance of the ExtendedWebBrowser class object in my frmWebBrowser form.
I'm using GMail as my example site. When I start the browser I load GMail and login, then go to view one of my messages. Then, when I click the "Open in New Window" button I get a new instance of Internet Exporer with the GMail login page, and a new instance of my webbrowser form, but the browser is blank and hasn't loaded anything.
Thanks for all your help. Code samples would be great; please send to CEisensmith AT GMail DOT com.
-
Monday, March 06, 2006 3:12 PM
I am not totally sure how this works.
Is there anyway this extension can be extended further to include RegisterAsBrowser? I am trying to create a tabbed browser -- I really need it for what I am doing. But if I put a webbrowser on subsequent tabs, only the one on the first tab will work. (I am doing the tabbing right and accessing each tab and browser instance right).
By working I mean only the first webbrowser will bring up a context menu with a right click, only the first will respond to a print, print preview, etc., even though I change the webbrowser reference (I add each to an arraylist).
As far as I have been able to figure out, it's because the subsequent webbrowsers need RegisterAsBrowser called when the user will change to that tab.
PLEASE HELP!
This is driving me nuts. I am seriously debating returning to 2003, even though I'd have to rewrite everything. At least tabbed browsing worked in 2003.
Doe
-
Monday, March 06, 2006 7:11 PM
The RegisterAsBrowser property is part of the IWebBrowser2 interface. This property can be accessed the same way as the Application property of the web browser.
Example:
private UnsafeNativeMethods.IWebBrowser2 axIWebBrowser2; /// <SUMMARY> /// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code. /// Called by the control when the underlying ActiveX control is created. /// </SUMMARY> /// <PARAM name="nativeActiveXObject"> [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")] protected override void AttachInterfaces(object nativeActiveXObject) { this.axIWebBrowser2 = (UnsafeNativeMethods.IWebBrowser2)nativeActiveXObject; base.AttachInterfaces(nativeActiveXObject); } /// <SUMMARY> /// Sets or retrieves a value that indicates whether the object is registered as a top-level browser for target name resolution /// </SUMMARY> public bool RegisterAsBrowser { get { return axIWebBrowser2.RegisterAsBrowser; } set { axIWebBrowser2.RegisterAsBrowser = value; } } /// <SUMMARY> /// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code. /// Called by the control when the underlying ActiveX control is discarded. /// </SUMMARY> [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")] protected override void DetachInterfaces() { this.axIWebBrowser2 = null; base.DetachInterfaces(); } /// <SUMMARY> /// Returns the automation object for the web browser /// </SUMMARY> public object Application { get { return axIWebBrowser2.Application; } }Hope this helps!
Best regards,
Jeroen Landheer. -
Monday, March 06, 2006 7:29 PM[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void DetachInterfaces()
{
this.axIWebBrowser2 = null;
base.DetachInterfaces();
}
/// <SUMMARY>
/// Returns the automation object for the web browser
/// </SUMMARY>
public object Application
{
get { return axIWebBrowser2.Application; }
}
Hope this helps!
Best regards,
Jeroen Landheer.========
Yes it does. :-)
I am using VB.Net rather than c, but I can read c well enough and will figure it out.
Thanks a lot!!!
Doe
-
Tuesday, March 07, 2006 10:04 PM
Alright, I think I have sessioning working (Thanks jlandheer).
I'm just having one additional difficulty. Whenever I'm using the WebBrowser and I click a button or link which is tied to a "Window.close()" command, the WebBrowser control hangs. The form the control is on can still be manipulated (and if it is moved under another form, will "Streak" with colored lines from the other window).
I've tried handling this as a Disposed event and as a Visibility changed event and neither seem to work. I've also tried to implement the WindowClosing event for the axIWebBrowser, like the code above has for NewWindow3 and OnNavigate2, but the event never seems to get raised.
Any assistance would be appreciated. Thanks.
-
Wednesday, March 08, 2006 8:42 PM
You can use the WebBrowser.Document.Window.Unload event. This event equals the DHTML onunload event, but be carefull, this event is raised in the following situations:
- Close the current browser window.
- Navigate to another location by entering a new address or selecting a Favorite.
- Click the Back, Forward, Refresh, or Home button.
- Click on an anchor that refers the browser to another Web page.
- Invoke the anchor click method.
- Invoke the document write method.
- Invoke the document open method.
- Invoke the document close method.
- Invoke the window close method.
- Invoke the window open method, providing the possible value _self for the window name.
- Invoke the window navigate or NavigateAndFind method.
- Invoke the location replace method.
- Invoke the location reload method.
- Specify a new value for the location href property.
- Submit a form to the address specified in the ACTION attribute via the INPUT type=submit control, or invoke the submit method.
So I check if the Webbrowser.Document propererty is null in order to see whether it is an Window.Close event.
-
Friday, March 10, 2006 2:21 AM
Okay, I give up. I've tried.
I am unable to translate the c in public interface IWebBrowser2 into VB.
Is there some way that the VB code that WilfridB shared could be extended to include RegisterAsBrowser? Without RegisterAsBrowser, tabbed browsing seems impossible to do in VB.net 2005. Each browser on each tab really needs to be registered as it is called.
Help from any VBers appreciated!!!
Guess being able to read c, doesn't necessarily mean being able to translate it.
Doe :-(
-
Friday, March 10, 2006 11:36 AM
Hi Doe
Here's the translation of the IWebBrowser2 interface to VB.Net...
<ComImport, TypeLibType((TypeLibTypeFlags.FOleAutomation Or (TypeLibTypeFlags.FDual Or TypeLibTypeFlags.FHidden))), Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E"), SuppressUnmanagedCodeSecurity> _ Public Interface IWebBrowser2 ' Methods <DispId(301)> _ Sub ClientToWindow(<Out> ByRef pcx As Integer, <Out> ByRef pcy As Integer) <DispId(502)> _ Sub ExecWB(<In> ByVal cmdID As OLECMDID, <In> ByVal cmdexecopt As OLECMDEXECOPT, ByRef pvaIn As Object, ByVal pvaOut As IntPtr) <DispId(303)> _ Function GetProperty(<In> ByVal [property] As String) As Object <DispId(100)> _ Sub GoBack() <DispId(101)> _ Sub GoForward() <DispId(102)> _ Sub GoHome() <DispId(103)> _ Sub GoSearch() <DispId(104)> _ Sub Navigate(<In> ByVal Url As String, <In> ByRef flags As Object, <In> ByRef targetFrameName As Object, <In> ByRef postData As Object, <In> ByRef headers As Object) <DispId(500)> _ Sub Navigate2(<In> ByRef URL As Object, <In> ByRef flags As Object, <In> ByRef targetFrameName As Object, <In> ByRef postData As Object, <In> ByRef headers As Object) <DispId(302)> _ Sub PutProperty(<In> ByVal [property] As String, <In> ByVal vtValue As Object) <DispId(501)> _ Function QueryStatusWB(<In> ByVal cmdID As OLECMDID) As OLECMDF <DispId(300)> _ Sub Quit() <DispId(-550)> _ Sub Refresh() <DispId(105)> _ Sub Refresh2(<In> ByRef level As Object) <DispId(503)> _ Sub ShowBrowserBar(<In> ByRef pvaClsid As Object, <In> ByRef pvarShow As Object, <In> ByRef pvarSize As Object) <DispId(106)> _ Sub [Stop]() ' Properties <DispId(555)> _ Property AddressBar As Boolean <DispId(200)> _ ReadOnly Property Application As <MarshalAs(UnmanagedType.IDispatch)> Object <DispId(212)> _ ReadOnly Property Busy As Boolean <DispId(202)> _ ReadOnly Property Container As <MarshalAs(UnmanagedType.IDispatch)> Object <DispId(203)> _ ReadOnly Property Document As <MarshalAs(UnmanagedType.IDispatch)> Object <DispId(400)> _ ReadOnly Property FullName As String <DispId(407)> _ Property FullScreen As Boolean <DispId(209)> _ Property Height As Integer <DispId(-515)> _ ReadOnly Property HWND As Integer <DispId(206)> _ Property Left As Integer <DispId(210)> _ ReadOnly Property LocationName As String <DispId(211)> _ ReadOnly Property LocationURL As String <DispId(406)> _ Property MenuBar As Boolean <DispId(0)> _ ReadOnly Property Name As String <DispId(550)> _ Property Offline As Boolean <DispId(201)> _ ReadOnly Property Parent As <MarshalAs(UnmanagedType.IDispatch)> Object <DispId(401)> _ ReadOnly Property Path As String <DispId(-525)> _ ReadOnly Property ReadyState As WebBrowserReadyState <DispId(552)> _ Property RegisterAsBrowser As Boolean <DispId(553)> _ Property RegisterAsDropTarget As Boolean <DispId(556)> _ Property Resizable As Boolean <DispId(551)> _ Property Silent As Boolean <DispId(403)> _ Property StatusBar As Boolean <DispId(404)> _ Property StatusText As String <DispId(554)> _ Property TheaterMode As Boolean <DispId(405)> _ Property ToolBar As Integer <DispId(207)> _ Property Top As Integer <DispId(204)> _ ReadOnly Property TopLevelContainer As Boolean <DispId(205)> _ ReadOnly Property Type As String <DispId(402)> _ Property Visible As Boolean <DispId(208)> _ Property Width As Integer End InterfaceHope this helps!
Best regards,
Jeroen Landheer -
Friday, March 10, 2006 12:21 PM
Hi GidonJ.
Yes, this might work for the most common situations, but it still isn't applicable for every situation. A better method in this case might be listening to the WM_PARENTNOTIFY/WM_DESTROY messages by overriding void WndProc(ref Message)
It's not the most simple solution, but I assure you: It works flawlessly.
An example:
- Create a event called "Quit" or any other name you would like
- Launch the event from the following code:
[PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")] protected override void WndProc(ref Message m) { if (m.Msg == (int)WindowsMessages.WM_PARENTNOTIFY) { //int lp = m.LParam.ToInt32(); int wp = m.WParam.ToInt32(); int X = wp & 0xFFFF; //int Y = (wp >> 16) & 0xFFFF; if (X == (int)WindowsMessages.WM_DESTROY) this.OnQuit(); } base.WndProc(ref m); }The WindowMessages enumeration looks like this:
enum WindowsMessages { WM_ACTIVATE = 0x6, WM_ACTIVATEAPP = 0x1C, WM_AFXFIRST = 0x360, WM_AFXLAST = 0x37F, WM_APP = 0x8000, WM_ASKCBFORMATNAME = 0x30C, WM_CANCELJOURNAL = 0x4B, WM_CANCELMODE = 0x1F, WM_CAPTURECHANGED = 0x215, WM_CHANGECBCHAIN = 0x30D, WM_CHAR = 0x102, WM_CHARTOITEM = 0x2F, WM_CHILDACTIVATE = 0x22, WM_CLEAR = 0x303, WM_CLOSE = 0x10, WM_COMMAND = 0x111, WM_COMPACTING = 0x41, WM_COMPAREITEM = 0x39, WM_CONTEXTMENU = 0x7B, WM_COPY = 0x301, WM_COPYDATA = 0x4A, WM_CREATE = 0x1, WM_CTLCOLORBTN = 0x135, WM_CTLCOLORDLG = 0x136, WM_CTLCOLOREDIT = 0x133, WM_CTLCOLORLISTBOX = 0x134, WM_CTLCOLORMSGBOX = 0x132, WM_CTLCOLORSCROLLBAR = 0x137, WM_CTLCOLORSTATIC = 0x138, WM_CUT = 0x300, WM_DEADCHAR = 0x103, WM_DELETEITEM = 0x2D, WM_DESTROY = 0x2, WM_DESTROYCLIPBOARD = 0x307, WM_DEVICECHANGE = 0x219, WM_DEVMODECHANGE = 0x1B, WM_DISPLAYCHANGE = 0x7E, WM_DRAWCLIPBOARD = 0x308, WM_DRAWITEM = 0x2B, WM_DROPFILES = 0x233, WM_ENABLE = 0xA, WM_ENDSESSION = 0x16, WM_ENTERIDLE = 0x121, WM_ENTERMENULOOP = 0x211, WM_ENTERSIZEMOVE = 0x231, WM_ERASEBKGND = 0x14, WM_EXITMENULOOP = 0x212, WM_EXITSIZEMOVE = 0x232, WM_FONTCHANGE = 0x1D, WM_GETDLGCODE = 0x87, WM_GETFONT = 0x31, WM_GETHOTKEY = 0x33, WM_GETICON = 0x7F, WM_GETMINMAXINFO = 0x24, WM_GETOBJECT = 0x3D, WM_GETTEXT = 0xD, WM_GETTEXTLENGTH = 0xE, WM_HANDHELDFIRST = 0x358, WM_HANDHELDLAST = 0x35F, WM_HELP = 0x53, WM_HOTKEY = 0x312, WM_HSCROLL = 0x114, WM_HSCROLLCLIPBOARD = 0x30E, WM_ICONERASEBKGND = 0x27, WM_IME_CHAR = 0x286, WM_IME_COMPOSITION = 0x10F, WM_IME_COMPOSITIONFULL = 0x284, WM_IME_CONTROL = 0x283, WM_IME_ENDCOMPOSITION = 0x10E, WM_IME_KEYDOWN = 0x290, WM_IME_KEYLAST = 0x10F, WM_IME_KEYUP = 0x291, WM_IME_NOTIFY = 0x282, WM_IME_REQUEST = 0x288, WM_IME_SELECT = 0x285, WM_IME_SETCONTEXT = 0x281, WM_IME_STARTCOMPOSITION = 0x10D, WM_INITDIALOG = 0x110, WM_INITMENU = 0x116, WM_INITMENUPOPUP = 0x117, WM_INPUTLANGCHANGE = 0x51, WM_INPUTLANGCHANGEREQUEST = 0x50, WM_KEYDOWN = 0x100, WM_KEYFIRST = 0x100, WM_KEYLAST = 0x108, WM_KEYUP = 0x101, WM_KILLFOCUS = 0x8, WM_LBUTTONDBLCLK = 0x203, WM_LBUTTONDOWN = 0x201, WM_LBUTTONUP = 0x202, WM_MBUTTONDBLCLK = 0x209, WM_MBUTTONDOWN = 0x207, WM_MBUTTONUP = 0x208, WM_MDIACTIVATE = 0x222, WM_MDICASCADE = 0x227, WM_MDICREATE = 0x220, WM_MDIDESTROY = 0x221, WM_MDIGETACTIVE = 0x229, WM_MDIICONARRANGE = 0x228, WM_MDIMAXIMIZE = 0x225, WM_MDINEXT = 0x224, WM_MDIREFRESHMENU = 0x234, WM_MDIRESTORE = 0x223, WM_MDISETMENU = 0x230, WM_MDITILE = 0x226, WM_MEASUREITEM = 0x2C, WM_MENUCHAR = 0x120, WM_MENUCOMMAND = 0x126, WM_MENUDRAG = 0x123, WM_MENUGETOBJECT = 0x124, WM_MENURBUTTONUP = 0x122, WM_MENUSELECT = 0x11F, WM_MOUSEACTIVATE = 0x21, WM_MOUSEFIRST = 0x200, WM_MOUSEHOVER = 0x2A1, WM_MOUSELAST = 0x20A, WM_MOUSELEAVE = 0x2A3, WM_MOUSEMOVE = 0x200, WM_MOUSEWHEEL = 0x20A, WM_MOVE = 0x3, WM_MOVING = 0x216, WM_NCACTIVATE = 0x86, WM_NCCALCSIZE = 0x83, WM_NCCREATE = 0x81, WM_NCDESTROY = 0x82, WM_NCHITTEST = 0x84, WM_NCLBUTTONDBLCLK = 0xA3, WM_NCLBUTTONDOWN = 0xA1, WM_NCLBUTTONUP = 0xA2, WM_NCMBUTTONDBLCLK = 0xA9, WM_NCMBUTTONDOWN = 0xA7, WM_NCMBUTTONUP = 0xA8, WM_NCMOUSEHOVER = 0x2A0, WM_NCMOUSELEAVE = 0x2A2, WM_NCMOUSEMOVE = 0xA0, WM_NCPAINT = 0x85, WM_NCRBUTTONDBLCLK = 0xA6, WM_NCRBUTTONDOWN = 0xA4, WM_NCRBUTTONUP = 0xA5, WM_NEXTDLGCTL = 0x28, WM_NEXTMENU = 0x213, WM_NOTIFY = 0x4E, WM_NOTIFYFORMAT = 0x55, WM_NULL = 0x0, WM_PAINT = 0xF, WM_PAINTCLIPBOARD = 0x309, WM_PAINTICON = 0x26, WM_PALETTECHANGED = 0x311, WM_PALETTEISCHANGING = 0x310, WM_PARENTNOTIFY = 0x210, WM_PASTE = 0x302, WM_PENWINFIRST = 0x380, WM_PENWINLAST = 0x38F, WM_POWER = 0x48, WM_PRINT = 0x317, WM_PRINTCLIENT = 0x318, WM_QUERYDRAGICON = 0x37, WM_QUERYENDSESSION = 0x11, WM_QUERYNEWPALETTE = 0x30F, WM_QUERYOPEN = 0x13, WM_QUEUESYNC = 0x23, WM_QUIT = 0x12, WM_RBUTTONDBLCLK = 0x206, WM_RBUTTONDOWN = 0x204, WM_RBUTTONUP = 0x205, WM_RENDERALLFORMATS = 0x306, WM_RENDERFORMAT = 0x305, WM_SETCURSOR = 0x20, WM_SETFOCUS = 0x7, WM_SETFONT = 0x30, WM_SETHOTKEY = 0x32, WM_SETICON = 0x80, WM_SETREDRAW = 0xB, WM_SETTEXT = 0xC, WM_SETTINGCHANGE = 0x1A, WM_SHOWWINDOW = 0x18, WM_SIZE = 0x5, WM_SIZECLIPBOARD = 0x30B, WM_SIZING = 0x214, WM_SPOOLERSTATUS = 0x2A, WM_STYLECHANGED = 0x7D, WM_STYLECHANGING = 0x7C, WM_SYNCPAINT = 0x88, WM_SYSCHAR = 0x106, WM_SYSCOLORCHANGE = 0x15, WM_SYSCOMMAND = 0x112, WM_SYSDEADCHAR = 0x107, WM_SYSKEYDOWN = 0x104, WM_SYSKEYUP = 0x105, WM_TCARD = 0x52, WM_TIMECHANGE = 0x1E, WM_TIMER = 0x113, WM_UNDO = 0x304, WM_UNINITMENUPOPUP = 0x125, WM_USER = 0x400, WM_USERCHANGED = 0x54, WM_VKEYTOITEM = 0x2E, WM_VSCROLL = 0x115, WM_VSCROLLCLIPBOARD = 0x30A, WM_WINDOWPOSCHANGED = 0x47, WM_WINDOWPOSCHANGING = 0x46, WM_WININICHANGE = 0x1A }I got this knowledge from someone else on one of the other threads of this forum, who's name I've forgotten
, but this information is based on a Microsoft Knowledge Base article.Best regards,
Jeroen Landheer. -
Friday, March 10, 2006 2:16 PM
Egad, yes!!!
I was thinking you were just a c guy, so didn't want to ask you.
Thanks ever so much.
Whew.
Doe
-
Tuesday, March 21, 2006 2:49 PM
Thanks to both GidonJ and jlandheer for their help. I've tried both the solutions, but I haven't been able to get either to work completely.
I am closer with jlandheer's; I'm recieving the system messages, and the function responds to me clicking in the browser window; however, I'm not understanding the last bit that is supposed to trigger the event. The WParam always seems to be "0;" even when I've clicked something I know to be a Window.Close() call.
Please advise. Thanks.
<PermissionSet(SecurityAction.Demand, Name:="FullTrust")> _
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WindowsMessages.WM_PARENTNOTIFY Then
'int lp = m.LParam.ToInt32();
Dim wp As Integer = m.WParam.ToInt32
Dim X As Integer = wp + &HFFFF
'int Y = (wp >> 16) & 0xFFFF;
If X = WindowsMessages.WM_DESTROY Then
RaiseEvent Quit()
End If
End If
MyBase.WndProc(m)
End Sub
-
Monday, March 27, 2006 9:01 PM
In case anyone else is interested, the code for the IWebBrowser2 interface can be found at pinvoke.net in both C and VB. They also seem to have code for all the interop interfaces.
http://www.pinvoke.net/default.aspx/Interfaces.IWebBrowser2
Doe :-)
-
Wednesday, March 29, 2006 1:50 PM
For everyone that's interested. I've posted an article on the code project as promised.
The URL is: http://www.codeproject.com/csharp/ExtendedWebBrowser.asp
Best regards,
Jeroen Landheer. -
Thursday, April 20, 2006 2:04 AM
I'm not getting anything (Nothing) from e.Headers.
What I've done:
1) copied the module definition into my project
2) created the following class:
Class IEToolsPublic
Private wb As New ExtendedWebBrowser Private webBrowserHeader As String 'constructor Public Sub New()
MyBase.new() AddHandler wb.NavigatingExtended, AddressOf wb_NavigatingExtended End Sub 'destructor Protected Overrides Sub Finalize()
RemoveHandler wb.NavigatingExtended, AddressOf wb_NavigatingExtended MyBase.Finalize() End Sub 'Properties Public ReadOnly Property GetIEheader() 'make the header available
Get
Return webBrowserHeader End Get End Property 'make the webbrowser navigate. Then capture the Navigate event Public Sub LoadIEheaders(ByVal strUnusedURL As String)
False) End Sub 'capture the Navigating event Private Sub wb_NavigatingExtended(ByVal sender As Object, ByVal e As ExtendedWebBrowserModule.WebBrowserNavigatingExtendedEventArgs) 'grab the headerwb.Navigate(strUnusedURL,
True End SubwebBrowserHeader = e.Headers
e.Cancel =
End
Class3) Then I try to get the Header like this when my project starts up:
'if headers did not load from settings file, then grab default IE headers If strHeaders = "" Then
Dim classBrowser As New IEToolsclassBrowser.LoadIEheaders(
"www.microsoft.com")strHeaders = classBrowser.GetIEheader
End If4) strHeaders is always Nothing. :-(
-
Sunday, June 18, 2006 3:08 AM
Hi,
I've just started to use VB.NET in VS 2005 and I had a specific requirement to capture the URL from a NewWindow event as part of a browser application and with this URL, effectively open a popup window. Having hit the limits of what the standard WebBrowser control will do in VS 2005, i turned to the net and found this thread. I copied WilfridB's code into my application and it worked first time. Many, many thanks to you all, for without people like yourselves, people like me would never be able to achieve what we aim for. You are appreciated!

-
Thursday, July 20, 2006 9:39 PM
This is such a very good thread

BTW. Can anybody show me how to change the browser USER-AGENT from the original Mozilla MSIE6 to my own custom one? (ie: USER-AGENT: MyApp 1.1.1)
-
Thursday, September 07, 2006 4:08 PM
I'm using the vb.net 2005 code example that Wilfrid posted. I'm redirecting a popup window to a new windows form instead of the default IE one. My question is, how do I get BeforeNavigate2 working in Wilfrid's code? I want to watch for the user clicking a button on a form so that I can close the popup window automatically. I can't seem to figure out how to implement BeforeNavigate2 so I can get the URL and if it contains javascript:window.close then close my windows form.
Any assistance would be greatly appreciated.
Kindest regards,
Josh
-
Friday, October 06, 2006 11:35 PM
Did you ever get an answer?
I have a Windows browser and I need to change the User-Agent too.
Thanks,
Filippo -
Saturday, February 17, 2007 11:16 AM
I believe this is one of the best threads to have ever have occurred on this board. I've read it so many times because I've been working on a large project ( www.freewebs.com/reneecc ) for about the last year and it's web browser based.
A couple of weeks ago, i noticed that the webbrowser portion was not navigating flash well at all and I came to understand the full significance of the navigating3 events. I included Jeroen Landheer's code from the code project code into my solution and it certainly did fix the flash problems.
However, since then, I've noticed a couple of small inexplicable behaviors.
On these fora if I enter 'test' into a textbox and depress <enter> my browser navigates right back to the MSDN page that it was on. If I depress the Search button, navigation is quite proper. I wrote to the codeproject auther and have received no response. What's worse if that Test<enter> works with a program with nothing but an extended events view. I find extented code difficult to debug because there's very little code there. Most of it is a series of event driven black boxes.
These little bugs are the last known bugs and I really would like to get them cleaned up. Any help would be very appreciated.
It should also be a major message to MS that this thread has 38,000 + reads. I have never seen any thread receive the attention this thread, which means there are notable product issues with this control.
-
Monday, February 19, 2007 12:46 PMI am afraid this is not helping me.
I am working in VB 6.0 so please tell me in the same language.
Thanks in advance. -
Thursday, February 22, 2007 12:27 AMThese fora are not for vb6.
-
Sunday, April 01, 2007 9:59 AM
Hello,
this code is really nice!
But after implementing it, I have problems with the standard events like "WebBrowser1.DocumentCompleted or WebBrowser1.CanGoBackChanged
How can I use New Events and the old Events together?
In VB05-Code please!
Thanks for your help
-
Saturday, August 11, 2007 2:53 AM
O.k just wanted to say a huge thanks to all the contributors to this thread. Its been a massively helpful post and I really do appreciate the time, trouble and effort you all have put into providing a solution to the requirements gap found between the VS webcontrol and what I would have thought to be it's fairly typical use.
The less I have to poke around Win32 and COM the better. Thanks a bunch.
-
Sunday, September 02, 2007 1:28 AM
I've never seen a thread with replies over such a long period of time!
Anyway, since this thread is what gave me the leg up to extend the standard WebBrowser component with the DWebBrowser2 interface to get the 'useful' events like NewWindow3 (plus code to allow the html script itself to close the popup window) and add in the IWebBrowser2 interface to get the RegisterAsTopLevelBrowser property, have a look here or here at the full definition of the extended webbrowser I ended up with based on the contributions to this thread.
Please let me know if anybody has any comments or if this was useful. Bear in mind it was my first foray into .NET so i'm sure it's untidy and will make professional developers cringe ;-) As no doubt will my web pages but I'm learning all about them as well!
Many thanks to all.
Martyn.
-
Tuesday, September 04, 2007 2:30 AM
Hello everyone.
It's been some time since I last posted anything here, but I've done some research in the mean time. Here's a solution to capture script errors in the browser control, without using the "ScriptErrorsSuppressed" property. The latter causes also other dialogboxes to disapear, including certificate logon, and so on. This solution is different from one I posted on the code project earlier and works more solid. I'm still working on a solution to let pages run in a predetermined security zone and I'll expect to resolve this within the next few months.
For anyone who's interested and is short on time, the script error solution can be achieved by extending the class WebBrowser+WebBrowserSite and implementing the IOleClientSide interface. It was a though one to tackle, but one who deserves to be mentioned.
In the extended webbrowser class, create a class "ExtendedWebbrowserSite" that extends WebBrowserSite
-
Override the "CreateWebBrowserSiteBase" method and return your own "ExtendedWebBrowserSite" class instance
-
Implement the IOleCommandTarget interface in your ExtendedWebbrowserSite class
When this is done, you can capture a lot of events and other things, which allows more control over the web browser.
Here's a piece of code that I use for the ExtendedWebBrowserSite class:
/// <summary>
/// Represenst an extended version of the <see cref="WebBrowser.WebBrowserSite"/> class
/// </summary>
/// <remarks>
/// This class implements <b>IOleCommandTarget</b> for handling script errors
/// </remarks>
protected class ExtendedWebBrowserSite : WebBrowserSite, NativeMethods.IOleCommandTarget
{
/// <summary>
/// Creates a new instance of the <see cref="ExtendedWebBrowserSite"/> class
/// </summary>
/// <param name="host">The <see cref="ExtendedWebBrowser"/> hosting the browser</param>
public ExtendedWebBrowserSite(ExtendedWebBrowser host)
: base(host)
{
_host = host;
}
private ExtendedWebBrowser _host;
private ExtendedWebBrowser Host
{
get
{
return _host;
}
}#region IOleCommandTarget Members
int NativeMethods.IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, int cCmds, NativeMethods.OLECMD prgCmds, IntPtr pCmdText)
{
return NativeMethods.S_FALSE;
}int NativeMethods.IOleCommandTarget.Exec(ref Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, object[] pvaIn, ref int pvaOut)
{
int hResult = NativeMethods.S_OK;
//if (pguidCmdGroup == null)
// return h Result;
// Check for invalid pointers (or get a NullReferenceException on a value type???)
if (pguidCmdGroup == NativeMethods.CGID_DocHostCommandHandler)
{
switch (nCmdID)
{
case (int)NativeMethods.OLECMDID.OLECMDID_SHOWSCRIPTERROR:
// Dit werkt
// mshtml.IHTMLDocument document
mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)pvaIn[0];
mshtml.IHTMLWindow2 window = doc.parentWindow;
mshtml.IHTMLEventObj2 wndevt = (mshtml.IHTMLEventObj2)window.@event;
// IntPtr wndPtr = Marshal.GetIDispatchForObject(wndevt);string errorMessage = (string)wndevt.getAttribute("errorMessage", 0);
int errorLine = (int)wndevt.getAttribute("errorLine", 0);
int errorCode = (int)wndevt.getAttribute("errorCode", 0);
int errorCharacter = (int)wndevt.getAttribute("errorCharacter", 0);
string errorUrl = (string)wndevt.getAttribute("errorUrl", 0);// Notify the host
_host.OnScriptError(new ScriptErrorEventArgs(new BrowserScriptError(new Uri(errorUrl), errorLine, errorCharacter, errorMessage)));// Hide the dialog
pvaOut = NativeMethods.VARIANT_TRUE;
break;
default:
hResult = NativeMethods.OLECMDERR_E_NOTSUPPORTED;
break;
}
}
return hResult;
}#endregion
}Next, the host implements this class by overriding the CreateWebBrowserSiteBase method:
/// <summary>
/// Overridden. Creates a new <see cref="ExtendedWebBrowserSite"/> instance with this instance as the host
/// </summary>
/// <returns>A new instance of the <see cref="ExtendedWebBrowserSite"/> class</returns>
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
return new ExtendedWebBrowserSite(this);
}And ofcourse, OnScriptError (with it's appropiate EventArgs item) looks like this:
private static readonly object EventScriptError = new object();
/// <summary>
/// Fired when a script error occured
/// </summary>
public event EventHandler<ScriptErrorEventArgs> ScriptError
{
add
{
Events.AddHandler(EventScriptError, value);
}
remove
{
Events.RemoveHandler(EventScriptError, value);
}
}/// <summary>
/// Raises the <see cref="ScriptError"/> event
/// </summary>
/// <param name="e">The <see cref="ScriptErrorEventArgs"/> event arguments</param>
/// <remarks>The script error is automatically recorded in the <see cref="ScriptErrorControl"/></remarks>
protected virtual void OnScriptError(ScriptErrorEventArgs e)
{
if (e == null)
throw new ArgumentNullException("e");
// ScriptErrorControl.Instance.BrowserScriptErrorCollection.Add(e.Error);
BrowserApplication.Instance.AddScriptError(e.Error);EventHandler<ScriptErrorEventArgs> handler = (EventHandler<ScriptErrorEventArgs>)Events[EventScriptError];
if (handler != null)
handler(this, e);
}The reason that this is using "Events.AddHandler" and "Events.RemoveHandler" is that the events will not fire when the control is disposed. (The EventHandlerList will be disposed, causing all it's events to stop working)
Finally the ScriptErrorEventArgs class is a simple standard EventArgs class with some extra parameters.
Before I forget, the interface IOleCommandTarget and related items:
public enum OLECMDF
{
// Fields
OLECMDF_DEFHIDEONCTXTMENU = 0x20,
OLECMDF_ENABLED = 2,
OLECMDF_INVISIBLE = 0x10,
OLECMDF_LATCHED = 4,
OLECMDF_NINCHED = 8,
OLECMDF_SUPPORTED = 1
}public enum OLECMDID
{
// Fields
OLECMDID_PAGESETUP = 8,
OLECMDID_PRINT = 6,
OLECMDID_PRINTPREVIEW = 7,
OLECMDID_PROPERTIES = 10,
OLECMDID_SAVEAS = 4,
OLECMDID_SHOWSCRIPTERROR = 40
}
public enum OLECMDEXECOPT
{
// Fields
OLECMDEXECOPT_DODEFAULT = 0,
OLECMDEXECOPT_DONTPROMPTUSER = 2,
OLECMDEXECOPT_PROMPTUSER = 1,
OLECMDEXECOPT_SHOWHELP = 3
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"), ComVisible(true)]
public interface IOleCommandTarget
{
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int QueryStatus(ref Guid pguidCmdGroup, int cCmds, [In, Out] NativeMethods.OLECMD prgCmds, [In, Out] IntPtr pCmdText);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int Exec(ref Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, [In, MarshalAs(UnmanagedType.LPArray)] object[] pvaIn, ref int pvaOut);
}[StructLayout(LayoutKind.Sequential)]
public class OLECMD
{
[MarshalAs(UnmanagedType.U4)]
public int cmdID;
[MarshalAs(UnmanagedType.U4)]
public int cmdf;
public OLECMD()
{
}
}Hope this helps and keep the suggestions coming!
Best regards,
Jeroen Landheer
-
-
Tuesday, September 04, 2007 2:44 AM
Hello ReneeC
Sorry if you haven't got a response from me, I try to answer all my mail but as you can imagine, I'm getting a LOT of mail... It seems that this control is populair, and the amount of feedback is simply too much for a single person to handle. So if I disappointed you, my apologies.
For the other part, I've also had some weird issues, especially with the directional keys and have changed the procedures in the mean time to combat this problem. Here's what I'm using at the moment, let me know if this works for you:
/// <summary>
/// Overridden. Handles window messages for the browser control
/// </summary>
/// <param name="m">The <see cref="Message"/> send to this procedure</param>
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
switch ((NativeMethods.WindowsMessages)m.Msg)
{
// These are for getting flash to work
case NativeMethods.WindowsMessages.WM_LBUTTONDOWN:
case NativeMethods.WindowsMessages.WM_RBUTTONDOWN:
case NativeMethods.WindowsMessages.WM_MBUTTONDOWN:
case NativeMethods.WindowsMessages.WM_MOUSEACTIVATE:
//case (int)WindowsMessages.WM_KEYDOWN:
//case (int)WindowsMessages.WM_KEYUP:
//case (int)WindowsMessages.WM_CHAR:
//case (int)WindowsMessages.WM_SYSKEYDOWN:
//case (int)WindowsMessages.WM_SYSKEYUP:
base.DefWndProc(ref m);
// Don't call base
break;
// When the browser is destroyed, close the window
case NativeMethods.WindowsMessages.WM_PARENTNOTIFY:
int wp = m.WParam.ToInt32();
int X = wp & 0xFFFF;
if (X == (int)NativeMethods.WindowsMessages.WM_DESTROY)
this.OnQuit(EventArgs.Empty);
// Do the base action
goto default;
default:
// Default action, call base
base.WndProc(ref m);
break;
}
}/// <summary>
/// Overridden. Determines if a certain key is an input key
/// </summary>
/// <remarks>
/// The cursor keys are input keys for the web browser.
/// </remarks>
/// <param name="keyData">The <see cref="Keys"/> pressed</param>
/// <returns>true when the key should be handled as an input key, otherwise false</returns>
protected override bool IsInputKey(Keys keyData)
{
if (
((keyData & Keys.Up) == Keys.Up) ||
((keyData & Keys.Down) == Keys.Down) ||
((keyData & Keys.Left) == Keys.Left) ||
((keyData & Keys.Right) == Keys.Right))
return true;
return base.IsInputKey(keyData);
}And about MS? I'm sure that they will read it. ;-) This thread is indeed very populair.
Best regards,
Jeroen Landheer
-
Tuesday, September 25, 2007 10:32 PMHi,
Can this control be useful at design time. I have a situation where I am building a server control and I want to access the HTTP POST message at design time when that control is dragged.
Thanks
Abhang -
Friday, November 16, 2007 3:02 PM
Is this code available in vb .net?
-
Monday, December 31, 2007 4:39 PM
-
Friday, February 29, 2008 3:27 PMI'm trying to integrate this into a VB.NET project in VS2005. Everything works just fine until a new window is spawned then I get the standard 0xc0000005 COM error when it tries to access the Application property.
It's generating the error on the "Application = iwb.Application" line.
Here is the relevant code snippet - I can post more if required:
Public Class ExtendedWebBrowser
Inherits WebBrowser
Private cookie As AxHost.ConnectionPointCookie
Private wevents As WebBrowserExtendedEvents
Private iwb As IWebBrowser2
Protected Overrides Sub AttachInterfaces(ByVal nativeActiveXObject As Object)
iwb = CType(nativeActiveXObject, IWebBrowser2)
MyBase.AttachInterfaces(nativeActiveXObject)
End Sub
Protected Overrides Sub DetachInterfaces()
iwb = Nothing
MyBase.DetachInterfaces()
End Sub
Public ReadOnly Property Application() As Object
Get
Application = iwb.Application
End Get
End Property -
Friday, February 29, 2008 4:22 PM
Hi,
I've not used the Application property in my project. When I open a new window, I use the Handle property and it seems to work. I used to use the line 'e.ppDisp = WebForm.wbPopup.ActiveXInstance' which also worked but I must have found a reason somewhere to change it.
Code SnippetPrivate Sub wbMain_NewWindowExtended(ByVal sender As Object, ByVal e As ExtendWebBrowserModule.WebBrowserNewWindowExtendedEventArgs)
'This event fires when the browser requests a new window is created
msg = "Web site is trying to open a popup window to:" & ControlChars.CrLf & e.Url & ControlChars.CrLf & ControlChars.CrLf & "Do you wish to allow this?"
Dim res As DialogResult = ShowMessageBox(msg, My.Resources.BrowserAppName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, 0)
If res = Windows.Forms.DialogResult.No Then
'User does not want to open the popup. Return e.Cancel to prevent IE opening popup.
e.Cancel = True
Else
'User wants to open popup - return handle of wbPopup
e.ppDisp = WebForm.Handle
'send URL to our WebForm browser control to display it.
WebForm.wbPopup.Navigate(e.Url)
'return cancel as True to prevent IE opening a new window as we have handled it.
e.Cancel = True
WebForm.Visible = True
WebForm.BringToFront()
End If
End SubI hope this helps.
-
Friday, February 29, 2008 4:35 PMMartyn,
This certinaly does help - how are you going about adding the ppDisp to your ExtendedEventArgs so that it interfaces with your IWebBrowser2 interface?
EDIT: Uh, nevermind ... haven't finished my coffee yet, sorry about that.
-
Tuesday, March 11, 2008 12:20 AM
Oh, don't thank me. It was WilfridB that posted the original code so let me in turn say many thanks to WifridB for starting this thread!
I wonder if anyone reading this thread has used this code with VS2008 yet? Or indeed whether it's even necessary anymore.
-
Thursday, June 18, 2009 1:44 PMHi,
I've implemented the extendedwebbrowser and it is working brilliantly, however I have discovered a problem when using frames, I don't know if anyone has found a solution to this yet?
I am navigating to a frameset
I am handling the extendednavigating event, cancelling the event and adding headers to the request
The frameset loads in the control but one of the frames loads in a new window for some reason.
If I use the normal web browser control this happens as well
If I use the axtive x one it doesn't happen
If I don't handle the navigating event it works perfectly.
Any ideas? -
Saturday, August 08, 2009 3:28 AMHere, Here!
Thread still relevant. -
Tuesday, August 18, 2009 9:35 PMGreat post!
I translated your example to c# and it works like a charm!
However i would like to know if anyone has an idea how to intercept a XMLHttpRequest POST with beforenavigate?
:)- Edited by andurshakur Wednesday, August 19, 2009 4:03 PM typo
-
Thursday, October 01, 2009 8:57 AMhow can a add more code to this in order to disable text selection and picture drag?
thanks -
Monday, March 29, 2010 10:15 PM
HI,
I have the same problem when I load the frameset it loads in the main window.
Any solution will really help me to get out of this problem.
Hari -
Monday, November 15, 2010 6:33 PM
Thanks lavenm50.
I am impressed by the length of the thread as well :) and still disappointed by the current .net webbrowser control provided by MS.
5 years later, nothing has changed...
wilfridB
-
Monday, November 15, 2010 6:36 PM100% agreed :)


