Introduction
Background
Implementation challenges:
Events
_ATL_MIN_CRT
Asynchronous Pluggable Protocols
RegisterBindStatusCallback and Content-Disposition header
Brief Overview of Classes
Setting up the control
About Demo Applications
Control:
Properties
Events
Methods
Related Documents
History
Downloads
C# Version!
Contact
The goal of this project is to replace web browser wrapper control with one that allows developers to create and use a web browser control having total control over GUI, context menus, accelerator keys, downloads, security, ... without using any sub classing, registry or hacks. The result is an ATL control:
DOC_HOST_UI_FLAGS
per Webbrowser Control instance or globally. NO3DBORDER, ...
DOC_DOWNLOAD_CONTROL_FLAGS
per Webbrowser Control instance or globally. DLIMAGES
, DLVIDEOS
, ...
OnContextMenu
event for each context menu activated.
OnWBKeyDown
and OnWBKeyUp
events
FileDownloadEx
and OnFileDLxxxx
events.
DownloadUrlAsync
method and OnFileDLxxx
events.
SecurityManagerProcessUrlAction
event.
WBProcessUrlAction
event.
OnAuthentication
event
OnGetOptionKeyPath
and OnGetOverrideKeyPath
events.
GET
or POST
methods with notifications via OnPostxxxx
events.
OnWBDragxxx
and OnWBDropx
events.
Even though, this control was made to be used by VB, but due to the fact that
it is a Fully compliant ActiveX control, it can also be used from MFC
,
.NET
, ...
The control is written in VC++ 6.0 using ATL3.0. It is compiled with minimum dependencies (no
MFC
, std::
, CString
, ...). It is designed to host multiple
WebBrowser controls within one ATL
created window. This is contradictory to MSDN recommendation
which suggests to use one ATL window per hosted control. The reason for choosing
this approach was to remove burden of Webbrowser control management from the hosting client application
to the control. Normally, a developer places an instance of a control on a form/dlg,
then if needed, an array of the controls is created and maintained by client
application. My approach enables the developer to insert one instance of this control on
a form/dlg and then use CvbWB::AddBrowser
and CvbWB::RemoveBrowser
methods to
add and remove Webbrowser controls. Each newly created control (through an
instance of IWB
class) is assigned a unique id (wbUID)
.
This unique id enables the client application to
communicate with that specific Webbrowser control instance via it's properties, methods, and
to find out which Webbrowser control has fired an event.
There are many articles that cover the basics of creating, hosting and sinking events of a Webbrowser
control.
So rather than going through CoCreateInstance
, IOleObject::SetClientSite
, and so on. I
decided to explain some of the main implementation challenges where you will find very little
and often no information about them.
Here is a list of main challenges encountered and resolved during development of this control. I neither claim that these solutions are unique nor the best. Just that they seem to work.
1) The first issue that I encountered was lack of documentation on how to
pass byref parameter or objects to a client application such as VB. Attempts to
handle any of these wizard generated events was causing GPF. Here is a sample of the none working code for NewWindow3
event
taken from CProxy_IvbWBEvents
class:
VOID Fire_NewWindow3(SHORT wbUID, IDispatch * * ppDisp, VARIANT_BOOL * Cancel, LONG lFlags, BSTR sURLContext, BSTR sURL) { T* pT = static_cast(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[6]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast (sp.p); if (pDispatch != NULL) { pvars[5] = wbUID; ///////////////////////////////////////////////////////////// //Next two params need to be passed by ref or they cause GPF // pvars[4] = ppDisp; pvars[3] = Cancel; ///////////////////////////////////////////////////////////// pvars[2] = lFlags; pvars[1] = sURLContext; pvars[0] = sURL; DISPPARAMS disp = { pvars, NULL, 6, 0 }; pDispatch->Invoke(0x2d, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL); } } }
And here is the correction:
pvars[4].vt = VT_BYREF|VT_DISPATCH; pvars[4].byref = ppDisp; pvars[3].vt = VT_BOOL|VT_BYREF; pvars[3].byref = Cancel;
2) The second issue that I encountered was again related to events. This issue showed up when I implemented the protocol handlers.
Apparently, the
IConnectionPointImpl
does not fire events across COM components. So, after some looking around, I came across KB article 280512,
ATLCPImplMT
encapsulates ATL event firing across COM apartments. Using included class IConnectionPointImplMT
(From MS) solved this issue. And here is the completed code for Newwindow3
event:
VOID Fire_NewWindow3(SHORT wbUID, IDispatch * * ppDisp, VARIANT_BOOL * Cancel, LONG lFlags, BSTR sURLContext, BSTR sURL) { T* pT = static_cast(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[6]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { ////////////////////////////////////////////////////////////////////// //Next three lines need to be replaced //pT->Lock(); //CComPtr sp = m_vec.GetAt(nConnectionIndex); //pT->Unlock(); ///////////////////// ////////////////////////////////////////////////////////////////////// //Replaced the previous three lines of code with the next two lines CComPtr sp; sp.Attach (GetInterfaceAt(nConnectionIndex)); ///////////////////// IDispatch* pDispatch = reinterpret_cast (sp.p); if (pDispatch != NULL) { pvars[5] = wbUID; pvars[4].vt = VT_BYREF|VT_DISPATCH; pvars[4].byref = ppDisp; pvars[3].vt = VT_BOOL|VT_BYREF; pvars[3].byref = Cancel; pvars[2] = lFlags; pvars[1] = sURLContext; pvars[0] = sURL; DISPPARAMS disp = { pvars, NULL, 6, 0 }; pDispatch->Invoke(0x2d, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL); } } }
3) The third issue showed up after implementing protocol hanlder. I needed to fire events from the WBPassthruSink
(protocol handler sink) class for a specific Webbrowser control to notify the client
application via ProtocolHandlerOnBeginTransaction
and ProtocolHandlerOnResponse
events. Since the instances of the WBPassthruSink
class are created
by URLMon as needed by PassthroughAPP
,
I had to find a way to determine which instance of the Webbrowser control is involved so I can fire events for that specific control.
My solution was to find the Internet Explorer Server HWND in the implementation of WBPassthruSink::OnStart
using IWindowForBindingUI
interface
Obtained from our protocol handler.
//Using IWindowForBindingUI interface CComPtrobjWindowForBindingUI; //This is a macro for QueryService HRESULT hret = QueryServiceFromClient(&objWindowForBindingUI); if( (SUCCEEDED(hret)) && (objWindowForBindingUI) ) { HWND hwndIEServer = NULL; //Should return InternetExplorerServer HWND objWindowForBindingUI->GetWindow(IID_IHttpSecurity, &hwndIEServer); //From here we can find the ATL window hosting this instance of our control //and have it fire an event for the form/dlg hosting this instance of our control if(hwndIEServer)
One of the design goals of this control was to be build with minimum dependencies. Standard _ATL_MIN_CRT support does the job for eliminating the CRT overhead well. But unfortunately, it doesn't support the use of global C++ constructs, like the following:
class CTest { public: CTest() { MessageBox(NULL, _T("Hello, I'm intitialized"), _T("Static object"), MB_SETFOREGROUND | MB_OK); } ~CTest() { MessageBox(NULL, _T("Bye, I'm done"), _T("Static object"), MB_SETFOREGROUND | MB_OK); } }; static CTest g_test; extern CTest *gp_Test;
The above would lead to linker conflicts, because CRT code for
constructors/destructors invocation would be referenced.
To overcome this, I am using AuxCrt.cpp
custom _ATL_MIN_CRT implementation and a replacement for AtlImpl.cpp
class.
This class is from Andrew Nosenko (andien@geocities.com).
http://www.geocities.com/~andien/atlaux.htm.
With this class, I was able to use CSimpleArray
as a global variable to keep track of instances of
Webbrowser controls. Note, for convenience, I placed a copy of AuxCrt.cpp
in the ATL\Include\
directory.
//Taken from StdAfx.h //gCtrlInstances keeps track of each instance of our control //This global is needed due to the fact that a client may place //this control on more than one form/dlg or have multiple instances of BW //hosting in one control. In this case, using one //global ptr to our control will cause the events to be routed to the //first control, not the one we want. The control instances (this) is //added to this array in Constructor and removed in Destructor of CvbWB class. extern CSimpleArray<void*> gCtrlInstances; //Flag to track registering and unregistering of HTTP/HTTPS protocols //Can only be done once per DLL load. Effects all instances of Webbrowser control. extern BOOL gb_IsHttpRegistered; extern BOOL gb_IsHttpsRegistered; //Protocol handling registration extern CComPtrm_spCFHTTP; extern CComPtr m_spCFHTTPS; ....
One of the my main design goals was to be able to act as a pass through
between Webbrowser control and URLMon so as to intercept all the requests and responses by using
a asynchronous
pluggable protocol. At the start, this task seemed pretty straightforward, implement IInternetProtocol, IInternetProtocolInfo, IInternetPriority, IInternetProtocolSink, IInternetBindInfo, IClassFactory
interfaces. In the implementation of the IServiceProvider::QueryService
, create and pass an instance of my IInternetProtocolImpl
to
URLMon
. Overwrite necessary methods and handle the requests. Unfortunately, this approach had a
big flaw, My IInternetProtocol
implementation was only being called
to handle the main document and not for the rest of the page requests, images, css,...
After doing some searching, I came across an excellent package called PassthroughAPP
by
Igor Tandetnik. In google groups under
microsoft.public.inetsdk.programming.xxx, just search for PassthroughAPP
. The
package contains 5 files.
PassthroughObject.h |
A simple COM object. IPassthroughObject
|
ProtocolCF.h |
A customized COM class factory. Implements CComClassFactory |
ProtocolCF.inl |
Class factory implementation |
ProtocolImpl.h |
Protocol handlers header. Implemented interfaces,
|
ProtocolImpl.inl |
Protocol handlers implementation |
Except for
the five methods that I have overridden in WBPassthruSink class to intercept all
the requests and responds, I will not be able to answer any questions regarding PassthroughAPP.
Please direct your
questions to the author as my
understanding of package's design and implementation is limited.
One of the design goals of this control was to take full control over file
downloads. This was pretty simple to implement at first and all seemed to work
without a glitch. But as usual, a strange problem was reported. If a user
attempted to download an attachment from Hotmail, Yahoo, ... the default
download dialog was being displayed, bypassing my custom download manager. I
traced the problem to RegisterBindStatusCallback
method which is called in IDownloadManager::Download
method, it was returning E_FAIL. This failure seems to occur when a server sends
a Content-Disposition header in response to a file download request. Of course, MSDN
does not even mention anything about an E_FAIL return or why
RegisterBindStatusCallback may fail. After searching for a while to no
avail, I decided to attempt to implement a work around.
First step was to somehow force RegisterBindStatusCallback
to succeed.
RegisterBindStatusCallback
, passing an IBindStatusCallback
pointer to
retrieve previous IBindStatusCallback
RevokeObjectParam
to
unregister the previous IBindStatusCallback
RevokeObjectParam
indicate success, attempt to call RegisterBindStatusCallback
for a second time which should succeed//Taken from WBDownLoadManager::Download //filedl is an instance of my IBindStatusCallback implementation //pbc is a BindCtx pointer passed to Download method IBindStatusCallback *pPrevBSCB = NULL; hr = RegisterBindStatusCallback(pbc, reinterpret_cast(filedl), &pPrevBSCB, 0L); if( (FAILED(hr)) && (pPrevBSCB) ) { //RevokeObjectParam for current BSCB, so we can register our BSCB //_BSCB_Holder_ is the key used to register a callback with a specific BindCtX LPOLESTR oParam = L"_BSCB_Holder_"; hr = pbc->RevokeObjectParam(oParam); if(SUCCEEDED(hr)) { //Attempt register again, should succeed now hr = RegisterBindStatusCallback(pbc, reinterpret_cast (filedl), 0, 0L); if(SUCCEEDED(hr)) { //Need to pass a pointer for BindCtx and previous BSCB to our implementation filedl->m_pPrevBSCB = pPrevBSCB; filedl->AddRef(); pPrevBSCB->AddRef(); filedl->m_pBindCtx = pbc; pbc->AddRef(); } //....
Second step was to relay some calls to the previous IBindStatusCallback
from our implementation. Otherwise no download
will take place. Memory leaks and crashes to be expected. This part was based on
trial and error.
::OnStartBinding
if(m_pPrevBSCB) { m_pPrevBSCB->OnStopBinding(HTTP_STATUS_OK, NULL); }
::OnProgress
if(m_pPrevBSCB) { //Need to do this otherwise a filedownload dlg will be displayed //as we are downloading the file. if(ulStatusCode == BINDSTATUS_CONTENTDISPOSITIONATTACH) return S_OK; m_pPrevBSCB->OnProgress(ulProgress, ulProgressMax, ulStatusCode, szStatusText); }
::OnStopBinding
if( (m_pPrevBSCB) && (m_pBindCtx) ) { //Register PrevBSCB and release our pointers LPOLESTR oParam = L"_BSCB_Holder_"; m_pBindCtx->RegisterObjectParam(oParam, reinterpret_cast(m_pPrevBSCB)); m_pPrevBSCB->Release(); m_pPrevBSCB = NULL; m_pBindCtx->Release(); m_pBindCtx = NULL; //Decrease our ref count, so when release is called //we delete this object --m_cRef; }
Please ensure that you have the latest SDK that works with VC++ 6.0 , February 2003 SDK.
Class Name | Implements | Description |
---|---|---|
CvbWB |
CComObjectRootEx
IDispatchImpl
CComControl
IPersistStreamInitImpl
IOleControlImpl
IOleObjectImpl
IOleInPlaceActiveObjectImpl
IViewObjectExImpl
IOleInPlaceObjectWindowlessImpl
ISupportErrorInfo
IConnectionPointContainerImpl
IPersistStorageImpl
ISpecifyPropertyPagesImpl
IQuickActivateImpl
IDataObjectImpl
IProvideClassInfo2Impl
IPropertyNotifySinkCP
CComCoClass
CProxy_IvbWBEvents
|
This class was created as a Full ATL control using the wizard. It is responsible to host the
control in a client application (VB, C++), fire events, allow access to properties and
methods of all WebBrowser controls to the hosting client. This task is achieved by using a
simple array of IWB pointers. The pointers are added and
removed from array in calls to AddBrowser and RemoveBrowser methods.
Each new instance of IWB is given a unique id wbUID .
The client application uses this id to access this instance of Webbrowser
control's properties and methods. Also, all events come with an extra
parammeter, wbUID , which identifies the Webbrowser instance
that has fired the event. In addition, This class contains a number of useful methods and
properties, get_ActiveDocumentObj get_ActiveElementObj (Returns Active
document or element. Accounts for frames), DownloadUrlAsync (Starts a file
download, allowing client app to monitor status via OnFileDL_xxx events), ucInternetCrackUrl
(To break a given URL into parts including filename and ext. Parts are
accessed via Get/Set ucXXX properties),... |
IWB |
IUnknown |
This class is responsible to create and maintain a single
instance of a Webbrowser control along with all the necessary classes such as WBClientSite (IOleClientSite implementation). Also, all QIs from all
the classes are routed through the same IWB instance that created them.
In addition, it contains a number of useful methods, IsFrameset , FramesCount
, DocHighlightFindText ,... |
WBClientSite |
IOleClientSite |
Required as part of Webbrowser control hosting interfaces. All methods return E_NOTIMPL. |
WBInPlaceSite |
IOleInplaceSite |
Required as part of Webbrowser control hosting interfaces. All methods return E_NOTIMPL. |
WBEventDispatch |
IDispatch |
This class is the sink for Webbrowser control events. As the events arrive from Webbrowser control, it fires events to notify the client application. |
WBDocHostShowUI |
IDocHostShowUI |
I am only handling ::ShowMessage method which is responsible to intercept
HTTP messages and notifies the client via Fire_ShowMessage event to determine what to do with the message. A typical message may look like this:
Your current security settings prohibit running ActiveX controls on this page. As a result, the page may not display correctly. |
WBOleCommandTarget |
IOleCommandTarget |
The purpose of this class is to intercept Script errors via ::Exec method,
and based on the m_lScriptError flag, either allow or disallow them. |
WBAuthenticate |
IAuthenticate |
This class intercepts requests for basic authentication from servers,
notifies the client using OnAuthentication event to obtain
username and password. Useful for clients wanting to automate the process of logging in using
basic authentication schemes. |
WBDocHostUIHandler |
IDocHostUIHandler |
The purpose of this class is to intercept
context menu (::ShowContextMenu ), accelerator keys (::TranslateAccelerator ),
and to set the UI flags (::GetHostInfo ). |
WBHttpSecurity |
IHttpSecurity |
This class intercepts HTTP related security problems, such as
ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION , ERROR_INTERNET_SEC_CERT_CN_INVALID via OnSecurityProblem method.
Please note, using ::OnSecurityProblem method or OnHTTPSecurityProblem event incorrectly can compromise the security of your application and
potentially leave users of your application exposed to unwanted information disclosure. |
WBSecurityManager |
IInternetSecurityManager |
This class only implemets ::ProcessUrlAction method. It returns
INET_E_DEFAULT_ACTION for the rest of the methods. Please note, using ::ProcessUrlAction method or
SecurityManagerProcessUrlAction event incorrectly may result in the incorrect processing of URL actions and possibly leave users
susceptible to elevation of privilege attacks. |
WBServiceProvider |
IServiceProvider |
It is responsible to respond to QueryService calls on our
IUknown(IWB) in ::QueryService method. |
WBWindowForBindingUI |
IWindowForBindingUI |
It returns a hanlde to a window via ::GetWindow method
which is used by MSHTML to display information in the client's user interface when necessary. Currently,
this method returns a hanlde to the Internet Explorer Server window. |
WBBSCBFileDL |
IBindStatusCallback IHttpNegotiate |
An instance of this class is created and used
to receive callbacks and notify client app via OnFileDLxxxx events for all file downloads. By user clicking on a download link or
by using ::DownloadUrlAsync method from code. |
WBDownLoadManager |
IDownloadManager |
It implements ::Download method which in
turn creates an instance of our IBindStatusCallback implementation (WBBSCBFileDL ), registers our BSCB for callbacks and
notifies the client via
OnFileDLxxxx events of the progress of the download. Each BSCB is
given a Unique ID and a pointer to it is stored in a simple array in the CvbWB class
instance. This ID can be used by client app to cancel a download by calling CancelFileDl passing the id. |
CTmpBuffer |
A simple string buffer class, since CString is not available due to minimum
dependency requirement. |
|
CUrlParts |
A simple class which uses InternetCrackUrl method of WinInet to break a given URL into it's parts. This includes
file name and ext, if available. |
|
WBPassThruSink |
CInternetProtocolSinkWithSP IHttpNegotiate |
This class is the sink for the protocol handlers. |
WBDropTarget |
IDropTarget |
To handle custom dragdrop. |
WBDocHostUIHandler |
IDocHostUIHandler2 |
To handle GetOverrideKeyPath method. |
WBStream |
IStream |
To handle uploads with progress. |
How to register example, (assuming system dir path is 'C:\windows\system32\') regsvr32.exe C:\windows\system32\vbMHWB.dll.
Both demo projects are almost identical in terms of GUI and their use of the
control. The VBDemo was build using Visual Basic 6.0
and has no dependencies
other than this control. The MFCDemo project was build using Visual C++ 6.0
and
also has no other dependencies. With MFCDemo, you need to treat BOOL
as
VARIANT_BOOL
(Wizard translates VARIANT_BOOL
as BOOL
),
and make sure that value of an in/out BSTR parameter is released (ClearBSTRPtr
method is provided as an example) before assigning a new value. This step is necessary
to avoid memory leaks.
Note: this demo is not intended for novice programmers and should be viewed as a learning and experimental tool. Expect bugs!
This project was build using Visual Basic 6.0
. It does depend on an external
type library WinApiForVb.tlb
. This library was put together by me a while back to
avoid copying and pasting API declarations in every new VB project. It consists of 950 KB of API declarations (ANSI+UNICODE). The
source and the compiled versions of the WinApiForVb.tlb
have been provided in WinApiForVb-Source
and
WinApiForVb_Compiled
sub folders.
Build versions have been included in Binaries sub folder for all projects.
Count As Integer
- Read only.
Returns Web browser's count.
RegisterAsDropTarget(wbUID As Integer, bUseIEDefault As Boolean) As Boolean
To use IE default drag drop functionality, set bUseIEDefault to true. Default value is false, uses internal drag drop mechanism via WBDrag/Drop events.
ActiveElementObj(wbUID As Integer) As Object
- Read only.
Returns active element dispatch object for specified wbUID
. Accounts for frames.
ActiveDocumentObj(wbUID As Integer) As Object
- Read only.
Returns active document dispatch object for specified wbUID
. Accounts for frames.
ObjectWB(wbUID As Integer) As Object
- Read only.
Returns dispatch object for specified wbUID
.
**ContextMenuAction([wbUID As Integer]) As Long
Default=0 do not display, 1 display all, 2 raise OnContextMenu
event.
**DocumentDownloadControlFlags([wbUID As Integer]) As Long
Default=_DLIMAGES
,_VIDEOS
,_BGSOUNDS
. Refresh
Webbrowser control for new flags to take effect.
**DocumentHostUiFlags([wbUID As Integer]) As Long
Default=TextSelect
,No3DBorder
,FlatScrollbars
. Refresh
Webbrowser control for new flags to take effect.
**DocumentHostUiDoubleClickAction([wbUID As Integer]) As Long
DEFAULT
=0, SHOWPROPERTIES
= 1, SHOWCODE
/Source
= 2. Refresh
Webbrowser control for new flags to take effect.
IsDocFrameset(wbUID As Integer) As Boolean
Returns True
if the document specified by wbUID
contains frames.
*ucScheme As String
Set/Get URL scheme as string: HTTP, HTTPS.
*ucHostName As String
Set/Get URL host name.
*ucPort As Long
Set/Get URL port.
*ucUserName As String
Set/Get URL username.
*ucPassword As String
Set/Get URL password.
*ucUrlPath As String
Set/Get URL path.
*ucExtraInfo As String
Set/Get URL extra info.
*ucFullURL As String
Set/Get full URL.
*ucFileName As String
- Read only
Get URL filename.
*ucFileExtension As String
- Read only
Get URL file extension.
*ucInternetScheme As Long
Set/Get URL Scheme as long
.
HWNDShellDocObjectView(wbUID As Integer) As Long
- Read only
Returns HWND
of ShellDocObjectView
for specified wbUID
.
HWNDInternetExplorerServer(wbUID As Integer) As Long
- Read only
Returns HWND
of InternetExplorerServer
for specified wbUID
.
HWNDMainWnd As Long
- Read only
Returns HWND
of the main DLL window where all Web browsers are hosted.
HWNDShellEmbedding(wbUID As Integer) As Long
- Read only
Returns HWND
of ShellEmbedding
for specified wbUID
.
StartupURL As String
Initial startup URL. Default about:blank.
**UseIEDefaultFileDownload([wbUID As Integer]) As Boolean
Default=False
, using internal download mechanism, send FileDownloadEx
and OnFileDLxxx
events.
FramesCount(wbUID As Integer) As Long
- Read only
Returns number of frames for specified wbUID
.
WBVisible(wbUID As Integer) As Boolean
Set/Get visible state for specified wbUID
.
WBPageTextSize(wbUID As Integer)
Set/Get page zoom level. valid values 0 to 4 (smallest-largest).
SourceOnDocComplete(wbUID As Integer) As Boolean
If set to True, fires DocumentCompleteWBEx
instead of DocumentComplete
passing document text before any scripts are executed.
Note* Properties are used in combination with two methods ucInternetCrackUrl
and ucInternetCreateUrl
.
Note** If wbUID
is greater than 0, action is of the specific wbUID
else action will be applied to all
Webbrowser controls. Less for client to do.
OnWBKeyDown(wbUID As Integer, nKeyCode As Integer, nVirtExtKey As Integer, bHandled As Boolean)
Fired when a key is down within browser window. bHandled
default value is False. Set bHandled
to True to consume the key.
OnWBKeyUp(wbUID As Integer, nKeyCode As Integer, nVirtExtKey As Integer, bHandled As Boolean)
Fired when a key is up within browser window. bHandled
default value is False. Set bHandled
to True to consume the key.
DocHostShowMessage(wbUID As Integer, lHwnd As Long, strText As String, strCaption As String, lType As Long, strHelpFile As String, lHelpContext As Long, lReturnValue As Long, ShowMsgInternaly As Boolean)
Fires before an HTML message, including javascript alerts, is about to be displayed. To display own messagebox, set ShowMsgInternaly
to false and set lReturnValue
to the return value.
OnShowScriptError(wbUID As Integer, vErrorLine, vErrorCharacter, vErrorCode, vErrorMsg, vErrorURL, bStopRunningScript As Boolean)
Fires when there is a script error passing relative information. Default value of bStopRunningScript
is True
.
FindAnyTextMatchCallback(wbUID As Integer, pHtmlDoc2Disp As Object, pTxtRangeElemDisp As Object, bStopSearch As Boolean)
Fired in response after a call to FindAnyTextMatch
and if a match is found.
Searching for a match continues till pHtmlDoc2Disp
contains IDispatch
of the document object.
pTxtRangeElemDisp
contains IDispatch of IHTMLTxtRange
element used to find given text
ProtocolHandlerOnBeginTransaction(ByVal wbUID As Integer, ByVal sURL As String, ByVal sRequestHeaders As String, sAdditionalHeaders As String, Cancel As Boolean)
Fired by the HTTP or HTTPS protocol handler before sending the request headers to a server. Fired after BeforeNavigate2. This includes HTML, images, CSS, ... To activate or deactivate protocol handlers, use RegisterHTTPprotocol or RegisterHTTPSprotocol. Additional headers can be added using sAdditionalHeaders parameter. Default, Cancel = False. Request can be cancelled by setting Cancel to True.
ProtocolHandlerOnResponse(ByVal wbUID As Integer, ByVal sURL As String, ByVal sResponseHeaders As String, ByVal sRedirectedUrl As String, ByVal sRedirectHeaders As String, Cancel As Boolean)
Fired by the HTTP or HTTPS protocol handler after receiving the response headers from the server. This includes any redirect headers that were sent after a normal response. Fired before DocumentComplete. To activate or deactivate protocol handlers, use RegisterHTTPprotocol or RegisterHTTPSprotocol. If sRedirectedUrl has value, it indicates that during the initial request, we were redirected to another site.
Default, Cancel = True. Request can be cancelled by setting Cancel to True.
NewWindow2(ByVal wbUID As Integer, ppDisp As Object, Cancel As Boolean)
A new, hidden, non-navigated web browser window is needed. Default, Cancel = True.
NewWindow3(ByVal wbUID As Integer, ppDisp As Object, Cancel As Boolean, ByVal lFlags As Long, ByVal sURLContext As String, ByVal sURL As String)
This event has been added in addition to the NewWindow2 event. Fires before NewWindow2 and is only available in XP SP2 and higher. Default, Cancel = True.
OnAuthentication(ByVal wbUID As Integer, sUsername As String, sPassword As String, Cancel As Boolean)
Network authentication. Supports basic authentication. Can be used to automate network log-ins without user interaction. Default, Cancel = False.
OnContextMenu(ByVal wbUID As Integer, ByVal ContextMenuType As Long, ByVal X As Long, ByVal Y As Long, ByVal ObjElem As Object, ctxDisplay As Boolean)
Fired before the context menu is displayed. ctxDisplay default value is False.
OnGetOptionKeyPath(ByVal wbUID As Integer, sRegistryOptionKeyPath As String)
Points the web browser control to a registry key located at HKEY_CURRENT_USER/Software/YourCompany/YourApp for registry overrides.
OnGetOverrideKeyPath(ByVal wbUID As Integer, sRegistryOverrideKeyPath As String)
Points the web browser control to a registry key located at HKEY_CURRENT_USER/Software/YourCompany/YourApp for user preference overrides.
OnWBDragEnter(ByVal wbUID As Integer, ByVal KeyState As Integer, ByVal ptX As Long, ByVal ptY As Long, lEffect As Long)
Keystate, combination of MK_CONTROL, MK_SHIFT, MK_ALT, MK_BUTTON, MK_LBUTTON, MK_MBUTTON, and MK_RBUTTON. ptX and ptY are in screen coordinates
OnWBDragLeave(ByVal wbUID As Integer)
DragLeave - cancelled.
OnWBDragOver(ByVal wbUID As Integer, ByVal KeyState As Integer, ByVal ptX As Long, ByVal ptY As Long, lEffect As Long)
Parameters are same as OnWBDragEnter event.
OnWBDrop(ByVal wbUID As Integer, ByVal KeyState As Integer, ByVal ptX As Long, ByVal ptY As Long, ByVal lpData As String,ByVal lWBDropFormat As Long, lEffect As Long)
Fired for a single file or data drops. Drop- lpData will contain the dropped filename or data. lWBDropFormat can be one of:
OnWBDrop2(ByValwbUID As Integer, ByVal KeyState As Integer, ByVal ptX As Long, ByVal ptY As Long, ByVal vData, lEffect As Long)
Fired for multiple file name drops, i.e. from explorer. - vData will contain a string array VT_ARRAY|VT_BSTR of dropped file names.
OnPostResponse(ByValPostUID As Integer, ByVal sURL As String, ByVal lResponseCode As Long, ByVal sResponseHeaders As String)
Fired after a response is available from the server.
OnPostOnProgress(ByValPostUID As Integer, ByVal sURL As String, ByVal lProgress As Long, ByVal lProgressMax As Long, ByVal lStatusCode As Long, ByVal sStatusText As String, CancelPost As Boolean)
Fired during data arrival in response to a post request.
OnPostError(PostUID As Integer, sURL As String, sErrorMsg As String)
Fired if any errors occur.
OnPostEnd(ByValPostUID As Integer,ByVal sURL As String)
Fired to signal the end of a post request.
OnPostDataAvailable(ByVal PostUID As Integer, ByVal sURL As String, ByVal pData As String, CancelPost As Boolean)
Fired if any data has been received.
OnWMMessage(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, lReturn As Long, Handled As Boolean)
Fired in response to a WM_xxx message. This message must have been added to a subclassed window message, using AddMessage method. uMsg, one of the WM_xxxx messages. Defaults, Handled = False, lReturn = 0
*OnFileDLProgress(ByVal sURL As String, ByVal lProgress As Long, ByVal lProgressMax As Long, CancelDl As Boolean)
On download progress.
*OnFileDLEndDownload(ByVal sURL As String)
On end of download.
*OnFileDLDownloadError(ByVal sURL As String, ByVal sErrorMsg As String)
On download errors.
*OnFileDLBeginningTransaction(Byval FileDlUID As Integer, Byval sURL As String, Byval sRequestHeaders As String, sAdditionalRequestHeaders As String, bResuming As Boolean, bCancel As Boolean)
Fired before sending request headers to the server for a file download initiated by the DownloadAsync method. Gives client a chance to add additional headers. If the local file exists, you can set bResuming to True, indicating that the control should start writing to the end of the local file when the data arrives. You should also add a range header to the sAdditionalRequestHeaders parameter to attempt to resume a broken download.
*OnFileDLResponse(ByVal sURL As String, ByVal lResponseCode As Long, ByVal sResponseHeaders As String, CancelDl As Boolean)
Fired after receiving the first initial response from the server. Can examine sResponseHeaders and lResponseCode to determine whether to continue or abort the download.
*OnFileDLCancelDownload(ByVal sURL As String, ByVal CancelledDuringDL As Boolean)
Fired to signal that a download has been cancelled.
*FileDownloadEx(ByVal wbUID As Integer, ByVal FileDlUID As Integer, ByVal sURL As String, ByVal sFilename As String, ByVal sExt As String, ByVal sExtraHeaders As String, ByVal sRedirURL As String, SendProgressEvents As Boolean, bStopDownload As Boolean, sPathToSave As String)
By default, vbMHWB takes over all web browser control file downloads internally. This gives the developer the ability to control the download using OnFileDLxxx events. If you wish to use the default behaviour of web browser control, set UseIEDefaultFileDownload to True. This event is called in place of the FileDownload event if UseIEDefaultFileDownload = False.
DocumentCompleteWBEx(ByVal wbUID As Integer, URL As Variant, ByVal pDisp As Object, ByVal isTopLevel As Boolean, ByVal sDocSource As String)
If SourceOnDocComplete property is set to true then this event is fired passing the source of the pDisp object (if HTML based) via sDocSource parameter before any scripts are executed.
WBProcessUrlAction(ByVal wbUID As Integer, ByVal sURL As String, ByVal lUrlAction As Long, ByVal PUAF_Flag As Long, lpUrlPolicy As Long, bHandled As Boolean)
lUrlAction, one of URL Action values. PUAF_Flag, one of PUAF enum. By default, bHandled is false, if setting lpUrlPolicy parameter, you also need to set the bHandled to true. lpUrlPolicy parameter is declared as long variable that can be set by client, one of URL Policy Flags.
WBEvaluateNewWindow(ByVal wbUID As Integer, ByVal sURL As String, ByVal sName As String, ByVal sURLContext As String, ByVal sFeatures As String, ByVal bReplace As Boolean, ByVal lFlags As Long, ByVal lUserActionTime As Long, lPopUpAction As Long)
WinXPsp2 and up
lPopUpAction default value set to E_FAIL (-2147467259) (Perform default IE action).
First calls NewWindow3 , then NewWindow2, if popup is not cancelled then displays the popup.
To cancel set lPopUpAction to 1. To allow set lPopUpAction to 0. lFlags one of NEW_WINDOW3_FLAGS enum
Note* Events are generated while using DownloadUrlAsync or by using the vbMHWB internal downloader by setting UseIEDefaultFileDownload to True (default is False). The DLL uses the internal download mechanism by default.
Sub AddBrowser(wbUID As Integer, [bBringToFront As Boolean = False])
Attempts to add new Web browser. If successful, returns the new ID contained in wbUID
.
bBringToFront
allows the client to open the new Web browser in the background.
Sub SaveAsBitmap(wbUID As Integer, BitmapName As String)
Saves the entire page, no scroll bars, or borders to a file passed in BitmapName
param.
Sub DrawWBThumbnailOnWnd(wbUID As Integer, WndHdc As Long, lX As Long, lY As Long, lW As Long, lH As Long)
Draws an image of the web browser's viewing area on a given WndHdc
. Routine uses StretchBlt
to fit the image based on lX
(left), lY
(top), lW
(width), lH
Height.
Sub LoadHTMLFromString(wbUID As Integer, sContent As String, sBaseUrl As String)
Loads sContent
into a stream which is then loaded into the document. Unlike document.write
, scripts are executed.
If content is greater than 256 characters then a base
tag must be present to dispaly the entire content.
sBaseUrl
sample: http://www.google.com.
Sub DisplayCertificateDialog(wbUID As Integer)
Displays the certificate dialog for a valid HTTPS site. This is the same as the user clicking the lock icon in IE6.
Sub ucResetFieldsToDefault()
Resets all the ucxxxx fields to their default.
Sub SubclassWnd(hwndWnd As Long)
Subclass a window specified by hwndWnd
and receive onWMxxxx
messages.
Sub UnSubclassWnd(hwndWnd As Long)
Unsubclass a previously subclassed window.
Sub AddMessage(hwndWnd As Long, lMsg As Long)
Add a WM_xxx
message for a subclassed window. Only the messages added via this method will have an event fired for them.
Sub SetupShellAutoComplete(hwndTarget As Long, IsTargetComboBox As Boolean, lFlags As AUTOCOMPLETE_FLAGS)
A wrapper for SHAutoComplete
method. If IsTargetComboBox = True
, attempts to find the Edit ctl part.
Sub SetupCustomAutoComplete(hwndTarget As Long, IsTargetComboBox As Boolean, lCustomAutoCompleteFlags As Long, varStringArray)
Enables custom autocomplete using IEnumString and IAutoComplete
interfaces. varStringArray must be a BSTR array. If IsTargetComboBox = True, attempts to find the Edit control part.
Sub CustomAutoCompleteAddString(hwndTarget As Long, IsTargetComboBox As Boolean, strItem As String)
Adds a string to a previously activated custom autocomplete. Does not check for duplicates.
Sub CustomAutoCompleteEnable(hwndTarget As Long, IsTargetComboBox As Boolean, bEnable As Boolean)
Enables or disables a previously activated custom autocomplete.
Sub QueryIERegistryOption(IeRegistryOptionsFlag As Long, varBuffer)
Queries HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main for one of IE_REGISTRY_OPTIONS_FLAGS enum
varBuffer
must be an empty VARIANT.
Sub SetIERegistryOption(IeRegistryOptionsFlag As Long, varBuffer)
Uses HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main to set one of IE_REGISTRY_OPTIONS_FLAGS enum
Sub DecodeMime(byVal strToDecode As String, strDecoded As String)
Replaces MIME encoded strings. %25 -> %
Sub DeleteIEFiles(enumWhichFiles As DELETE_IE_FILES_FLAGS)
Attempts to delete IE cache or history, or cookies.
Sub FindTextSimple(wbUID As Integer, TextToFind As String, bDownward As Boolean, bMatchWholeWord As Boolean, bMatchCase As Boolean, bScrollIntoView As Boolean, FindMatch As Boolean)
Attempts to find a given text in a document. Accounts for frames and are able to continue a search. Returns an error if no matches are found.
Sub FindAndHighlightAllText(wbUID As Integer, TextToFind As String, bMatchWholeWord As Boolean, bMatchCase As Boolean, HighlightColor As String, NumOfMatchsFound
As Long)
Attempts to find and highlight all text in the active document. Accounts for frames. Color example greenyellow. NumOfMatchsFound
returns number of matches found.
Sub FindAndHighlightAllTextFrames(wbUID As Integer, TextToFind As String, bMatchWholeWord As Boolean, bMatchCase As Boolean, HighlightColor As String, NumOfMatchsFound As Long)
Attempts to find and heighlight all text in the document, including frames. Color example greenyellow. Returns number of matches found
Sub FindAnyTextMatch(wbUID As Integer, TextToFind As String, bMatchWholeWord As Boolean, bMatchCase As Boolean, FindMatch As Boolean)
Attempts to find a given text. Accounts for frames. If FindMatch
equals True
, we have a match.
If any matches are found, FindAnyTextMatchCallback
event is fired which exposes the document and the HtmlTxtRange dispatch.
Sub ucInternetCrackUrl(URL As String, bSuccess As Boolean)
Cracks URL into components. Use ucXXX
properties to access various parts of a cracked URL. Success if bSuccess
returns True
.
Sub DownloadUrlAsync(ByVal URL As String, ByVal SaveFileName As String, DLUID As Integer)
Downloads a URL target to a file asynchronously. Generates events to track the download. DLUID
is the unique ID of the instance of the class downloading the file. Normally, you can cancel a dl using events that are received, but in case of a stalled dl, we can use this ID to call CancelFileDl
to force URLMon
to abort the dl, we should get a OnFileDLCancelDownload
event afterwards.
Sub ucInternetCreateUrl(URL As String)
Uses ucXXX
various parts to create a URL.
Sub RemoveBrowser(wbUIDToRemove As Integer)
Remove web browser based on a given UID.
Sub SetFocusW(wbUID As Integer)
Sets focus to a web browser based on wbUID
.
Sub PlaceWBOnTop(wbUID As Integer)
Places Webbrowser control on top of Zorder by UI activating the it.
Function AnyDocHasFocus() As Integer
Returns the wbUID
of any Web browser that has focus or 0.
Sub NavigateSimple(wbUID As Integer), URL As String)
Navigate to URL.
Sub SetupWindowsHook(lHookType As WINDOWSHOOK_TYPES, hwndTargetWnd As Long, bStart As Boolean, lUWMHookMsgID As Long)
Installs/Uninstalls 11 different kinds of windows hooks.
hwndTargetWnd
is the handle of the window to receive hook messages in it's wndproc function.
lUWMHookMsgID
is passed to client. It contains a unique message id registered using RegisterWindowMessage
. Client application looks for this id in wndproc to intercept hook calls. To consume a hook call, client need to return 1 and indicate that the message was handled.
Sub HookProcNCode(lHookType As WINDOWSHOOK_TYPES, nCode As Long)
Enables client application to retrieve the nCode
param from three hook callback
functions. WHT_CBT, WHT_MSGFILTER, and WHT_SYSMSGFILTER
. For the rest of the windows hooks, the nCode param is meanningless.
Sub GoSearch(wbUID As Integer)
Sub Refresh2(wbUID As Integer, level)
Sub SelectAll(wbUID As Integer)
Sub Paste(wbUID As Integer)
Sub Copy(wbUID As Integer)
Sub Cut(wbUID As Integer)
Sub Undo(wbUID As Integer)
Sub Redo(wbUID As Integer)
Sub ClearSelection(wbUID As Integer)
Sub Delete(wbUID As Integer)
Sub Find(wbUID As Integer)
Sub PasteSpecial(wbUID As Integer)
Sub Spell(wbUID As Integer)
Sub Properties(wbUID As Integer)
Sub NewWindow(wbUID As Integer)
Sub FileOpen(wbUID As Integer)
Sub Save(wbUID As Integer)
Sub SaveAs(wbUID As Integer)
Sub Print(wbUID As Integer)
Sub PrintPreview(wbUID As Integer)
Sub PageSetup(wbUID As Integer)
Sub Print2(wbUID As Integer)
Sub PrintPreview2(wbUID As Integer)
Sub ViewSource(wbUID As Integer)
Sub AddToFavorites(wbUID As Integer)
Sub ViewIEOptions(wbUID As Integer)
Sub OrganizeFavorites
Note* Wrappers for OleCommandTarget->Exec, using various OLECMDID_xxx IDs. Has the same effect as using IE commands.
WebBrowser Customization
Webbrowser Control Reference for C/C++ Developers
Advanced Hosting Reference
How To Get Protocol Headers in a Pluggable Protocol Handler
SAMPLE: ATLCPImplMT encapsulates ATL event firing across COM apartments
How to handle script errors as a WebBrowser control host
About Asynchronous Pluggable Protocols
URL
Monikers Interfaces
HTML
Control API Interfaces
Implementing a Custom Download Manager
MSHTML Reference
IInternetSecurityManager
Programming with ATL and C Run-Time Code
SetupWindowsHook
HookProcNCode
FindAndHighlightAllTextFrames
SetupCustomAutoComplete
CustomAutoCompleteAddString
CustomAutoCompleteEnable
QueryIERegistryOption
SetIERegistryOption
DecodeMime
DeleteIEFiles
OnWBKeyDown
OnWBKeyUp
DocHostShowMessage
FindAnyTextMatchCallback
OnShowScriptError
IHTMLOMWindowServices
- IE6 XP sp2
DocHostUIHandler::TranslateAccelerator.
FindAndHighlightAllText
method now returns number of matches found rather than returning a
Boolean value indicating success or failure
AddBrowser
method to allow the client to open WBs in the background. By default, Browsers are opened in the background.
IDownloadManager
interface within idl. No need for downloadmgr.h
LoadHTMLFromString
, Fixed a bug that caused the base URL to be set to about:blank.
Added a new parameter sBaseUrl
to enable client to set base URL
ShowMessage
event
OnAcceletorKeys
event
WB_SCRIPT_ERROR_ACTION
enum
WB_ACCELETOR_KEYS_ACTION
enum
AcceletorKeysAction
property
ScriptErrorAction
property
Terminate
method
WBEvaluateNewWindow
IWB::GetIEServerHwnd
IWB::GetShellDocObjHwnd
IWB::GetShellEmbedding
WBDocHostUIHandler::TranslateAccelerator
OrganizeFavorites
(Thank you dosuryu)
ViewIEOptions
SourceOnDocComplete
DocumentCompleteWBEx
Terminate
method. Calling this method has no effect.
WBDocHostShowUI::ShowMessage
to use MSHTML
provided title.
LoadHtmlFromString
to be able to load buffers larger than 500 KB.
bUseIEDefault
to RegisterAsDropTarget
property.
bUseIEDefault
default value is False
bUseIEDefault
to true to use default IE drag drop behaviour
lWBDropFormat
to WBDrop
event. The value can be one of
WBPageTextSize
SaveAsBitmap
DrawWBThumbnailOnWnd
LoadHtmlFromString
DisplayCertificateDialog
ucResetFieldsToDefault
SubclassWnd
UnSubclassWnd
AddMessage
SetupShellAutoComplete
WBPostData
OnGetOptionKeyPath
OnGetOverrideKeyPath
OnWBDragEnter
OnWBDragOver
OnWBDrop
OnWBDrop2
OnWBDragLeave
OnWMMessage
OnPostDataAvailable
OnPostOnProgress
OnPostError
OnPostEnd
OnPostResponse
IDropTarget
IDocHostUIHandler2
IStream
m_StartupURL
to L"" (Thank you dosuryu).
WBHttpSecurity::OnSecurityProblem
method from RPC_E_RETRY
to S_FALSE
(Thank you folklayer).
Terminate
and RemoveBrowser
methods so as not to display any messages in regard to ref count and not to generate any COM errors if ref count of IWB
instance is greater than one.
IOleControlImpl::GetControlInfo
and added default handling of accelerator keys to ProcessWBAccelKeys
method based on KB article 187644.
optional
keyword from vbMHWB.idl file.
WM_SETFOCUS
message to pass the focus from the control to the first web browser while tabbing through controls on a dialog/form.
OnAuthentication
OnHTTPSecurityProblem
ProtocolHandlerOnBeginTransaction
ProtocolHandlerOnResponse
NewWindow3
(WinXP sp2 specific)
IOleCommandTarget::Exec
method causing certain pages to crash.
Content_Disposition
header.
CvbWB::ProcessWBAccelKeys
method to process <SELECT> tags properly.
FileDownloadEx
event:
OnFileDLRedirect
OnFileDLStartDownload
A limited functionality C# version of this control is available. These limitations are due to issues with COM threading mechanism and interop.