summaryrefslogtreecommitdiff
path: root/plugins/IMO2sProxy/src/imo2skype/w32browser.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/IMO2sProxy/src/imo2skype/w32browser.c')
-rw-r--r--plugins/IMO2sProxy/src/imo2skype/w32browser.c1143
1 files changed, 1143 insertions, 0 deletions
diff --git a/plugins/IMO2sProxy/src/imo2skype/w32browser.c b/plugins/IMO2sProxy/src/imo2skype/w32browser.c
new file mode 100644
index 0000000000..8053a3c16d
--- /dev/null
+++ b/plugins/IMO2sProxy/src/imo2skype/w32browser.c
@@ -0,0 +1,1143 @@
+/* Module: win32_browsewnd.c
+ Purpose: Displays a window with an embedded browser in order to display the Voicechat
+ flash from imo.im
+ This example is bsaed on the work of Jeff Glatt (http://www.codeproject.com/KB/COM/cwebpage.aspx?msg=2852721)
+ Author: leecher, credits go to Jeff Glatt for his excellent work.
+ Date: 18.10.2009
+*/
+
+#include <windows.h>
+#include <exdisp.h>
+#include <mshtml.h>
+#include <mshtmhst.h>
+#include <process.h>
+#include "memlist.h"
+#include "w32browser.h"
+
+#ifndef _WIN64
+#if WINVER<0x0500
+#define SetWindowLongPtr SetWindowLong
+#define GetWindowLongPtr GetWindowLong
+#endif
+#ifndef LONG_PTR
+#define LONG_PTR LONG
+#endif
+#ifndef GWLP_USERDATA
+#define GWLP_USERDATA GWL_USERDATA
+#endif
+#endif
+
+static const SAFEARRAYBOUND ArrayBound = {1, 0};
+static TYP_LIST *m_hWindows = NULL;
+static DWORD m_dwThread = 0;
+static HANDLE m_hThread = NULL, m_hEvent = NULL;
+
+
+HRESULT STDMETHODCALLTYPE Frame_QueryInterface(IOleInPlaceFrame FAR* This, REFIID riid, LPVOID FAR* ppvObj);
+HRESULT STDMETHODCALLTYPE Frame_AddRef(IOleInPlaceFrame FAR* This);
+HRESULT STDMETHODCALLTYPE Frame_Release(IOleInPlaceFrame FAR* This);
+HRESULT STDMETHODCALLTYPE Frame_GetWindow(IOleInPlaceFrame FAR* This, HWND FAR* lphwnd);
+HRESULT STDMETHODCALLTYPE Frame_ContextSensitiveHelp(IOleInPlaceFrame FAR* This, BOOL fEnterMode);
+HRESULT STDMETHODCALLTYPE Frame_GetBorder(IOleInPlaceFrame FAR* This, LPRECT lprectBorder);
+HRESULT STDMETHODCALLTYPE Frame_RequestBorderSpace(IOleInPlaceFrame FAR* This, LPCBORDERWIDTHS pborderwidths);
+HRESULT STDMETHODCALLTYPE Frame_SetBorderSpace(IOleInPlaceFrame FAR* This, LPCBORDERWIDTHS pborderwidths);
+HRESULT STDMETHODCALLTYPE Frame_SetActiveObject(IOleInPlaceFrame FAR* This, IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName);
+HRESULT STDMETHODCALLTYPE Frame_InsertMenus(IOleInPlaceFrame FAR* This, HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);
+HRESULT STDMETHODCALLTYPE Frame_SetMenu(IOleInPlaceFrame FAR* This, HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject);
+HRESULT STDMETHODCALLTYPE Frame_RemoveMenus(IOleInPlaceFrame FAR* This, HMENU hmenuShared);
+HRESULT STDMETHODCALLTYPE Frame_SetStatusText(IOleInPlaceFrame FAR* This, LPCOLESTR pszStatusText);
+HRESULT STDMETHODCALLTYPE Frame_EnableModeless(IOleInPlaceFrame FAR* This, BOOL fEnable);
+HRESULT STDMETHODCALLTYPE Frame_TranslateAccelerator(IOleInPlaceFrame FAR* This, LPMSG lpmsg, WORD wID);
+
+IOleInPlaceFrameVtbl MyIOleInPlaceFrameTable = {Frame_QueryInterface,
+Frame_AddRef,
+Frame_Release,
+Frame_GetWindow,
+Frame_ContextSensitiveHelp,
+Frame_GetBorder,
+Frame_RequestBorderSpace,
+Frame_SetBorderSpace,
+Frame_SetActiveObject,
+Frame_InsertMenus,
+Frame_SetMenu,
+Frame_RemoveMenus,
+Frame_SetStatusText,
+Frame_EnableModeless,
+Frame_TranslateAccelerator};
+
+typedef struct {
+ IOleInPlaceFrame frame;
+ HWND window;
+} _IOleInPlaceFrameEx;
+
+HRESULT STDMETHODCALLTYPE Site_QueryInterface(IOleClientSite FAR* This, REFIID riid, void ** ppvObject);
+HRESULT STDMETHODCALLTYPE Site_AddRef(IOleClientSite FAR* This);
+HRESULT STDMETHODCALLTYPE Site_Release(IOleClientSite FAR* This);
+HRESULT STDMETHODCALLTYPE Site_SaveObject(IOleClientSite FAR* This);
+HRESULT STDMETHODCALLTYPE Site_GetMoniker(IOleClientSite FAR* This, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker ** ppmk);
+HRESULT STDMETHODCALLTYPE Site_GetContainer(IOleClientSite FAR* This, LPOLECONTAINER FAR* ppContainer);
+HRESULT STDMETHODCALLTYPE Site_ShowObject(IOleClientSite FAR* This);
+HRESULT STDMETHODCALLTYPE Site_OnShowWindow(IOleClientSite FAR* This, BOOL fShow);
+HRESULT STDMETHODCALLTYPE Site_RequestNewObjectLayout(IOleClientSite FAR* This);
+
+IOleClientSiteVtbl MyIOleClientSiteTable = {Site_QueryInterface,
+Site_AddRef,
+Site_Release,
+Site_SaveObject,
+Site_GetMoniker,
+Site_GetContainer,
+Site_ShowObject,
+Site_OnShowWindow,
+Site_RequestNewObjectLayout};
+
+HRESULT STDMETHODCALLTYPE UI_QueryInterface(IDocHostUIHandler FAR* This, REFIID riid, void ** ppvObject);
+HRESULT STDMETHODCALLTYPE UI_AddRef(IDocHostUIHandler FAR* This);
+HRESULT STDMETHODCALLTYPE UI_Release(IDocHostUIHandler FAR* This);
+HRESULT STDMETHODCALLTYPE UI_ShowContextMenu(IDocHostUIHandler FAR* This, DWORD dwID, POINT __RPC_FAR *ppt, IUnknown __RPC_FAR *pcmdtReserved, IDispatch __RPC_FAR *pdispReserved);
+HRESULT STDMETHODCALLTYPE UI_GetHostInfo(IDocHostUIHandler FAR* This, DOCHOSTUIINFO __RPC_FAR *pInfo);
+HRESULT STDMETHODCALLTYPE UI_ShowUI(IDocHostUIHandler FAR* This, DWORD dwID, IOleInPlaceActiveObject __RPC_FAR *pActiveObject, IOleCommandTarget __RPC_FAR *pCommandTarget, IOleInPlaceFrame __RPC_FAR *pFrame, IOleInPlaceUIWindow __RPC_FAR *pDoc);
+HRESULT STDMETHODCALLTYPE UI_HideUI(IDocHostUIHandler FAR* This);
+HRESULT STDMETHODCALLTYPE UI_UpdateUI(IDocHostUIHandler FAR* This);
+HRESULT STDMETHODCALLTYPE UI_EnableModeless(IDocHostUIHandler FAR* This, BOOL fEnable);
+HRESULT STDMETHODCALLTYPE UI_OnDocWindowActivate(IDocHostUIHandler FAR* This, BOOL fActivate);
+HRESULT STDMETHODCALLTYPE UI_OnFrameWindowActivate(IDocHostUIHandler FAR* This, BOOL fActivate);
+HRESULT STDMETHODCALLTYPE UI_ResizeBorder(IDocHostUIHandler FAR* This, LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR *pUIWindow, BOOL fRameWindow);
+HRESULT STDMETHODCALLTYPE UI_TranslateAccelerator(IDocHostUIHandler FAR* This, LPMSG lpMsg, const GUID __RPC_FAR *pguidCmdGroup, DWORD nCmdID);
+HRESULT STDMETHODCALLTYPE UI_GetOptionKeyPath(IDocHostUIHandler FAR* This, LPOLESTR __RPC_FAR *pchKey, DWORD dw);
+HRESULT STDMETHODCALLTYPE UI_GetDropTarget(IDocHostUIHandler FAR* This, IDropTarget __RPC_FAR *pDropTarget, IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget);
+HRESULT STDMETHODCALLTYPE UI_GetExternal(IDocHostUIHandler FAR* This, IDispatch __RPC_FAR *__RPC_FAR *ppDispatch);
+HRESULT STDMETHODCALLTYPE UI_TranslateUrl(IDocHostUIHandler FAR* This, DWORD dwTranslate, OLECHAR __RPC_FAR *pchURLIn, OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut);
+HRESULT STDMETHODCALLTYPE UI_FilterDataObject(IDocHostUIHandler FAR* This, IDataObject __RPC_FAR *pDO, IDataObject __RPC_FAR *__RPC_FAR *ppDORet);
+
+IDocHostUIHandlerVtbl MyIDocHostUIHandlerTable = {UI_QueryInterface,
+UI_AddRef,
+UI_Release,
+UI_ShowContextMenu,
+UI_GetHostInfo,
+UI_ShowUI,
+UI_HideUI,
+UI_UpdateUI,
+UI_EnableModeless,
+UI_OnDocWindowActivate,
+UI_OnFrameWindowActivate,
+UI_ResizeBorder,
+UI_TranslateAccelerator,
+UI_GetOptionKeyPath,
+UI_GetDropTarget,
+UI_GetExternal,
+UI_TranslateUrl,
+UI_FilterDataObject};
+
+HRESULT STDMETHODCALLTYPE InPlace_QueryInterface(IOleInPlaceSite FAR* This, REFIID riid, void ** ppvObject);
+HRESULT STDMETHODCALLTYPE InPlace_AddRef(IOleInPlaceSite FAR* This);
+HRESULT STDMETHODCALLTYPE InPlace_Release(IOleInPlaceSite FAR* This);
+HRESULT STDMETHODCALLTYPE InPlace_GetWindow(IOleInPlaceSite FAR* This, HWND FAR* lphwnd);
+HRESULT STDMETHODCALLTYPE InPlace_ContextSensitiveHelp(IOleInPlaceSite FAR* This, BOOL fEnterMode);
+HRESULT STDMETHODCALLTYPE InPlace_CanInPlaceActivate(IOleInPlaceSite FAR* This);
+HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceActivate(IOleInPlaceSite FAR* This);
+HRESULT STDMETHODCALLTYPE InPlace_OnUIActivate(IOleInPlaceSite FAR* This);
+HRESULT STDMETHODCALLTYPE InPlace_GetWindowContext(IOleInPlaceSite FAR* This, LPOLEINPLACEFRAME FAR* lplpFrame,LPOLEINPLACEUIWINDOW FAR* lplpDoc,LPRECT lprcPosRect,LPRECT lprcClipRect,LPOLEINPLACEFRAMEINFO lpFrameInfo);
+HRESULT STDMETHODCALLTYPE InPlace_Scroll(IOleInPlaceSite FAR* This, SIZE scrollExtent);
+HRESULT STDMETHODCALLTYPE InPlace_OnUIDeactivate(IOleInPlaceSite FAR* This, BOOL fUndoable);
+HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceDeactivate(IOleInPlaceSite FAR* This);
+HRESULT STDMETHODCALLTYPE InPlace_DiscardUndoState(IOleInPlaceSite FAR* This);
+HRESULT STDMETHODCALLTYPE InPlace_DeactivateAndUndo(IOleInPlaceSite FAR* This);
+HRESULT STDMETHODCALLTYPE InPlace_OnPosRectChange(IOleInPlaceSite FAR* This, LPCRECT lprcPosRect);
+
+IOleInPlaceSiteVtbl MyIOleInPlaceSiteTable = {InPlace_QueryInterface,
+InPlace_AddRef,
+InPlace_Release,
+InPlace_GetWindow,
+InPlace_ContextSensitiveHelp,
+InPlace_CanInPlaceActivate,
+InPlace_OnInPlaceActivate,
+InPlace_OnUIActivate,
+InPlace_GetWindowContext,
+InPlace_Scroll,
+InPlace_OnUIDeactivate,
+InPlace_OnInPlaceDeactivate,
+InPlace_DiscardUndoState,
+InPlace_DeactivateAndUndo,
+InPlace_OnPosRectChange};
+
+typedef struct {
+ IOleInPlaceSite inplace;
+ _IOleInPlaceFrameEx frame;
+} _IOleInPlaceSiteEx;
+
+typedef struct {
+ IDocHostUIHandler ui;
+} _IDocHostUIHandlerEx;
+
+typedef struct {
+ IOleClientSite client;
+ _IOleInPlaceSiteEx inplace;
+ _IDocHostUIHandlerEx ui;
+} _IOleClientSiteEx;
+
+#define NOTIMPLEMENTED return(E_NOTIMPL)
+
+typedef struct
+{
+ char *pszHTML;
+ char *pszTitle;
+ int width;
+ int height;
+ HWND hWnd; // out
+} ShowIEWndParam;
+
+
+//////////////////////////////////// My IDocHostUIHandler functions //////////////////////////////////////
+//
+HRESULT STDMETHODCALLTYPE UI_QueryInterface(IDocHostUIHandler FAR* This, REFIID riid, LPVOID FAR* ppvObj)
+{
+ return(Site_QueryInterface((IOleClientSite *)((char *)This - sizeof(IOleClientSite) - sizeof(_IOleInPlaceSiteEx)), riid, ppvObj));
+}
+
+HRESULT STDMETHODCALLTYPE UI_AddRef(IDocHostUIHandler FAR* This)
+{
+ return(1);
+}
+
+HRESULT STDMETHODCALLTYPE UI_Release(IDocHostUIHandler FAR* This)
+{
+ return(1);
+}
+
+HRESULT STDMETHODCALLTYPE UI_ShowContextMenu(IDocHostUIHandler FAR* This, DWORD dwID, POINT __RPC_FAR *ppt, IUnknown __RPC_FAR *pcmdtReserved, IDispatch __RPC_FAR *pdispReserved)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE UI_GetHostInfo(IDocHostUIHandler FAR* This, DOCHOSTUIINFO __RPC_FAR *pInfo)
+{
+ pInfo->cbSize = sizeof(DOCHOSTUIINFO);
+ pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER;
+ pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE UI_ShowUI(IDocHostUIHandler FAR* This, DWORD dwID, IOleInPlaceActiveObject __RPC_FAR *pActiveObject, IOleCommandTarget __RPC_FAR *pCommandTarget, IOleInPlaceFrame __RPC_FAR *pFrame, IOleInPlaceUIWindow __RPC_FAR *pDoc)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE UI_HideUI(IDocHostUIHandler FAR* This)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE UI_UpdateUI(IDocHostUIHandler FAR* This)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE UI_EnableModeless(IDocHostUIHandler FAR* This, BOOL fEnable)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE UI_OnDocWindowActivate(IDocHostUIHandler FAR* This, BOOL fActivate)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE UI_OnFrameWindowActivate(IDocHostUIHandler FAR* This, BOOL fActivate)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE UI_ResizeBorder(IDocHostUIHandler FAR* This, LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR *pUIWindow, BOOL fRameWindow)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE UI_TranslateAccelerator(IDocHostUIHandler FAR* This, LPMSG lpMsg, const GUID __RPC_FAR *pguidCmdGroup, DWORD nCmdID)
+{
+ return(S_FALSE);
+}
+
+HRESULT STDMETHODCALLTYPE UI_GetOptionKeyPath(IDocHostUIHandler FAR* This, LPOLESTR __RPC_FAR *pchKey, DWORD dw)
+{
+ return(S_FALSE);
+}
+
+HRESULT STDMETHODCALLTYPE UI_GetDropTarget(IDocHostUIHandler FAR* This, IDropTarget __RPC_FAR *pDropTarget, IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget)
+{
+ return(S_FALSE);
+}
+
+HRESULT STDMETHODCALLTYPE UI_GetExternal(IDocHostUIHandler FAR* This, IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
+{
+ *ppDispatch = 0;
+ return(S_FALSE);
+}
+
+HRESULT STDMETHODCALLTYPE UI_TranslateUrl(IDocHostUIHandler FAR* This, DWORD dwTranslate, OLECHAR __RPC_FAR *pchURLIn, OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut)
+{
+ *ppchURLOut = 0;
+ return(S_FALSE);
+}
+
+HRESULT STDMETHODCALLTYPE UI_FilterDataObject(IDocHostUIHandler FAR* This, IDataObject __RPC_FAR *pDO, IDataObject __RPC_FAR *__RPC_FAR *ppDORet)
+{
+ *ppDORet = 0;
+ return(S_FALSE);
+}
+
+////////////////////////////////////// My IOleClientSite functions /////////////////////////////////////
+//
+
+HRESULT STDMETHODCALLTYPE Site_QueryInterface(IOleClientSite FAR* This, REFIID riid, void ** ppvObject)
+{
+ if (!memcmp(riid, &IID_IUnknown, sizeof(GUID)) || !memcmp(riid, &IID_IOleClientSite, sizeof(GUID)))
+ *ppvObject = &((_IOleClientSiteEx *)This)->client;
+ else if (!memcmp(riid, &IID_IOleInPlaceSite, sizeof(GUID)))
+ *ppvObject = &((_IOleClientSiteEx *)This)->inplace;
+ else if (!memcmp(riid, &IID_IDocHostUIHandler, sizeof(GUID)))
+ *ppvObject = &((_IOleClientSiteEx *)This)->ui;
+ else
+ {
+ *ppvObject = 0;
+ return(E_NOINTERFACE);
+ }
+
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE Site_AddRef(IOleClientSite FAR* This)
+{
+ return(1);
+}
+
+HRESULT STDMETHODCALLTYPE Site_Release(IOleClientSite FAR* This)
+{
+ return(1);
+}
+
+HRESULT STDMETHODCALLTYPE Site_SaveObject(IOleClientSite FAR* This)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Site_GetMoniker(IOleClientSite FAR* This, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker ** ppmk)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Site_GetContainer(IOleClientSite FAR* This, LPOLECONTAINER FAR* ppContainer)
+{
+ *ppContainer = 0;
+
+ return(E_NOINTERFACE);
+}
+
+HRESULT STDMETHODCALLTYPE Site_ShowObject(IOleClientSite FAR* This)
+{
+ return(NOERROR);
+}
+
+HRESULT STDMETHODCALLTYPE Site_OnShowWindow(IOleClientSite FAR* This, BOOL fShow)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Site_RequestNewObjectLayout(IOleClientSite FAR* This)
+{
+ NOTIMPLEMENTED;
+}
+
+
+////////////////////////////////////// My IOleInPlaceSite functions /////////////////////////////////////
+//
+HRESULT STDMETHODCALLTYPE InPlace_QueryInterface(IOleInPlaceSite FAR* This, REFIID riid, LPVOID FAR* ppvObj)
+{
+ return(Site_QueryInterface((IOleClientSite *)((char *)This - sizeof(IOleClientSite)), riid, ppvObj));
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_AddRef(IOleInPlaceSite FAR* This)
+{
+ return(1);
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_Release(IOleInPlaceSite FAR* This)
+{
+ return(1);
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_GetWindow(IOleInPlaceSite FAR* This, HWND FAR* lphwnd)
+{
+ *lphwnd = ((_IOleInPlaceSiteEx FAR*)This)->frame.window;
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_ContextSensitiveHelp(IOleInPlaceSite FAR* This, BOOL fEnterMode)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_CanInPlaceActivate(IOleInPlaceSite FAR* This)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceActivate(IOleInPlaceSite FAR* This)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_OnUIActivate(IOleInPlaceSite FAR* This)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_GetWindowContext(IOleInPlaceSite FAR* This, LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+ *lplpFrame = (LPOLEINPLACEFRAME)&((_IOleInPlaceSiteEx *)This)->frame;
+ *lplpDoc = 0;
+
+ lpFrameInfo->fMDIApp = FALSE;
+ lpFrameInfo->hwndFrame = ((_IOleInPlaceFrameEx *)*lplpFrame)->window;
+ lpFrameInfo->haccel = 0;
+ lpFrameInfo->cAccelEntries = 0;
+
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_Scroll(IOleInPlaceSite FAR* This, SIZE scrollExtent)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_OnUIDeactivate(IOleInPlaceSite FAR* This, BOOL fUndoable)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceDeactivate(IOleInPlaceSite FAR* This)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_DiscardUndoState(IOleInPlaceSite FAR* This)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_DeactivateAndUndo(IOleInPlaceSite FAR* This)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE InPlace_OnPosRectChange(IOleInPlaceSite FAR* This, LPCRECT lprcPosRect)
+{
+ IOleObject *browserObject;
+ IOleInPlaceObject *inplace;
+
+ browserObject = *((IOleObject **)((char *)This - sizeof(IOleObject *) - sizeof(IOleClientSite)));
+ if (!browserObject->lpVtbl->QueryInterface(browserObject, &IID_IOleInPlaceObject, (void**)&inplace))
+ {
+ inplace->lpVtbl->SetObjectRects(inplace, lprcPosRect, lprcPosRect);
+ inplace->lpVtbl->Release(inplace);
+ }
+
+ return(S_OK);
+}
+
+
+
+////////////////////////////////////// My IOleInPlaceFrame functions /////////////////////////////////////////
+//
+HRESULT STDMETHODCALLTYPE Frame_QueryInterface(IOleInPlaceFrame FAR* This, REFIID riid, LPVOID FAR* ppvObj)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Frame_AddRef(IOleInPlaceFrame FAR* This)
+{
+ return(1);
+}
+
+HRESULT STDMETHODCALLTYPE Frame_Release(IOleInPlaceFrame FAR* This)
+{
+ return(1);
+}
+
+HRESULT STDMETHODCALLTYPE Frame_GetWindow(IOleInPlaceFrame FAR* This, HWND FAR* lphwnd)
+{
+ *lphwnd = ((_IOleInPlaceFrameEx *)This)->window;
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE Frame_ContextSensitiveHelp(IOleInPlaceFrame FAR* This, BOOL fEnterMode)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Frame_GetBorder(IOleInPlaceFrame FAR* This, LPRECT lprectBorder)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Frame_RequestBorderSpace(IOleInPlaceFrame FAR* This, LPCBORDERWIDTHS pborderwidths)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Frame_SetBorderSpace(IOleInPlaceFrame FAR* This, LPCBORDERWIDTHS pborderwidths)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Frame_SetActiveObject(IOleInPlaceFrame FAR* This, IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE Frame_InsertMenus(IOleInPlaceFrame FAR* This, HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Frame_SetMenu(IOleInPlaceFrame FAR* This, HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE Frame_RemoveMenus(IOleInPlaceFrame FAR* This, HMENU hmenuShared)
+{
+ NOTIMPLEMENTED;
+}
+
+HRESULT STDMETHODCALLTYPE Frame_SetStatusText(IOleInPlaceFrame FAR* This, LPCOLESTR pszStatusText)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE Frame_EnableModeless(IOleInPlaceFrame FAR* This, BOOL fEnable)
+{
+ return(S_OK);
+}
+
+HRESULT STDMETHODCALLTYPE Frame_TranslateAccelerator(IOleInPlaceFrame FAR* This, LPMSG lpmsg, WORD wID)
+{
+ NOTIMPLEMENTED;
+}
+
+
+
+
+/*************************** UnEmbedBrowserObject() ************************
+ * Called to detach the browser object from our host window, and free its
+ * resources, right before we destroy our window.
+ *
+ * hwnd = Handle to the window hosting the browser object.
+ *
+ * NOTE: The pointer to the browser object must have been stored in the
+ * window's USERDATA field. In other words, don't call UnEmbedBrowserObject().
+ * with a HWND that wasn't successfully passed to EmbedBrowserObject().
+ */
+
+void UnEmbedBrowserObject(HWND hwnd)
+{
+ IOleObject **browserHandle;
+ IOleObject *browserObject;
+
+ // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
+ // we initially attached the browser object to this window.
+ if ((browserHandle = (IOleObject **)GetWindowLongPtr(hwnd, GWLP_USERDATA)))
+ {
+ // Unembed the browser object, and release its resources.
+ browserObject = *browserHandle;
+ browserObject->lpVtbl->Close(browserObject, OLECLOSE_NOSAVE);
+ browserObject->lpVtbl->Release(browserObject);
+
+ GlobalFree(browserHandle);
+
+ return;
+ }
+}
+
+
+/******************************* DisplayHTMLStr() ****************************
+ * Takes a string containing some HTML BODY, and displays it in the specified
+ * window. For example, perhaps you want to display the HTML text of...
+ *
+ * <P>This is a picture.<P><IMG src="mypic.jpg">
+ *
+ * hwnd = Handle to the window hosting the browser object.
+ * string = Pointer to nul-terminated string containing the HTML BODY.
+ * (NOTE: No <BODY></BODY> tags are required in the string).
+ *
+ * RETURNS: 0 if success, or non-zero if an error.
+ *
+ * NOTE: EmbedBrowserObject() must have been successfully called once with the
+ * specified window, prior to calling this function. You need call
+ * EmbedBrowserObject() once only, and then you can make multiple calls to
+ * this function to display numerous pages in the specified window.
+ */
+
+long DisplayHTMLStr(HWND hwnd, LPCTSTR string)
+{
+ IWebBrowser2 *webBrowser2;
+ LPDISPATCH lpDispatch;
+ IHTMLDocument2 *htmlDoc2;
+ IOleObject *browserObject;
+ SAFEARRAY *sfArray;
+ VARIANT myURL;
+ VARIANT *pVar;
+ BSTR bstr;
+
+ // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
+ // we initially attached the browser object to this window.
+ browserObject = *((IOleObject **)GetWindowLongPtr(hwnd, GWLP_USERDATA));
+
+ // Assume an error.
+ bstr = 0;
+
+ // We want to get the base address (ie, a pointer) to the IWebBrowser2 object embedded within the browser
+ // object, so we can call some of the functions in the former's table.
+ if (!browserObject->lpVtbl->QueryInterface(browserObject, &IID_IWebBrowser2, (void**)&webBrowser2))
+ {
+ // Ok, now the pointer to our IWebBrowser2 object is in 'webBrowser2', and so its VTable is
+ // webBrowser2->lpVtbl.
+
+ // Before we can get_Document(), we actually need to have some HTML page loaded in the browser. So,
+ // let's load an empty HTML page. Then, once we have that empty page, we can get_Document() and
+ // write() to stuff our HTML string into it.
+ VariantInit(&myURL);
+ myURL.vt = VT_BSTR;
+ myURL.bstrVal = SysAllocString(L"about:blank");
+
+ // Call the Navigate2() function to actually display the page.
+ webBrowser2->lpVtbl->Navigate2(webBrowser2, &myURL, 0, 0, 0, 0);
+
+ // Free any resources (including the BSTR).
+ VariantClear(&myURL);
+
+ // Call the IWebBrowser2 object's get_Document so we can get its DISPATCH object. I don't know why you
+ // don't get the DISPATCH object via the browser object's QueryInterface(), but you don't.
+ if (!webBrowser2->lpVtbl->get_Document(webBrowser2, &lpDispatch))
+ {
+ // We want to get a pointer to the IHTMLDocument2 object embedded within the DISPATCH
+ // object, so we can call some of the functions in the former's table.
+ if (!lpDispatch->lpVtbl->QueryInterface(lpDispatch, &IID_IHTMLDocument2, (void**)&htmlDoc2))
+ {
+ // Ok, now the pointer to our IHTMLDocument2 object is in 'htmlDoc2', and so its VTable is
+ // htmlDoc2->lpVtbl.
+
+ // Our HTML must be in the form of a BSTR. And it must be passed to write() in an
+ // array of "VARIENT" structs. So let's create all that.
+ if ((sfArray = SafeArrayCreate(VT_VARIANT, 1, (SAFEARRAYBOUND *)&ArrayBound)))
+ {
+ if (!SafeArrayAccessData(sfArray, (void**)&pVar))
+ {
+ pVar->vt = VT_BSTR;
+#ifndef UNICODE
+ {
+ wchar_t *buffer;
+ DWORD size;
+
+ size = MultiByteToWideChar(CP_ACP, 0, string, -1, 0, 0);
+ if (!(buffer = (wchar_t *)GlobalAlloc(GMEM_FIXED, sizeof(wchar_t) * size))) goto bad;
+ MultiByteToWideChar(CP_ACP, 0, string, -1, buffer, size);
+ bstr = SysAllocString(buffer);
+ GlobalFree(buffer);
+ }
+#else
+ bstr = SysAllocString(string);
+#endif
+ // Store our BSTR pointer in the VARIENT.
+ if ((pVar->bstrVal = bstr))
+ {
+ htmlDoc2->lpVtbl->clear(htmlDoc2);
+ // Pass the VARIENT with its BSTR to write() in order to shove our desired HTML string
+ // into the body of that empty page we created above.
+ htmlDoc2->lpVtbl->write(htmlDoc2, sfArray);
+
+ // Close the document. If we don't do this, subsequent calls to DisplayHTMLStr
+ // would append to the current contents of the page
+ htmlDoc2->lpVtbl->close(htmlDoc2);
+
+ // Normally, we'd need to free our BSTR, but SafeArrayDestroy() does it for us
+// SysFreeString(bstr);
+ }
+ }
+
+ // Free the array. This also frees the VARIENT that SafeArrayAccessData created for us,
+ // and even frees the BSTR we allocated with SysAllocString
+ SafeArrayDestroy(sfArray);
+ }
+
+ // Release the IHTMLDocument2 object.
+bad: htmlDoc2->lpVtbl->Release(htmlDoc2);
+ }
+
+ // Release the DISPATCH object.
+ lpDispatch->lpVtbl->Release(lpDispatch);
+ }
+
+ // Release the IWebBrowser2 object.
+ webBrowser2->lpVtbl->Release(webBrowser2);
+ }
+
+ // No error?
+ if (bstr) return(0);
+
+ // An error
+ return(-1);
+}
+
+
+
+/******************************* ResizeBrowser() ****************************
+ * Resizes the browser object for the specified window to the specified
+ * width and height.
+ *
+ * hwnd = Handle to the window hosting the browser object.
+ * width = Width.
+ * height = Height.
+ *
+ * NOTE: EmbedBrowserObject() must have been successfully called once with the
+ * specified window, prior to calling this function. You need call
+ * EmbedBrowserObject() once only, and then you can make multiple calls to
+ * this function to resize the browser object.
+ */
+
+void ResizeBrowser(HWND hwnd, DWORD width, DWORD height)
+{
+ IWebBrowser2 *webBrowser2;
+ IOleObject *browserObject;
+
+ // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
+ // we initially attached the browser object to this window.
+ browserObject = *((IOleObject **)GetWindowLongPtr(hwnd, GWLP_USERDATA));
+
+ // We want to get the base address (ie, a pointer) to the IWebBrowser2 object embedded within the browser
+ // object, so we can call some of the functions in the former's table.
+ if (!browserObject->lpVtbl->QueryInterface(browserObject, &IID_IWebBrowser2, (void**)&webBrowser2))
+ {
+ // Ok, now the pointer to our IWebBrowser2 object is in 'webBrowser2', and so its VTable is
+ // webBrowser2->lpVtbl.
+
+ // Call are put_Width() and put_Height() to set the new width/height.
+ webBrowser2->lpVtbl->put_Width(webBrowser2, width);
+ webBrowser2->lpVtbl->put_Height(webBrowser2, height);
+
+ // We no longer need the IWebBrowser2 object (ie, we don't plan to call any more functions in it,
+ // so we can release our hold on it). Note that we'll still maintain our hold on the browser
+ // object.
+ webBrowser2->lpVtbl->Release(webBrowser2);
+ }
+}
+
+
+
+
+
+/***************************** EmbedBrowserObject() **************************
+ * Puts the browser object inside our host window, and save a pointer to this
+ * window's browser object in the window's GWL_USERDATA field.
+ *
+ * hwnd = Handle of our window into which we embed the browser object.
+ *
+ * RETURNS: 0 if success, or non-zero if an error.
+ *
+ * NOTE: We tell the browser object to occupy the entire client area of the
+ * window.
+ *
+ * NOTE: No HTML page will be displayed here. We can do that with a subsequent
+ * call to either DisplayHTMLPage() or DisplayHTMLStr(). This is merely once-only
+ * initialization for using the browser object. In a nutshell, what we do
+ * here is get a pointer to the browser object in our window's GWL_USERDATA
+ * so we can access that object's functions whenever we want, and we also pass
+ * the browser a pointer to our IOleClientSite struct so that the browser can
+ * call our functions in our struct's VTable.
+ */
+
+long EmbedBrowserObject(HWND hwnd)
+{
+ LPCLASSFACTORY pClassFactory;
+ IOleObject *browserObject;
+ IWebBrowser2 *webBrowser2;
+ RECT rect;
+ char *ptr;
+ _IOleClientSiteEx *_iOleClientSiteEx;
+
+ // Our IOleClientSite, IOleInPlaceSite, and IOleInPlaceFrame functions need to get our window handle. We
+ // could store that in some global. But then, that would mean that our functions would work with only that
+ // one window. If we want to create multiple windows, each hosting its own browser object (to display its
+ // own web page), then we need to create unique IOleClientSite, IOleInPlaceSite, and IOleInPlaceFrame
+ // structs for each window. And we'll put an extra field at the end of those structs to store our extra
+ // data such as a window handle. So, our functions won't have to touch global data, and can therefore be
+ // re-entrant and work with multiple objects/windows.
+ //
+ // Remember that a pointer to our IOleClientSite we create here will be passed as the first arg to every
+ // one of our IOleClientSite functions. Ditto with the IOleInPlaceFrame object we create here, and the
+ // IOleInPlaceFrame functions. So, our functions are able to retrieve the window handle we'll store here,
+ // and then, they'll work with all such windows containing a browser control.
+ //
+ // Furthermore, since the browser will be calling our IOleClientSite's QueryInterface to get a pointer to
+ // our IOleInPlaceSite and IDocHostUIHandler objects, that means that our IOleClientSite QueryInterface
+ // must have an easy way to grab those pointers. Probably the easiest thing to do is just embed our
+ // IOleInPlaceSite and IDocHostUIHandler objects inside of an extended IOleClientSite which we'll call
+ // a _IOleClientSiteEx. As long as they come after the pointer to the IOleClientSite VTable, then we're
+ // ok.
+ //
+ // Of course, we need to GlobalAlloc the above structs now. We'll just get all 4 with a single call to
+ // GlobalAlloc, especially since 3 of them are all contained inside of our _IOleClientSiteEx anyway.
+ //
+ // So, we're not actually allocating separate IOleClientSite, IOleInPlaceSite, IOleInPlaceFrame and
+ // IDocHostUIHandler structs.
+ //
+ // One final thing. We're going to allocate extra room to store the pointer to the browser object.
+ if (!(ptr = (char *)GlobalAlloc(GMEM_FIXED, sizeof(_IOleClientSiteEx) + sizeof(IOleObject *))))
+ return(-1);
+
+ // Initialize our IOleClientSite object with a pointer to our IOleClientSite VTable.
+ _iOleClientSiteEx = (_IOleClientSiteEx *)(ptr + sizeof(IOleObject *));
+ _iOleClientSiteEx->client.lpVtbl = &MyIOleClientSiteTable;
+
+ // Initialize our IOleInPlaceSite object with a pointer to our IOleInPlaceSite VTable.
+ _iOleClientSiteEx->inplace.inplace.lpVtbl = &MyIOleInPlaceSiteTable;
+
+ // Initialize our IOleInPlaceFrame object with a pointer to our IOleInPlaceFrame VTable.
+ _iOleClientSiteEx->inplace.frame.frame.lpVtbl = &MyIOleInPlaceFrameTable;
+
+ // Save our HWND (in the IOleInPlaceFrame object) so our IOleInPlaceFrame functions can retrieve it.
+ _iOleClientSiteEx->inplace.frame.window = hwnd;
+
+ // Initialize our IDocHostUIHandler object with a pointer to our IDocHostUIHandler VTable.
+ _iOleClientSiteEx->ui.ui.lpVtbl = &MyIDocHostUIHandlerTable;
+
+ // Get a pointer to the browser object and lock it down (so it doesn't "disappear" while we're using
+ // it in this program). We do this by calling the OS function CoGetClassObject().
+ //
+ // NOTE: We need this pointer to interact with and control the browser. With normal WIN32 controls such as a
+ // Static, Edit, Combobox, etc, you obtain an HWND and send messages to it with SendMessage(). Not so with
+ // the browser object. You need to get a pointer to its "base structure" (as returned by CoGetClassObject()). This
+ // structure contains an array of pointers to functions you can call within the browser object. Actually, the
+ // base structure contains a 'lpVtbl' field that is a pointer to that array. We'll call the array a 'VTable'.
+ //
+ // For example, the browser object happens to have a SetHostNames() function we want to call. So, after we
+ // retrieve the pointer to the browser object (in a local we'll name 'browserObject'), then we can call that
+ // function, and pass it args, as so:
+ //
+ // browserObject->lpVtbl->SetHostNames(browserObject, SomeString, SomeString);
+ //
+ // There's our pointer to the browser object in 'browserObject'. And there's the pointer to the browser object's
+ // VTable in 'browserObject->lpVtbl'. And the pointer to the SetHostNames function happens to be stored in an
+ // field named 'SetHostNames' within the VTable. So we are actually indirectly calling SetHostNames by using
+ // a pointer to it. That's how you use a VTable.
+ //
+ // NOTE: We pass our _IOleClientSiteEx struct and lie -- saying that it's a IOleClientSite. It's ok. A
+ // _IOleClientSiteEx struct starts with an embedded IOleClientSite. So the browser won't care, and we want
+ // this extended struct passed to our IOleClientSite functions.
+
+ // Get a pointer to the browser object's IClassFactory object via CoGetClassObject()
+ pClassFactory = 0;
+ if (!CoGetClassObject(&CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, NULL, &IID_IClassFactory, (void **)&pClassFactory) && pClassFactory)
+ {
+ // Call the IClassFactory's CreateInstance() to create a browser object
+ if (!pClassFactory->lpVtbl->CreateInstance(pClassFactory, 0, &IID_IOleObject, &browserObject))
+ {
+ // Free the IClassFactory. We need it only to create a browser object instance
+ pClassFactory->lpVtbl->Release(pClassFactory);
+
+ // Ok, we now have the pointer to the browser object in 'browserObject'. Let's save this in the
+ // memory block we allocated above, and then save the pointer to that whole thing in our window's
+ // USERDATA field. That way, if we need multiple windows each hosting its own browser object, we can
+ // call EmbedBrowserObject() for each one, and easily associate the appropriate browser object with
+ // its matching window and its own objects containing per-window data.
+ *((IOleObject **)ptr) = browserObject;
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)ptr);
+
+ // Give the browser a pointer to my IOleClientSite object
+ if (!browserObject->lpVtbl->SetClientSite(browserObject, (IOleClientSite *)_iOleClientSiteEx))
+ {
+ // We can now call the browser object's SetHostNames function. SetHostNames lets the browser object know our
+ // application's name and the name of the document in which we're embedding the browser. (Since we have no
+ // document name, we'll pass a 0 for the latter). When the browser object is opened for editing, it displays
+ // these names in its titlebar.
+ //
+ // We are passing 3 args to SetHostNames. You'll note that the first arg to SetHostNames is the base
+ // address of our browser control. This is something that you always have to remember when working in C
+ // (as opposed to C++). When calling a VTable function, the first arg to that function must always be the
+ // structure which contains the VTable. (In this case, that's the browser control itself). Why? That's
+ // because that function is always assumed to be written in C++. And the first argument to any C++ function
+ // must be its 'this' pointer (ie, the base address of its class, which in this case is our browser object
+ // pointer). In C++, you don't have to pass this first arg, because the C++ compiler is smart enough to
+ // produce an executable that always adds this first arg. In fact, the C++ compiler is smart enough to
+ // know to fetch the function pointer from the VTable, so you don't even need to reference that. In other
+ // words, the C++ equivalent code would be:
+ //
+ // browserObject->SetHostNames(L"My Host Name", 0);
+ //
+ // So, when you're trying to convert C++ code to C, always remember to add this first arg whenever you're
+ // dealing with a VTable (ie, the field is usually named 'lpVtbl') in the standard objects, and also add
+ // the reference to the VTable itself.
+ //
+ // Oh yeah, the L is because we need UNICODE strings. And BTW, the host and document names can be anything
+ // you want.
+ browserObject->lpVtbl->SetHostNames(browserObject, L"My Host Name", 0);
+
+ GetClientRect(hwnd, &rect);
+
+ // Let browser object know that it is embedded in an OLE container.
+ if (!OleSetContainedObject((struct IUnknown *)browserObject, TRUE) &&
+
+ // Set the display area of our browser control the same as our window's size
+ // and actually put the browser object into our window.
+ !browserObject->lpVtbl->DoVerb(browserObject, OLEIVERB_SHOW, NULL, (IOleClientSite *)_iOleClientSiteEx, -1, hwnd, &rect) &&
+
+ // Ok, now things may seem to get even trickier, One of those function pointers in the browser's VTable is
+ // to the QueryInterface() function. What does this function do? It lets us grab the base address of any
+ // other object that may be embedded within the browser object. And this other object has its own VTable
+ // containing pointers to more functions we can call for that object.
+ //
+ // We want to get the base address (ie, a pointer) to the IWebBrowser2 object embedded within the browser
+ // object, so we can call some of the functions in the former's table. For example, one IWebBrowser2 function
+ // we intend to call below will be Navigate2(). So we call the browser object's QueryInterface to get our
+ // pointer to the IWebBrowser2 object.
+ !browserObject->lpVtbl->QueryInterface(browserObject, &IID_IWebBrowser2, (void**)&webBrowser2))
+ {
+ // Ok, now the pointer to our IWebBrowser2 object is in 'webBrowser2', and so its VTable is
+ // webBrowser2->lpVtbl.
+
+ // Let's call several functions in the IWebBrowser2 object to position the browser display area
+ // in our window. The functions we call are put_Left(), put_Top(), put_Width(), and put_Height().
+ // Note that we reference the IWebBrowser2 object's VTable to get pointers to those functions. And
+ // also note that the first arg we pass to each is the pointer to the IWebBrowser2 object.
+ webBrowser2->lpVtbl->put_Left(webBrowser2, 0);
+ webBrowser2->lpVtbl->put_Top(webBrowser2, 0);
+ webBrowser2->lpVtbl->put_Width(webBrowser2, rect.right);
+ webBrowser2->lpVtbl->put_Height(webBrowser2, rect.bottom);
+
+ // We no longer need the IWebBrowser2 object (ie, we don't plan to call any more functions in it
+ // right now, so we can release our hold on it). Note that we'll still maintain our hold on the
+ // browser object until we're done with that object.
+ webBrowser2->lpVtbl->Release(webBrowser2);
+
+ // Success
+ return(0);
+ }
+ }
+
+ // Something went wrong setting up the browser!
+ UnEmbedBrowserObject(hwnd);
+ return(-4);
+ }
+
+ pClassFactory->lpVtbl->Release(pClassFactory);
+ GlobalFree(ptr);
+
+ // Can't create an instance of the browser!
+ return(-3);
+ }
+
+ GlobalFree(ptr);
+
+ // Can't get the web browser's IClassFactory!
+ return(-2);
+}
+
+
+
+
+
+/****************************** WindowProc() ***************************
+ * Our message handler for our window to host the browser.
+ */
+
+LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_SIZE:
+ {
+ // Resize the browser object to fit the window
+ ResizeBrowser(hwnd, LOWORD(lParam), HIWORD(lParam));
+ return(0);
+ }
+
+ case WM_CREATE:
+ {
+ // Embed the browser object into our host window. We need do this only
+ // once. Note that the browser object will start calling some of our
+ // IOleInPlaceFrame and IOleClientSite functions as soon as we start
+ // calling browser object functions in EmbedBrowserObject().
+ if (EmbedBrowserObject(hwnd)) return(-1);
+
+ // Success
+ return(0);
+ }
+
+ case WM_DESTROY:
+ {
+ int i, nCount;
+
+ // Detach the browser object from this window, and free resources.
+ UnEmbedBrowserObject(hwnd);
+
+ // If all the windows are now closed, quit this app
+ if (m_hWindows)
+ {
+ for (i=0, nCount=List_Count(m_hWindows); i<nCount; i++)
+ {
+ if (List_ElementAt (m_hWindows, i)==hwnd)
+ {
+ List_RemoveElementAt (m_hWindows, i);
+ break;
+ }
+ }
+ }
+
+ return(TRUE);
+ }
+
+
+ }
+
+ return(DefWindowProc(hwnd, uMsg, wParam, lParam));
+}
+
+// -----------------------------------------------------------------------------
+
+
+static DWORD WINAPI ShowIEWndFunc(PVOID pLoadWnd)
+{
+ MSG msg;
+ WNDCLASSEX wc={0};
+ HWND hWndCache = NULL;
+ static const TCHAR ClassName[] = "imo.im Voicechat wnd";
+
+ if (CoInitialize(NULL) != S_OK) return -1;
+
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.cbWndExtra = 2*sizeof(PVOID); // Extra to be used by caller, as we already make use of GWL_USERDATA
+ wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
+ wc.lpfnWndProc = WindowProc;
+ wc.lpszClassName = &ClassName[0];
+ RegisterClassEx(&wc);
+
+ m_hWindows = List_Init(0);
+
+ if (pLoadWnd)
+ {
+ // Create an invisible window with IE Control so that the appropriate libraries get loaded
+ // and a new window can be shown more quickly
+ hWndCache = CreateWindowEx(0, wc.lpszClassName, "dummy", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
+ HWND_DESKTOP, NULL, wc.hInstance, 0);
+ List_Push (m_hWindows, hWndCache);
+ DisplayHTMLStr(hWndCache, "");
+ }
+
+ while (GetMessage(&msg, 0, 0, 0) == 1)
+ {
+ switch (msg.message)
+ {
+ case WM_USER:
+ {
+ ShowIEWndParam *Param = (ShowIEWndParam *)msg.lParam;
+ if ((Param->hWnd = CreateWindowEx(0, wc.lpszClassName, Param->pszTitle, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, Param->width, Param->height,
+ HWND_DESKTOP, NULL, wc.hInstance, 0)))
+ {
+ List_Push (m_hWindows, Param->hWnd);
+ DisplayHTMLStr(Param->hWnd, Param->pszHTML);
+ ShowWindow(Param->hWnd, SW_SHOWNORMAL);
+ SetForegroundWindow (Param->hWnd);
+ UpdateWindow(Param->hWnd);
+ }
+ SetEvent (m_hEvent);
+ break;
+ }
+ case WM_USER+1:
+ {
+ DestroyWindow ((HWND)msg.lParam);
+ break;
+ }
+ }
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ UnregisterClass (wc.lpszClassName, wc.hInstance);
+ CoUninitialize();
+ if (m_hWindows) List_Exit (m_hWindows);
+ ExitThread (0);
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+// Interface
+// -----------------------------------------------------------------------------
+
+// bInitBrowser - Tries to initialize a dummy window on start so that subsequent
+// calls are faster as all libraries are already present in
+// memory. Drawback: Higher memory consumption
+int W32Browser_Init(BOOL bInitBrowser)
+{
+ if (m_hThread) W32Browser_Exit();
+ m_hThread = (HANDLE)_beginthreadex(NULL, 0, ShowIEWndFunc, (LPVOID)bInitBrowser, 0, &m_dwThread);
+ if (!m_hThread) return -1;
+ if (!(m_hEvent = CreateEvent (NULL, FALSE, FALSE, NULL)))
+ {
+ TerminateThread (m_hThread, -1);
+ CloseHandle (m_hThread);
+ return -1;
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+void W32Browser_Exit(void)
+{
+ if (m_hWindows)
+ {
+ HWND hWnd;
+
+ while (hWnd = List_Pop(m_hWindows))
+ W32Browser_CloseWindow (hWnd);
+ m_hWindows = NULL;
+ }
+ if (m_hThread)
+ {
+ PostThreadMessage (m_dwThread, WM_QUIT, 0, 0);
+ if (WaitForSingleObject (m_hThread, 2000) == WAIT_TIMEOUT)
+ TerminateThread (m_hThread, -1);
+ CloseHandle (m_hThread);
+ m_hThread = NULL;
+ }
+ if (m_hEvent)
+ {
+ CloseHandle (m_hEvent);
+ m_hEvent = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void *W32Browser_ShowHTMLStr(char *pszHTMLStr, int width, int height, char *pszTitle)
+{
+ // Window gets its own thread to not block the Mainthread
+ static ShowIEWndParam Param;
+
+ Param.width = width;
+ Param.height = height;
+ Param.pszHTML = pszHTMLStr;
+ Param.pszTitle = pszTitle;
+ Param.hWnd = 0;
+ PostThreadMessage (m_dwThread, WM_USER, 0, (LPARAM)&Param);
+ WaitForSingleObject (m_hEvent, INFINITE);
+ return (void*)Param.hWnd;
+}
+
+// -----------------------------------------------------------------------------
+
+void W32Browser_CloseWindow (void *pWnd)
+{
+ PostThreadMessage (m_dwThread, WM_USER+1, 0, (LPARAM)pWnd);
+}