Using Web Browser Control in VB .net

G

gokul

Hi,
Iam a newbie to dotnet and I experience problems in using the Browser
control in VB .net. Though Iam able to use it with its basic features,
I need to customise it.

http://www.codeproject.com/books/0764549146_8.asp
The above link shows where what I want is achived in C#, but I need t
oa cjhive the same in VB .net.

Someone help and guidance would be much appreciated.

Regards
GOkul
 
C

Charles Law

Gokul

The web page you referenced comes back with an error for me. Can you check
it and re-post. Also, can you be more specific about the kind of problems
you are having?

Charles
 
G

Gokul RajaD

Hi Charles Law,
Iam a newbie to dotnet and I experience problems in using the Browser
control in VB .net.
Though Iam able to use it with its basic features,
I need to customise it.

http://www.codeproject.com/books/0764549146_8.asp

The above links works perfectly....fine for me...please try copying and
pasting the link in the browser.
check the HTML customisation part....
Listing 8-36:: The Complete Code for MainForm of MyCustomWebBrowser

This is the code which I need in VB.Net.
Regards
Gokul
 
C

Charles Law

Hi Gokul

I can see the code you are referring to. There is a lot there, and much of
it can be achieved with the WebBrowser control directly, without any special
effort.

You say you are able to use it with basic features, so I am not sure which
ones are causing you problems. Rather than trawl through the listing, can
you identify some of the specific problems you are having? For example, to
print you would use

AxWebBrowser1.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER)

Alternatively, are you trying to show a custom context menu with the
IDocHostUIHandler interface, or is it something else?

Regards

Charles
 
G

gokul

Dear Charles Law,
I need to remove the 3D border of the Webbrowser control, they say it
could be achieved using IDocHostUIHandler.

and also Iam trying to change the Context menu.
Apart from it Iam trying to capture the word/text on which the mouse
is pointing using API calls.....do u have any idea about it!!!!?

Thank You for the prompt replies.

Letz work on it to make a wonderful product and share the Concepts and
ideas.
Regards
Gokul
 
C

Charles Law

Hi Gokul

Ok, here goes. It works something like this.

First, include the following interface definition stuff somewhere convenient
(I have a separate module with these kind of interfaces in):

<code>
Public Enum DOCHOSTUIFLAG
DOCHOSTUIFLAG_DIALOG = &H1
DOCHOSTUIFLAG_DISABLE_HELP_MENU = &H2
DOCHOSTUIFLAG_NO3DBORDER = &H4
DOCHOSTUIFLAG_SCROLL_NO = &H8
DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE = &H10
DOCHOSTUIFLAG_OPENNEWWIN = &H20
DOCHOSTUIFLAG_DISABLE_OFFSCREEN = &H40
DOCHOSTUIFLAG_FLAT_SCROLLBAR = &H80
DOCHOSTUIFLAG_DIV_BLOCKDEFAULT = &H100
DOCHOSTUIFLAG_ACTIVATE_CLIENTHIT_ONLY = &H200
DOCHOSTUIFLAG_OVERRIDEBEHAVIORFACTORY = &H400
DOCHOSTUIFLAG_CODEPAGELINKEDFONTS = &H800
DOCHOSTUIFLAG_URL_ENCODING_DISABLE_UTF8 = &H1000
DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8 = &H2000
DOCHOSTUIFLAG_ENABLE_FORMS_AUTOCOMPLETE = &H4000
DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION = &H10000
DOCHOSTUIFLAG_IME_ENABLE_RECONVERSION = &H20000
DOCHOSTUIFLAG_THEME = &H40000
DOCHOSTUIFLAG_NOTHEME = &H80000
DOCHOSTUIFLAG_NOPICS = &H100000
DOCHOSTUIFLAG_NO3DOUTERBORDER = &H200000
End Enum

Public Enum DOCHOSTUIDBLCLK
DOCHOSTUIDBLCLK_DEFAULT = 0
DOCHOSTUIDBLCLK_SHOWPROPERTIES = 1
DOCHOSTUIDBLCLK_SHOWCODE = 2
End Enum

' MSG structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure MSG
Dim hwnd As IntPtr
Dim message As Integer
Dim wParam As Integer
Dim lParam As Integer
Dim time As Integer
Dim pt As tagPOINT
End Structure

