in response to a direct question from a forum member to explain how to prevent the default web-gadget context menus from being shown, I quickly hacked up the following code which does exactly this. It is based on some old code of Freak's I had lying around.
From MSDN :
All the code does then is implement it's own iDocHostUIHandler interface which it uses to supplement the default one provided by the webgadget. It does not replace the default implementation outright (unlike most handlers I see). This means you can pick and choose which elements of the available functionality you wish to supplement etc.MSHTML implements IDocHostUIHandler to communicate with the host about its user interface status. The host can also implement this interface to extend, replace, or disable the default UI elements, such as menus, context menus, and toolbars. When replacing or disabling elements, the host merely returns S_OK, S_FALSE, or E_NOTIMPL from most methods. When extending the user interface, the host should delegate as necessary to the default MSHTML implementation.
In the demo code provided I simply use the custom interface to prevent the context menus from being shown. You can of course choose to show your own menus instead based upon the object beneath the cursor and so on.
Code: Select all
;/////////////////////////////////////////////////////////////////////////////////
;An example of setting a custom iDocHostUIHandler interface for a web-gadget.
;This interface allows you to replace the menus, toolbars and context menus etc.
;We use it to show how to disable a webgadget's context menus.
;
;Stephen Rodriguez (srod). Based upon some code written by Freak.
;/////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////
;Most custom implementations of the iDocHostUIHandler interface simply replace the default
;implementation out-right. This implementation does not and instead falls back to the default implementation
;for those methods we are not interested in. Amongst other things this prevents certain memory leaks (apparently!)
;/////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////
Structure _IDocHostUIHandler
*vTable.i
ref.i
iDocHostUiHandler.iDocHostUiHandler
EndStructure
;/////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////
;The following function sets the specified webgadget's iDocHostUIHandler interface to a custom implementation which we must provide ourselves.
;Return a HRESULT value (#S_OK if successful).
Procedure.i SetCustomDocHostUIHandler(id, vTableAddress)
Protected result=#E_FAIL, hWnd, iBrowser.IWebBrowser2, iDispatch.IDispatch, iDocument.IHTMLDocument2, iOLE.IOleObject, iDocHostUIHandler.IDocHostUIHandler
Protected iCustomDoc.ICustomDoc, iOLEClientSite.IOleClientSite, *this._IDocHostUIHandler
hWnd = GadgetID(id)
If hWnd
iBrowser = GetWindowLong_(hWnd, #GWL_USERDATA)
If iBrowser
If iBrowser\get_Document(@iDispatch) = #S_OK
If iDispatch\QueryInterface(?IID_IHTMLDocument2, @iDocument) = #S_OK
If iDocument\QueryInterface(?IID_IOleObject, @iOLE) = #S_OK
If iOLE\GetClientSite(@iOLEClientSite) = #S_OK
If iOLEClientSite\QueryInterface(?IID_IDocHostUIHandler, @iDocHostUIHandler) = #S_OK
If iDocument\QueryInterface(?IID_ICustomDoc, @iCustomDoc) = #S_OK
*this = AllocateMemory(SizeOf(_IDocHostUIHandler))
If *this
*this\vTable = vTableAddress
*this\iDocHostUiHandler = iDocHostUIHandler
iCustomDoc\SetUIHandler(*this)
result = #S_OK
Else
iDocHostUIHandler\Release()
EndIf
iCustomDoc\Release()
Else
iDocHostUIHandler\Release()
EndIf
EndIf
IOleClientSite\Release()
EndIf
iOLE\Release()
EndIf
iDocument\Release()
EndIf
iDispatch\Release()
EndIf
EndIf
EndIf
ProcedureReturn result
EndProcedure
;/////////////////////////////////////////////////////////////////////////////////
;-TEST CODE.
;/////////////////////////////////////////////////////////////////////////////////
If OpenWindow(0, 0, 0, 600, 600, "WebGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
WebGadget(0, 10, 10, 600, 600, "http://www.google.com")
;Here we set our custom iDocHostUIHandler interface. Below this code is our custom implementation for this interface.
;We prevent the context menus from being displayed by simply returning #S_OK from the ShowContextMenu() method.
;All other methods (except the iUnknown ones) simply call the default iDocHostUIHandler methods.
SetCustomDocHostUIHandler(0, ?IDocHostUIHandlerFunctionTable)
Repeat
Event = WaitWindowEvent();
Select Event
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
EndIf
End
;/////////////////////////////////////////////////////////////////////////////////
;-CUSTOM iDocHostUIHandler IMPLEMENTATION.
;/////////////////////////////////////////////////////////////////////////////////
;iUnknown.
Procedure.i IDocHostUIHandler_QueryInterface(*this._IDocHostUIHandler, riid, *ppObj.INTEGER)
Protected hResult = #E_NOINTERFACE, iunk.iUnknown
If *ppObj And riid
*ppObj\i = 0
If CompareMemory(riid, ?IID_IUnknown, SizeOf(IID)) Or CompareMemory(riid, ?IID_IDocHostUIHandler, SizeOf(IID))
*ppObj\i = *this
*this\ref+1
hResult = #S_OK
EndIf
EndIf
ProcedureReturn hResult
EndProcedure
;iUnknown.
Procedure.i IDocHostUIHandler_AddRef(*this._IDocHostUIHandler)
*this\ref = *this\ref + 1
ProcedureReturn *this\ref
EndProcedure
;iUnknown.
Procedure.i IDocHostUIHandler_Release(*this._IDocHostUIHandler)
Protected refCount
*this\ref = *this\ref - 1
refCount = *this\ref
If *this\ref = 0
*this\iDocHostUiHandler\Release()
FreeMemory(*this)
EndIf
ProcedureReturn refCount
EndProcedure
;Return #S_FALSE to show the default context menus.
Procedure.i IDocHostUIHandler_ShowContextMenu(*this._IDocHostUIHandler, dwID, ppt, pcmdTarget, pdispReserved)
Debug "Context menu prohibited!"
ProcedureReturn #S_OK
EndProcedure
Procedure.i IDocHostUIHandler_GetHostInfo(*this._IDocHostUIHandler, *pInfo)
ProcedureReturn *this\iDocHostUiHandler\GetHostInfo(*pInfo)
EndProcedure
Procedure.i IDocHostUIHandler_ShowUI(*this._IDocHostUIHandler, dwID, pActiveObject, pCommandTarget, pFrame, pDoc)
ProcedureReturn *this\iDocHostUiHandler\ShowUI(dwID, pActiveObject, pCommandTarget, pFrame, pDoc)
EndProcedure
Procedure.i IDocHostUIHandler_HideUI(*this._IDocHostUIHandler)
ProcedureReturn *this\iDocHostUiHandler\HideUI()
EndProcedure
Procedure.i IDocHostUIHandler_UpdateUI(*this._IDocHostUIHandler)
ProcedureReturn *this\iDocHostUiHandler\UpdateUI()
EndProcedure
Procedure.i IDocHostUIHandler_EnableModeless(*this._IDocHostUIHandler, fEnable)
ProcedureReturn *this\iDocHostUiHandler\EnableModeless(fEnable)
EndProcedure
Procedure.i IDocHostUIHandler_OnDocWindowActivate(*this._IDocHostUIHandler, fActivate)
ProcedureReturn *this\iDocHostUiHandler\OnDocWindowActivate(fActivate)
EndProcedure
Procedure.i IDocHostUIHandler_OnFrameWindowActivate(*this._IDocHostUIHandler, fActivate)
ProcedureReturn *this\iDocHostUiHandler\OnFrameWindowActivate(fActivate)
EndProcedure
Procedure.i IDocHostUIHandler_ResizeBorder(*this._IDocHostUIHandler, prcBorder, pUIWindow, fFrameWindow)
ProcedureReturn *this\iDocHostUiHandler\ResizeBorder(prcBorder, pUIWindow, fFrameWindow)
EndProcedure
Procedure.i IDocHostUIHandler_TranslateAccelerator(*this._IDocHostUIHandler, lpMsg, pguidCmdGroup, nCmdID)
ProcedureReturn *this\iDocHostUiHandler\TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID)
EndProcedure
Procedure.i IDocHostUIHandler_GetOptionKeyPath(*this._IDocHostUIHandler, pchKey, dw)
ProcedureReturn *this\iDocHostUiHandler\GetOptionKeyPath(pchKey, dw)
EndProcedure
Procedure.i IDocHostUIHandler_GetDropTarget(*this._IDocHostUIHandler, pDropTarget, ppDropTarget)
ProcedureReturn *this\iDocHostUiHandler\GetDropTarget(pDropTarget, ppDropTarget)
EndProcedure
Procedure.i IDocHostUIHandler_GetExternal(*this._IDocHostUIHandler, ppDispatch.i)
ProcedureReturn *this\iDocHostUiHandler\GetExternal(ppDispatch.i)
EndProcedure
Procedure.i IDocHostUIHandler_TranslateUrl(*this._IDocHostUIHandler, dwTranslate, pchURLIn, ppchURLOut)
ProcedureReturn *this\iDocHostUiHandler\TranslateUrl(dwTranslate, pchURLIn, ppchURLOut)
EndProcedure
Procedure.i IDocHostUIHandler_FilterDataObject(*this._IDocHostUIHandler, pDO, ppDORet)
ProcedureReturn *this\iDocHostUiHandler\FilterDataObject(pDO, ppDORet)
EndProcedure
DataSection
IID_IUnknown: ; 00000000-0000-0000-C000-000000000046
Data.l $00000000
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
IID_IHTMLDocument2: ; 332C4425-26CB-11D0-B483-00C04FD90119
Data.l $332C4425
Data.w $26CB, $11D0
Data.b $B4, $83, $00, $C0, $4F, $D9, $01, $19
IID_IOleObject: ; 00000112-0000-0000-C000-000000000046
Data.l $00000112
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
IID_IDocHostUIHandler: ; BD3F23C0-D43E-11CF-893B-00AA00BDCE1A
Data.l $BD3F23C0
Data.w $D43E, $11CF
Data.b $89, $3B, $00, $AA, $00, $BD, $CE, $1A
IID_ICustomDoc: ; 3050F3F0-98B5-11CF-BB82-00AA00BDCE0B
Data.l $3050F3F0
Data.w $98B5, $11CF
Data.b $BB, $82, $00, $AA, $00, $BD, $CE, $0B
IDocHostUIHandlerFunctionTable:
Data.i @IDocHostUIHandler_QueryInterface()
Data.i @IDocHostUIHandler_AddRef()
Data.i @IDocHostUIHandler_Release()
Data.i @IDocHostUIHandler_ShowContextMenu()
Data.i @IDocHostUIHandler_GetHostInfo()
Data.i @IDocHostUIHandler_ShowUI()
Data.i @IDocHostUIHandler_HideUI()
Data.i @IDocHostUIHandler_UpdateUI()
Data.i @IDocHostUIHandler_EnableModeless()
Data.i @IDocHostUIHandler_OnDocWindowActivate()
Data.i @IDocHostUIHandler_OnFrameWindowActivate()
Data.i @IDocHostUIHandler_ResizeBorder()
Data.i @IDocHostUIHandler_TranslateAccelerator()
Data.i @IDocHostUIHandler_GetOptionKeyPath()
Data.i @IDocHostUIHandler_GetDropTarget()
Data.i @IDocHostUIHandler_GetExternal()
Data.i @IDocHostUIHandler_TranslateUrl()
Data.i @IDocHostUIHandler_FilterDataObject()
EndDataSection
;/////////////////////////////////////////////////////////////////////////////////