' DOCHOSTUIINFO structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure DOCHOSTUIINFO
Dim cbSize As Integer
Dim dwFlags As DOCHOSTUIFLAG
Dim dwDoubleClick As DOCHOSTUIDBLCLK
Dim pchHostCss As String
Dim pchHostNS As String
End Structure

' OLEMENUGROUPWIDTHS structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure OLEMENUGROUPWIDTHS
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=6)> _
Dim width() As Integer
End Structure

' ICustomDoc interface
<ComVisible(True), ComImport(),
Guid("3050f3f0-98b5-11cf-bb82-00aa00bdce0b"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface ICustomDoc
Sub SetUIHandler(ByVal pUIHandler As IDocHostUIHandler)
End Interface

' IOleWindow interface
<ComVisible(True), ComImport(),
Guid("00000114-0000-0000-C000-000000000046"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IOleWindow
Sub GetWindow(ByVal phwnd As IntPtr)
Sub ContextSensitiveHelp(ByVal fEnterMode As Boolean)
End Interface

' IOleInPlaceActiveObject interface
<ComVisible(True), ComImport(),
Guid("00000117-0000-0000-C000-000000000046"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IOleInPlaceActiveObject : Inherits IOleWindow
' IOleWindow interface
Shadows Sub GetWindow(ByVal phwnd As IntPtr)
Shadows Sub ContextSensitiveHelp(ByVal fEnterMode As Boolean)
Sub TranslateAccelerator(ByRef lpmsg As MSG)
Sub OnFrameWindowActivate(ByVal fActivate As Boolean)
Sub OnDocWindowActivate(ByVal fActivate As Boolean)
Sub ResizeBorder(ByRef prcBorder As tagRECT, ByVal pUIWindow As
IOleInPlaceUIWindow, ByVal fFrameWindow As Boolean)
Sub EnableModeless(ByVal fEnable As Boolean)
End Interface

' IOleInPlaceUIWindow interface
<ComVisible(True), ComImport(),
Guid("00000115-0000-0000-C000-000000000046"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IOleInPlaceUIWindow : Inherits IOleWindow
' IOleWindow interface
Shadows Sub GetWindow(ByVal phwnd As IntPtr)
Shadows Sub ContextSensitiveHelp(ByVal fEnterMode As Boolean)
Sub GetBorder(ByRef lprectBorder As tagRECT)
Sub RequestBorderSpace(ByRef pborderwidths As tagRECT)
Sub SetBorderSpace(ByRef pborderwidths As tagRECT)
Sub SetActiveObject(ByVal pActiveObject As IOleInPlaceActiveObject,
ByVal pszObjName As String)
End Interface

' IDropTarget interface
<ComVisible(True), ComImport(),
Guid("00000122-0000-0000-C000-000000000046"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IDropTarget
Sub DragEnter(ByVal pDataObj As IDataObject, ByVal grfKeyState As
Integer, ByVal pt As tagPOINT, ByRef pdwEffect As Integer)
Sub DragOver(ByVal grfKeyState As Integer, ByVal pt As tagPOINT, ByRef
pdwEffect As Integer)
Sub DragLeave()
Sub Drop(ByVal pDataObj As IDataObject, ByVal grfKeyState As Integer,
ByVal pt As tagPOINT, ByRef pdwEffect As Integer)
End Interface

' IOleInPlaceFrame interface
<ComVisible(True), ComImport(),
Guid("00000116-0000-0000-C000-000000000046"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IOleInPlaceFrame : Inherits IOleInPlaceUIWindow
' IOleWindow interface
Shadows Sub GetWindow(ByVal phwnd As IntPtr)
Shadows Sub ContextSensitiveHelp(ByVal fEnterMode As Boolean)

' IOleInPlaceUIWindow interface
Shadows Sub GetBorder(ByRef lprectBorder As tagRECT)
Shadows Sub RequestBorderSpace(ByRef pborderwidths As tagRECT)
Shadows Sub SetBorderSpace(ByRef pborderwidths As tagRECT)
Shadows Sub SetActiveObject(ByVal pActiveObject As
IOleInPlaceActiveObject, ByVal pszObjName As String)

' TODO: hmenuShared should be a reference to a remotable handle
Sub InsertMenus(ByVal hmenuShared As IntPtr, ByRef lpMenuWidths As
OLEMENUGROUPWIDTHS)
Sub SetMenu(ByVal hmenuShared As IntPtr, ByVal holemenu As IntPtr, ByVal
hwndActiveObject As IntPtr)
Sub RemoveMenus(ByVal hmenuShared As IntPtr)
Sub SetStatusText(ByVal pszStatusText As String)
Sub EnableModeless(ByVal fEnable As Boolean)
Sub TranslateAccelerator(ByRef lpmsg As MSG, ByVal wID As UInt16)
End Interface

' IDocHostUIHandler interface
<ComVisible(True), ComImport(),
Guid("bd3f23c0-d43e-11cf-893b-00aa00bdce1a"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IDocHostUIHandler

<PreserveSig()> _
Function ShowContextMenu( _
ByVal dwID As Integer, _
ByRef ppt As tagPOINT, _
<MarshalAs(UnmanagedType.IUnknown)> ByVal pcmdtReserved As Object, _
<MarshalAs(UnmanagedType.IDispatch)> ByVal pdispReserved As Object)
As Integer

Sub GetHostInfo(ByRef pInfo As DOCHOSTUIINFO)

<PreserveSig()> _
Function ShowUI( _
ByVal dwID As Integer, _
ByVal pActiveObject As IOleInPlaceActiveObject, _
ByVal pCommandTarget As IOleCommandTarget, _
ByVal pFrame As IOleInPlaceFrame, _
ByVal pDoc As IOleInPlaceUIWindow) As Integer

Sub HideUI()
Sub UpdateUI()
Sub EnableModeless(ByVal fEnable As Boolean)
Sub OnDocWindowActivate(ByVal fActivate As Boolean)
Sub OnFrameWindowActivate(ByVal fActivate As Boolean)

Sub ResizeBorder( _
ByRef prcBorder As tagRECT, _
ByVal pUIWindow As IOleInPlaceUIWindow, _
ByVal fFrameWindow As Boolean)

<PreserveSig()> _
Function TranslateAccelerator( _
ByRef lpMsg As MSG, _
ByRef pguidCmdGroup As Guid, _
ByVal nCmdID As Integer) As Integer

Sub GetOptionKeyPath( _
ByRef pchKey As String, _
ByVal dw As Integer)

Sub GetDropTarget( _
ByVal pDropTarget As IDropTarget, _
ByRef ppDropTarget As IDropTarget)

Sub GetExternal(<MarshalAs(UnmanagedType.IDispatch)> ByRef ppDispatch As
Object)

<PreserveSig()> _
Function TranslateUrl( _
ByVal dwTranslate As Integer, _
ByRef pchURLIn As UInt16, _
ByVal ppchURLOut As IntPtr) As Integer

<PreserveSig()> _
Function FilterDataObject( _
ByVal pDO As IDataObject, _
ByRef ppDORet As IDataObject) As Integer

End Interface
</code>

Next, create a class (I call mine DocHostUIHandler) and implement
IDocHostUIHandler. If you are using V2003 you will get all the subs and
functions filled in for you; wonderful.

For convenience, define the following at the top of the class.

<code>
Private Const S_OK As Integer = 0
Private Const S_FALSE As Integer = 1
</code>

For every function that you are not going to intercept, return S_FALSE. That
will signal that you have not provided your own implementation. If you want
to prevent something, like the context menu, you can return S_TRUE in
ShowContextMenu(), for example. To change it, provide your own and then
return S_TRUE.

Now create a function in you main code, somewhere:

<code>
Private Sub SetUIHandler()

' Get a handle to the ICustomDoc interface on the document
Dim icd As ICustomDoc

icd = CType(AxWebBrowser1.Document, ICustomDoc)
icd.SetUIHandler(New DocHostUIHandler)

' *** Make sure you wait for a readystate of DocumentComplete here ***

End Sub
</code>

Now, call SetUIHandler in the DocumentComplete event of the AxWebBrowser1.

Finally, going back to the class that implements IDocHostUIHandler, my
GetHostInfo does this:

<code>
With pInfo
.cbSize = Len(pInfo)
.dwFlags = DOCHOSTUIFLAG.DOCHOSTUIFLAG_DIV_BLOCKDEFAULT
.dwDoubleClick = DOCHOSTUIDBLCLK.DOCHOSTUIDBLCLK_DEFAULT
End With
</code>

You can set the flags to what you like, for example, one of them affects the
3D border. The definition of the flags is in the MSDN.

Well, that's it. I hope I've included everything. Let me know how you get
on.


HTH

Charles
 
C

Charles Law

Hi Gokul


When you say you could not implement GetHostInfo, did you get an error, or
did it just not work?

Here is my version of GetHostInfo:

<code>
Public Sub GetHostInfo(ByRef pInfo As DOCHOSTUIINFO) Implements
IDocHostUIHandler.GetHostInfo

With pInfo
.cbSize = Len(pInfo)
.dwFlags = DOCHOSTUIFLAG.DOCHOSTUIFLAG_DIV_BLOCKDEFAULT Or _
DOCHOSTUIFLAG.DOCHOSTUIFLAG_FLAT_SCROLLBAR Or _
DOCHOSTUIFLAG.DOCHOSTUIFLAG_NO3DBORDER

.dwDoubleClick = DOCHOSTUIDBLCLK.DOCHOSTUIDBLCLK_DEFAULT
End With

End Sub
<code>

This successfully removes the 3D border, and also gives me a flat scroll
bar.

For additional information, I am using Windows 2000, SP4 and VS2003

Regards

Charles
 
G

gokul

Hi Charles,

By the time I replied U sat on it to give a last shot..........and
made it to work after a couple of tweaks...............

Its pretty fine.......now.....

Thank You

Regards
Gokul Raja.D
 
G

gokul

The tweaks are:

1.
These Interface(IOleCommandTarget) were missing and it gave an error
during Compilation, so I added this code:
<code>
<StructLayout(LayoutKind.Sequential)> _
Public Structure OLECMDTEXT
Public cmdtextf As UInt32
Public cwActual As UInt32
Public cwBuf As UInt32
Public rgwz As Char
End Structure

<StructLayout(LayoutKind.Sequential)> _
Public Structure OLECMD
Public cmdID As Long
Public cmdf As UInt64
End Structure

' Interop definition for IOleCommandTarget.
<ComImport(), Guid("b722bccb-4e68-101b-a2bc-00aa00404770"), _
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IOleCommandTarget
Sub QueryStatus(ByRef pguidCmdGroup As Guid, ByVal cCmds As
UInt32, _
<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> ByVal
prgCmds As OLECMD, _
ByRef pCmdText As OLECMDTEXT)

Sub Exec(ByRef pguidCmdGroup As Guid, ByVal nCmdId As Long, _
ByVal nCmdExecOpt As Long, ByRef pvaIn As Object, _
ByRef pvaOut As Object)
End Interface
</code>

2. During the first time the Noborder or FlatScroll.....none of the
setting were taking place only we load it again it got
implemented...so just triggered as follows:
AxWebBrowser1.Navigate("about:blank")
AxWebBrowser1.Navigate("http://www.google.com")

So this tweak allowed to achieve the desired effect on the Control
during load itself...........
It works pretty fine now......
Regards
Gokul Raja.D
 
C

Charles Law

Hi Gokul

Yes, sorry for missing those out. I have included mine below. They are
different in some places. It won't make any difference to you at this stage,
but I would suggest changing them because it will make a difference if you
use the IOLECommandTarget interface in future. In particular, the 'longs'
translate to integers in .NET.

<code>
' OLECMD
<StructLayout(LayoutKind.Sequential)> _
Public Structure OLECMD
Public cmdID As Int32
Public cmdf As Int32
End Structure

' OLECMDTEXT
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Class OLECMDTEXT
Public cmdtextf As OLECMDTEXTF
Public cwActual As Int32
Private cwBuf As Int32 = 256 'Make sure this is the same as SizeConst
below

<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
Public text As String
End Class

' IOleCommandTarget interface
<ComImport(), Guid("b722bccb-4e68-101b-a2bc-00aa00404770"), _
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IOleCommandTarget

Sub QueryStatus(ByRef pguidCmdGroup As Guid, ByVal cCmds As Int32, _
<InAttribute(), Out(), MarshalAs(UnmanagedType.LPArray,
SizeParamIndex:=1)> ByVal prgCmds() As OLECMD, <InAttribute(), Out()> ByVal
pCmdText As OLECMDTEXT)

Sub Exec(ByRef pguidCmdGroup As Guid, ByVal nCmdId As Int32, _
ByVal nCmdExecOpt As Int32, ByVal pvaIn As OLEVARIANT, ByVal pvaOut
As OLEVARIANT)

End Interface
</code>

Also, I would recommend putting a wait after every navigate. I call a
function WaitReady(), below

<code>
Private Sub WaitReady()
Do Until AxWebBrowser1.ReadyState =
SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE
Application.DoEvents()
Loop
End Sub
</code>

You could probably dispense with the second navigate then.

The reason for the wait is that pages are loaded asynchronously. Therefore,
the first navigate returns immediately, even before the page has been
initialised. The second navigate then causes the first one to be cancelled,
and the second page gets loaded.

As a general rule, before doing anything else, always navigate to
about:blank and wait for complete. This ensures that the control is always
fully initialised before you proceed.

HTH

Charles
 
C

Charles Law

[Copy of my e-mail reply to Gokul]

Hi Gokul

I will have a think about the first problem.

In the second, one thing that is notable is the changing of the designMode
state. Each time you change the state of this, you need to call SetUIHandler
to set the IDocHostUIHandler again. It gets cleared when the designMode
state changes. You should also set up the handler for the
HTMLDocumentEvents2 interface again (and any others that you use, on the
body for example).

I am also not convinced of the validity of using oSel.text <> "Control". Try
using AxWebBrowser1.document.selection.type instead. I think you will find
it more reliable. It will return "None", "Text", or "Control", depending on
what is selected.

Let me know if these suggestions help, and if you still have problem 1 after
the changes.

I notice that you are using late binding. Generally, I would suggest using
Option Explicit On and Option Strict On. It can help pick up some unintended
typographic errors.

Regards

Charles
 
G

gokul

Dear Charles,
I did tried your suggestions and couldn't come up with the
solution.....

(thank you for the tip AxWebBrowser1.document.selection.type )But
Iam unable to get the text that is selected on the Page without using
osel.text, now oSel.text also gives me problems....

and the second question is related to the First question I had
Yesterday for you........
I use a ShowDialog to display a list of URL's and from a list of
hyperlinks present in the dialog Iam suppose to navigate to the
corresponding pages in my Browser.

But Iam unable to achieve it.

Regards
Gokul
 
G

gokul

The Showdialog was the Culprit it wasn't allowing the change of
control to my other form and I had Issues....it is solved
now..........

But to get the selected text from the Browser control is my major
problem.

Regards
Gokul
 
C

Charles Law

Gokul

I use the following function, copied from the MSDN, to get at the current
selection. Does this do what you want?

Public Function GetElementUnderInsertionPoint(ByVal doc As
mshtml.IHTMLDocument2) As mshtml.IHTMLElement
'**************************
' Function copied from MSDN
'**************************
Select Case doc.selection.type
Case "None", "Text"
' This reduces the selection to just the insertion
' point. The parentElement method will then return the
' element directly under the mouse pointer.
Dim rg As mshtml.IHTMLTxtRange

rg = CType(AxWebBrowser1.document.selection.createRange,
mshtml.IHTMLTxtRange)
rg.collapse()

Return rg.parentElement

Case "Control"
' A form or image is selected. The commonParentElement
' will return the site selected element.
Dim ctlRg As mshtml.IHTMLControlRange

ctlRg = CType(AxWebBrowser1.document.selection.createRange,
mshtml.IHTMLControlRange)

Return ctlRg.commonParentElement

Case Else
MsgBox("Unexpected type: " & doc.selection.type)

Return Nothing

End Select

End Function

HTH

Charles
 
G

gokul

Dear Charles,
Thanks for the Tip, it worked....Indeed I posted a reply last night
.........but I couldn't figure why it hasn't posted here......

Thanks a lot.....
Regards
Gokul Raja.D
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top