diff --git a/CMakeLists.txt b/CMakeLists.txt index a0b8038..64080f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,11 +5,6 @@ project(m2dev-client-src) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -if (MSVC) - add_compile_options("/Zc:__cplusplus") - add_compile_options("/Zc:preprocessor") -endif() - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/buildtool" @@ -34,6 +29,7 @@ add_compile_options( ) add_definitions(-DNOMINMAX) +add_definitions(-DWIN32_LEAN_AND_MEAN) add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-DWINDOWS_IGNORE_PACKING_MISMATCH) diff --git a/src/CWebBrowser/CWebBrowser.c b/src/CWebBrowser/CWebBrowser.c index 6461871..0d54370 100644 --- a/src/CWebBrowser/CWebBrowser.c +++ b/src/CWebBrowser/CWebBrowser.c @@ -1,1717 +1,1716 @@ -/* Simple.c - -This is a Win32 C application (ie, no MFC, WTL, nor even any C++ -- just plain C) that demonstrates -how to embed a browser "control" (actually, an OLE object) in your own window (in order to display a -web page, or an HTML file on disk). - -This example opens two windows, each containing a browser object. The first window displays an HTML -string in memory. The second window displays Microsoft's web site. We also disable the pop-up context -menu, and resize the browser to fill our window. - -This is very loosely based upon a C++ example written by Chris Becke. I used that to learn the minimum -of what I needed to know about hosting the browser object. Then I wrote this example from the ground up -in C. - -This requires IE 5.0 (or better) -- due to the IDocHostUIHandler interface, or a browser that supports -the same level of OLE in-place activation. -*/ - - -#include -#include // Defines of stuff like IWebBrowser2. This is an include file with Visual C 6 and above -#include // Defines of stuff like IHTMLDocument2. This is an include file with Visual C 6 and above -#include // Defines of stuff like IDocHostUIHandler. This is an include file with Visual C 6 and above -//#include // for _ASSERT() - -#define _ASSERT(x) - - - -// A running count of how many windows we have open that contain a browser object -unsigned char WindowCount = 0; - -// The class name of our Window to host the browser. It can be anything of your choosing. -static const TCHAR ClassName[] = "Browser Example"; - -// This is used by DisplayHTMLStr(). It can be global because we never change it. -static const SAFEARRAYBOUND ArrayBound = {1, 0}; - - - - - - - - - - -// Our IOleInPlaceFrame functions that the browser may call -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); - -// Our IOleInPlaceFrame VTable. This is the array of pointers to the above functions in our C -// program that the browser may call in order to interact with our frame window that contains -// the browser object. We must define a particular set of functions that comprise the -// IOleInPlaceFrame set of functions (see above), and then stuff pointers to those functions -// in their respective 'slots' in this table. We want the browser to use this VTable with our -// IOleInPlaceFrame structure. -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}; - -// We need to return an IOleInPlaceFrame struct to the browser object. And one of our IOleInPlaceFrame -// functions (Frame_GetWindow) is going to need to access our window handle. So let's create our own -// struct that starts off with an IOleInPlaceFrame struct (and that's important -- the IOleInPlaceFrame -// struct *must* be first), and then has an extra data field where we can store our own window's HWND. +///* Simple.c +// +//This is a Win32 C application (ie, no MFC, WTL, nor even any C++ -- just plain C) that demonstrates +//how to embed a browser "control" (actually, an OLE object) in your own window (in order to display a +//web page, or an HTML file on disk). // -// And because we may want to create multiple windows, each hosting its own browser object (to -// display its own web page), then we need to create a IOleInPlaceFrame struct for each window. So, -// we're not going to declare our IOleInPlaceFrame struct globally. We'll allocate it later using -// GlobalAlloc, and then stuff the appropriate HWND in it then, and also stuff a pointer to -// MyIOleInPlaceFrameTable in it. But let's just define it here. -typedef struct { - IOleInPlaceFrame frame; // The IOleInPlaceFrame must be first! - - /////////////////////////////////////////////////// - // Here you add any extra variables that you need - // to access in your IOleInPlaceFrame functions. - // You don't want those functions to access global - // variables, because then you couldn't use more - // than one browser object. (ie, You couldn't have - // multiple windows, each with its own embedded - // browser object to display a different web page). - // - // So here is where I added my extra HWND that my - // IOleInPlaceFrame function Frame_GetWindow() needs - // to access. - /////////////////////////////////////////////////// - HWND window; -} _IOleInPlaceFrameEx; - - - - - - -// Our IOleClientSite functions that the browser may call -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); - -// Our IOleClientSite VTable. This is the array of pointers to the above functions in our C -// program that the browser may call in order to interact with our frame window that contains -// the browser object. We must define a particular set of functions that comprise the -// IOleClientSite set of functions (see above), and then stuff pointers to those functions -// in their respective 'slots' in this table. We want the browser to use this VTable with our -// IOleClientSite structure. -IOleClientSiteVtbl MyIOleClientSiteTable = {Site_QueryInterface, -Site_AddRef, -Site_Release, -Site_SaveObject, -Site_GetMoniker, -Site_GetContainer, -Site_ShowObject, -Site_OnShowWindow, -Site_RequestNewObjectLayout}; - - - - - - -// Our IDocHostUIHandler functions that the browser may call -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); - -// Our IDocHostUIHandler VTable. This is the array of pointers to the above functions in our C -// program that the browser may call in order to replace/set certain user interface considerations -// (such as whether to display a pop-up context menu when the user right-clicks on the embedded -// browser object). We must define a particular set of functions that comprise the -// IDocHostUIHandler set of functions (see above), and then stuff pointers to those functions -// in their respective 'slots' in this table. We want the browser to use this VTable with our -// IDocHostUIHandler structure. -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}; - -// We'll allocate our IDocHostUIHandler object dynamically with GlobalAlloc() for reasons outlined later. - - - -// Our IOleInPlaceSite functions that the browser may call -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); - -// Our IOleInPlaceSite VTable. This is the array of pointers to the above functions in our C -// program that the browser may call in order to interact with our frame window that contains -// the browser object. We must define a particular set of functions that comprise the -// IOleInPlaceSite set of functions (see above), and then stuff pointers to those functions -// in their respective 'slots' in this table. We want the browser to use this VTable with our -// IOleInPlaceSite structure. -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}; - -// We need to pass our IOleClientSite structure to OleCreate (which in turn gives it to the browser). -// But the browser is also going to ask our IOleClientSite's QueryInterface() to return a pointer to -// our IOleInPlaceSite and/or IDocHostUIHandler structs. So we'll need to have those pointers handy. -// Plus, some of our IOleClientSite and IOleInPlaceSite functions will need to have the HWND to our -// window, and also a pointer to our IOleInPlaceFrame struct. So let's create a single struct that -// has the IOleClientSite, IOleInPlaceSite, IDocHostUIHandler, and IOleInPlaceFrame structs all inside -// it (so we can easily get a pointer to any one from any of those structs' functions). As long as the -// IOleClientSite struct is the very first thing in this custom struct, it's all ok. We can still pass -// it to OleCreate() and pretend that it's an ordinary IOleClientSite. We'll call this new struct a -// _IOleClientSiteEx. +//This example opens two windows, each containing a browser object. The first window displays an HTML +//string in memory. The second window displays Microsoft's web site. We also disable the pop-up context +//menu, and resize the browser to fill our window. // -// And because we may want to create multiple windows, each hosting its own browser object (to -// display its own web page), then we need to create a unique _IOleClientSiteEx struct for -// each window. So, we're not going to declare this struct globally. We'll allocate it later -// using GlobalAlloc, and then initialize the structs within it. - -typedef struct { - IOleInPlaceSite inplace; // My IOleInPlaceSite object. Must be first with in _IOleInPlaceSiteEx. - - /////////////////////////////////////////////////// - // Here you add any extra variables that you need - // to access in your IOleInPlaceSite functions. - // - // So here is where I added my IOleInPlaceFrame - // struct. If you need extra variables, add them - // at the end. - /////////////////////////////////////////////////// - _IOleInPlaceFrameEx frame; // My IOleInPlaceFrame object. Must be first within my _IOleInPlaceFrameEx -} _IOleInPlaceSiteEx; - -typedef struct { - IDocHostUIHandler ui; // My IDocHostUIHandler object. Must be first. - - /////////////////////////////////////////////////// - // Here you add any extra variables that you need - // to access in your IDocHostUIHandler functions. - /////////////////////////////////////////////////// -} _IDocHostUIHandlerEx; - -typedef struct { - IOleClientSite client; // My IOleClientSite object. Must be first. - _IOleInPlaceSiteEx inplace; // My IOleInPlaceSite object. A convenient place to put it. - _IDocHostUIHandlerEx ui; // My IDocHostUIHandler object. Must be first within my _IDocHostUIHandlerEx. - - /////////////////////////////////////////////////// - // Here you add any extra variables that you need - // to access in your IOleClientSite functions. - /////////////////////////////////////////////////// -} _IOleClientSiteEx; - - - - - - - - - - - - - -// This is a simple C example. There are lots more things you can control about the browser object, but -// we don't do it in this example. _Many_ of the functions we provide below for the browser to call, will -// never actually be called by the browser in our example. Why? Because we don't do certain things -// with the browser that would require it to call those functions (even though we need to provide -// at least some stub for all of the functions). +//This is very loosely based upon a C++ example written by Chris Becke. I used that to learn the minimum +//of what I needed to know about hosting the browser object. Then I wrote this example from the ground up +//in C. // -// So, for these "dummy functions" that we don't expect the browser to call, we'll just stick in some -// assembly code that causes a debugger breakpoint and tells the browser object that we don't support -// the functionality. That way, if you try to do more things with the browser object, and it starts -// calling these "dummy functions", you'll know which ones you should add more meaningful code to. -#define NOTIMPLEMENTED _ASSERT(0); return(E_NOTIMPL) - - - - - -//////////////////////////////////// My IDocHostUIHandler functions ////////////////////////////////////// -// The browser object asks us for the pointer to our IDocHostUIHandler object by calling our IOleClientSite's -// QueryInterface (ie, Site_QueryInterface) and specifying a REFIID of IID_IDocHostUIHandler. +//This requires IE 5.0 (or better) -- due to the IDocHostUIHandler interface, or a browser that supports +//the same level of OLE in-place activation. +//*/ // -// NOTE: You need at least IE 4.0. Previous versions do not ask for, nor utilize, our IDocHostUIHandler functions. - -HRESULT STDMETHODCALLTYPE UI_QueryInterface(IDocHostUIHandler FAR* This, REFIID riid, LPVOID FAR* ppvObj) -{ - // The browser assumes that our IDocHostUIHandler object is associated with our IOleClientSite - // object. So it is possible that the browser may call our IDocHostUIHandler's QueryInterface() - // to ask us to return a pointer to our IOleClientSite, in the same way that the browser calls - // our IOleClientSite's QueryInterface() to ask for a pointer to our IDocHostUIHandler. - // - // Rather than duplicate much of the code in IOleClientSite's QueryInterface, let's just get - // a pointer to our _IOleClientSiteEx object, substitute it as the 'This' arg, and call our - // our IOleClientSite's QueryInterface. Note that since our _IDocHostUIHandlerEx is embedded right - // inside our _IOleClientSiteEx, and comes immediately after the _IOleInPlaceSiteEx, we can employ - // the following trickery to get the pointer to our _IOleClientSiteEx. - 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); -} - -// Called when the browser object is about to display its context menu. -HRESULT STDMETHODCALLTYPE UI_ShowContextMenu(IDocHostUIHandler FAR* This, DWORD dwID, POINT __RPC_FAR *ppt, IUnknown __RPC_FAR *pcmdtReserved, IDispatch __RPC_FAR *pdispReserved) -{ - // If desired, we can pop up your own custom context menu here. Of course, - // we would need some way to get our window handle, so what we'd probably - // do is like what we did with our IOleInPlaceFrame object. We'd define and create - // our own IDocHostUIHandlerEx object with an embedded IDocHostUIHandler at the - // start of it. Then we'd add an extra HWND field to store our window handle. - // It could look like this: - // - // typedef struct _IDocHostUIHandlerEx { - // IDocHostUIHandler ui; // The IDocHostUIHandler must be first! - // HWND window; - // } IDocHostUIHandlerEx; - // - // Of course, we'd need a unique IDocHostUIHandlerEx object for each window, so - // EmbedBrowserObject() would have to allocate one of those too. And that's - // what we'd pass to our browser object (and it would in turn pass it to us - // here, instead of 'This' being a IDocHostUIHandler *). - - // We will return S_OK to tell the browser not to display its default context menu, - // or return S_FALSE to let the browser show its default context menu. For this - // example, we wish to disable the browser's default context menu. - return(S_OK); -} - -// Called at initialization of the browser object UI. We can set various features of the browser object here. -HRESULT STDMETHODCALLTYPE UI_GetHostInfo(IDocHostUIHandler FAR* This, DOCHOSTUIINFO __RPC_FAR *pInfo) -{ - pInfo->cbSize = sizeof(DOCHOSTUIINFO); - - // Set some flags. We don't want any 3D border. You can do other things like hide - // the scroll bar (DOCHOSTUIFLAG_SCROLL_NO), display picture display (DOCHOSTUIFLAG_NOPICS), - // disable any script running when the page is loaded (DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE), - // open a site in a new browser window when the user clicks on some link (DOCHOSTUIFLAG_OPENNEWWIN), - // and lots of other things. See the MSDN docs on the DOCHOSTUIINFO struct passed to us. - pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER; - - // Set what happens when the user double-clicks on the object. Here we use the default. - pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; - - return(S_OK); -} - -// Called when the browser object shows its UI. This allows us to replace its menus and toolbars by creating our -// own and displaying them here. -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) -{ - // We've already got our own UI in place so just return S_OK to tell the browser - // not to display its menus/toolbars. Otherwise we'd return S_FALSE to let it do - // that. - return(S_OK); -} - -// Called when browser object hides its UI. This allows us to hide any menus/toolbars we created in ShowUI. -HRESULT STDMETHODCALLTYPE UI_HideUI(IDocHostUIHandler FAR* This) -{ - return(S_OK); -} - -// Called when the browser object wants to notify us that the command state has changed. We should update any -// controls we have that are dependent upon our embedded object, such as "Back", "Forward", "Stop", or "Home" -// buttons. -HRESULT STDMETHODCALLTYPE UI_UpdateUI(IDocHostUIHandler FAR* This) -{ - // We update our UI in our window message loop so we don't do anything here. - return(S_OK); -} - -// Called from the browser object's IOleInPlaceActiveObject object's EnableModeless() function. Also -// called when the browser displays a modal dialog box. -HRESULT STDMETHODCALLTYPE UI_EnableModeless(IDocHostUIHandler FAR* This, BOOL fEnable) -{ - return(S_OK); -} - -// Called from the browser object's IOleInPlaceActiveObject object's OnDocWindowActivate() function. -// This informs off of when the object is getting/losing the focus. -HRESULT STDMETHODCALLTYPE UI_OnDocWindowActivate(IDocHostUIHandler FAR* This, BOOL fActivate) -{ - return(S_OK); -} - -// Called from the browser object's IOleInPlaceActiveObject object's OnFrameWindowActivate() function. -HRESULT STDMETHODCALLTYPE UI_OnFrameWindowActivate(IDocHostUIHandler FAR* This, BOOL fActivate) -{ - return(S_OK); -} - -// Called from the browser object's IOleInPlaceActiveObject object's ResizeBorder() function. -HRESULT STDMETHODCALLTYPE UI_ResizeBorder(IDocHostUIHandler FAR* This, LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR *pUIWindow, BOOL fRameWindow) -{ - return(S_OK); -} - -// Called from the browser object's TranslateAccelerator routines to translate key strokes to commands. -HRESULT STDMETHODCALLTYPE UI_TranslateAccelerator(IDocHostUIHandler FAR* This, LPMSG lpMsg, const GUID __RPC_FAR *pguidCmdGroup, DWORD nCmdID) -{ - // We don't intercept any keystrokes, so we do nothing here. But for example, if we wanted to - // override the TAB key, perhaps do something with it ourselves, and then tell the browser - // not to do anything with this keystroke, we'd do: - // - // if (pMsg && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB) - // { - // // Here we do something as a result of a TAB key press. - // - // // Tell the browser not to do anything with it. - // return(S_FALSE); - // } - // - // // Otherwise, let the browser do something with this message. - // return(S_OK); - - // For our example, we want to make sure that the user can invoke some key to popup the context - // menu, so we'll tell it to ignore all messages. - return(S_FALSE); -} - -// Called by the browser object to find where the host wishes the browser to get its options in the registry. -// We can use this to prevent the browser from using its default settings in the registry, by telling it to use -// some other registry key we've setup with the options we want. -HRESULT STDMETHODCALLTYPE UI_GetOptionKeyPath(IDocHostUIHandler FAR* This, LPOLESTR __RPC_FAR *pchKey, DWORD dw) -{ - // Let the browser use its default registry settings. - return(S_FALSE); -} - -// Called by the browser object when it is used as a drop target. We can supply our own IDropTarget object, -// IDropTarget functions, and IDropTarget VTable if we want to determine what happens when someone drags and -// drops some object on our embedded browser object. -HRESULT STDMETHODCALLTYPE UI_GetDropTarget(IDocHostUIHandler FAR* This, IDropTarget __RPC_FAR *pDropTarget, IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget) -{ - // Return our IDropTarget object associated with this IDocHostUIHandler object. I don't - // know why we don't do this via UI_QueryInterface(), but we don't. - - // NOTE: If we want/need an IDropTarget interface, then we would have had to setup our own - // IDropTarget functions, IDropTarget VTable, and create an IDropTarget object. We'd want to put - // a pointer to the IDropTarget object in our own custom IDocHostUIHandlerEx object (like how - // we may add an HWND field for the use of UI_ShowContextMenu). So when we created our - // IDocHostUIHandlerEx object, maybe we'd add a 'idrop' field to the end of it, and - // store a pointer to our IDropTarget object there. Then we could return this pointer as so: - // - // *pDropTarget = ((IDocHostUIHandlerEx FAR *)This)->idrop; - // return(S_OK); - - // But for our purposes, we don't need an IDropTarget object, so we'll tell whomever is calling - // us that we don't have one. - return(S_FALSE); -} - -// Called by the browser when it wants a pointer to our IDispatch object. This object allows us to expose -// our own automation interface (ie, our own COM objects) to other entities that are running within the -// context of the browser so they can call our functions if they want. An example could be a javascript -// running in the URL we display could call our IDispatch functions. We'd write them so that any args passed -// to them would use the generic datatypes like a BSTR for utmost flexibility. -HRESULT STDMETHODCALLTYPE UI_GetExternal(IDocHostUIHandler FAR* This, IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) -{ - // Return our IDispatch object associated with this IDocHostUIHandler object. I don't - // know why we don't do this via UI_QueryInterface(), but we don't. - - // NOTE: If we want/need an IDispatch interface, then we would have had to setup our own - // IDispatch functions, IDispatch VTable, and create an IDispatch object. We'd want to put - // a pointer to the IDispatch object in our custom _IDocHostUIHandlerEx object (like how - // we may add an HWND field for the use of UI_ShowContextMenu). So when we defined our - // _IDocHostUIHandlerEx object, maybe we'd add a 'idispatch' field to the end of it, and - // store a pointer to our IDispatch object there. Then we could return this pointer as so: - // - // *ppDispatch = ((_IDocHostUIHandlerEx FAR *)This)->idispatch; - // return(S_OK); - - // But for our purposes, we don't need an IDispatch object, so we'll tell whomever is calling - // us that we don't have one. Note: We must set ppDispatch to 0 if we don't return our own - // IDispatch object. - *ppDispatch = 0; - return(S_FALSE); -} - -// Called by the browser object to give us an opportunity to modify the URL to be loaded. -HRESULT STDMETHODCALLTYPE UI_TranslateUrl(IDocHostUIHandler FAR* This, DWORD dwTranslate, OLECHAR __RPC_FAR *pchURLIn, OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut) -{ - // We don't need to modify the URL. Note: We need to set ppchURLOut to 0 if we don't - // return an OLECHAR (buffer) containing a modified version of pchURLIn. - *ppchURLOut = 0; - return(S_FALSE); -} - -// Called by the browser when it does cut/paste to the clipboard. This allows us to block certain clipboard -// formats or support additional clipboard formats. -HRESULT STDMETHODCALLTYPE UI_FilterDataObject(IDocHostUIHandler FAR* This, IDataObject __RPC_FAR *pDO, IDataObject __RPC_FAR *__RPC_FAR *ppDORet) -{ - // Return our IDataObject object associated with this IDocHostUIHandler object. I don't - // know why we don't do this via UI_QueryInterface(), but we don't. - - // NOTE: If we want/need an IDataObject interface, then we would have had to setup our own - // IDataObject functions, IDataObject VTable, and create an IDataObject object. We'd want to put - // a pointer to the IDataObject object in our custom _IDocHostUIHandlerEx object (like how - // we may add an HWND field for the use of UI_ShowContextMenu). So when we defined our - // _IDocHostUIHandlerEx object, maybe we'd add a 'idata' field to the end of it, and - // store a pointer to our IDataObject object there. Then we could return this pointer as so: - // - // *ppDORet = ((_IDocHostUIHandlerEx FAR *)This)->idata; - // return(S_OK); - - // But for our purposes, we don't need an IDataObject object, so we'll tell whomever is calling - // us that we don't have one. Note: We must set ppDORet to 0 if we don't return our own - // IDataObject object. - *ppDORet = 0; - return(S_FALSE); -} - - - - - - - - - - - - - -////////////////////////////////////// My IOleClientSite functions ///////////////////////////////////// -// We give the browser object a pointer to our IOleClientSite object when we call OleCreate() or DoVerb(). - -/************************* Site_QueryInterface() ************************* - * The browser object calls this when it wants a pointer to one of our - * IOleClientSite, IDocHostUIHandler, or IOleInPlaceSite structures. They - * are all accessible via the _IOleClientSiteEx struct we allocated in - * EmbedBrowserObject() and passed to DoVerb() and OleCreate(). - * - * This = A pointer to whatever _IOleClientSiteEx struct we passed to - * OleCreate() or DoVerb(). - * riid = A GUID struct that the browser passes us to clue us as to - * which type of struct (object) it would like a pointer - * returned for. - * ppvObject = Where the browser wants us to return a pointer to the - * appropriate struct. (ie, It passes us a handle to fill in). - * - * RETURNS: S_OK if we return the struct, or E_NOINTERFACE if we don't have - * the requested struct. - */ - -HRESULT STDMETHODCALLTYPE Site_QueryInterface(IOleClientSite FAR* This, REFIID riid, void ** ppvObject) -{ - // It just so happens that the first arg passed to us is our _IOleClientSiteEx struct we allocated - // and passed to DoVerb() and OleCreate(). Nevermind that 'This' is declared is an IOleClientSite *. - // Remember that in EmbedBrowserObject(), we allocated our own _IOleClientSiteEx struct, and lied - // to OleCreate() and DoVerb() -- passing our _IOleClientSiteEx struct and saying it was an - // IOleClientSite struct. It's ok. An _IOleClientSiteEx starts with an embedded IOleClientSite, so - // the browser didn't mind. So that's what the browser object is passing us now. The browser doesn't - // know that it's really an _IOleClientSiteEx struct. But we do. So we can recast it and use it as - // so here. - - // If the browser is asking us to match IID_IOleClientSite, then it wants us to return a pointer to - // our IOleClientSite struct. Then the browser will use the VTable in that struct to call our - // IOleClientSite functions. It will also pass this same pointer to all of our IOleClientSite - // functions. - // - // Actually, we're going to lie to the browser again. We're going to return our own _IOleClientSiteEx - // struct, and tell the browser that it's a IOleClientSite struct. It's ok. The first thing in our - // _IOleClientSiteEx is an embedded IOleClientSite, so the browser doesn't mind. We want the browser - // to continue passing our _IOleClientSiteEx pointer wherever it would normally pass a IOleClientSite - // pointer. - // - // The IUnknown interface uses the same VTable as the first object in our _IOleClientSiteEx - // struct (which happens to be an IOleClientSite). So if the browser is asking us to match - // IID_IUnknown, then we'll also return a pointer to our _IOleClientSiteEx. - - if (!memcmp(riid, &IID_IUnknown, sizeof(GUID)) || !memcmp(riid, &IID_IOleClientSite, sizeof(GUID))) - *ppvObject = &((_IOleClientSiteEx *)This)->client; - - // If the browser is asking us to match IID_IOleInPlaceSite, then it wants us to return a pointer to - // our IOleInPlaceSite struct. Then the browser will use the VTable in that struct to call our - // IOleInPlaceSite functions. It will also pass this same pointer to all of our IOleInPlaceSite - // functions (except for Site_QueryInterface, Site_AddRef, and Site_Release. Those will always get - // the pointer to our _IOleClientSiteEx. - // - // Actually, we're going to lie to the browser. We're going to return our own _IOleInPlaceSiteEx - // struct, and tell the browser that it's a IOleInPlaceSite struct. It's ok. The first thing in - // our _IOleInPlaceSiteEx is an embedded IOleInPlaceSite, so the browser doesn't mind. We want the - // browser to continue passing our _IOleInPlaceSiteEx pointer wherever it would normally pass a - // IOleInPlaceSite pointer. - else if (!memcmp(riid, &IID_IOleInPlaceSite, sizeof(GUID))) - *ppvObject = &((_IOleClientSiteEx *)This)->inplace; - - // If the browser is asking us to match IID_IDocHostUIHandler, then it wants us to return a pointer to - // our IDocHostUIHandler struct. Then the browser will use the VTable in that struct to call our - // IDocHostUIHandler functions. It will also pass this same pointer to all of our IDocHostUIHandler - // functions (except for Site_QueryInterface, Site_AddRef, and Site_Release. Those will always get - // the pointer to our _IOleClientSiteEx. - // - // Actually, we're going to lie to the browser. We're going to return our own _IDocHostUIHandlerEx - // struct, and tell the browser that it's a IDocHostUIHandler struct. It's ok. The first thing in - // our _IDocHostUIHandlerEx is an embedded IDocHostUIHandler, so the browser doesn't mind. We want the - // browser to continue passing our _IDocHostUIHandlerEx pointer wherever it would normally pass a - // IDocHostUIHandler pointer. My, we're really playing dirty tricks on the browser here. heheh. - else if (!memcmp(riid, &IID_IDocHostUIHandler, sizeof(GUID))) - *ppvObject = &((_IOleClientSiteEx *)This)->ui; - - // For other types of objects the browser wants, just report that we don't have any such objects. - // NOTE: If you want to add additional functionality to your browser hosting, you may need to - // provide some more objects here. You'll have to investigate what the browser is asking for - // (ie, what REFIID it is passing). - 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) -{ - // Tell the browser that we are a simple object and don't support a container - *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 ///////////////////////////////////// -// The browser object asks us for the pointer to our IOleInPlaceSite object by calling our IOleClientSite's -// QueryInterface (ie, Site_QueryInterface) and specifying a REFIID of IID_IOleInPlaceSite. - -HRESULT STDMETHODCALLTYPE InPlace_QueryInterface(IOleInPlaceSite FAR* This, REFIID riid, LPVOID FAR* ppvObj) -{ - // The browser assumes that our IOleInPlaceSite object is associated with our IOleClientSite - // object. So it is possible that the browser may call our IOleInPlaceSite's QueryInterface() - // to ask us to return a pointer to our IOleClientSite, in the same way that the browser calls - // our IOleClientSite's QueryInterface() to ask for a pointer to our IOleInPlaceSite. - // - // Rather than duplicate much of the code in IOleClientSite's QueryInterface, let's just get - // a pointer to our _IOleClientSiteEx object, substitute it as the 'This' arg, and call our - // our IOleClientSite's QueryInterface. Note that since our IOleInPlaceSite is embedded right - // inside our _IOleClientSiteEx, and comes immediately after the IOleClientSite, we can employ - // the following trickery to get the pointer to our _IOleClientSiteEx. - 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) -{ - // Return the HWND of the window that contains this browser object. We stored that - // HWND in our _IOleInPlaceSiteEx struct. Nevermind that the function declaration for - // Site_GetWindow says that 'This' is an IOleInPlaceSite *. Remember that in - // EmbedBrowserObject(), we allocated our own _IOleInPlaceSiteEx struct which - // contained an embedded IOleInPlaceSite struct within it. And when the browser - // called Site_QueryInterface() to get a pointer to our IOleInPlaceSite object, we - // returned a pointer to our _IOleClientSiteEx. The browser doesn't know this. But - // we do. That's what we're really being passed, so we can recast it and use it as - // so here. - *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) -{ - // Tell the browser we can in place activate - return(S_OK); -} - -HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceActivate(IOleInPlaceSite FAR* This) -{ - // Tell the browser we did it ok - 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) -{ - // Give the browser the pointer to our IOleInPlaceFrame struct. We stored that pointer - // in our _IOleInPlaceSiteEx struct. Nevermind that the function declaration for - // Site_GetWindowContext says that 'This' is an IOleInPlaceSite *. Remember that in - // EmbedBrowserObject(), we allocated our own _IOleInPlaceSiteEx struct which - // contained an embedded IOleInPlaceSite struct within it. And when the browser - // called Site_QueryInterface() to get a pointer to our IOleInPlaceSite object, we - // returned a pointer to our _IOleClientSiteEx. The browser doesn't know this. But - // we do. That's what we're really being passed, so we can recast it and use it as - // so here. - // - // Actually, we're giving the browser a pointer to our own _IOleInPlaceSiteEx struct, - // but telling the browser that it's a IOleInPlaceSite struct. No problem. Our - // _IOleInPlaceSiteEx starts with an embedded IOleInPlaceSite, so the browser is - // cool with it. And we want the browser to pass a pointer to this _IOleInPlaceSiteEx - // wherever it would pass a IOleInPlaceSite struct to our IOleInPlaceSite functions. - *lplpFrame = (LPOLEINPLACEFRAME)&((_IOleInPlaceSiteEx *)This)->frame; - - // We have no OLEINPLACEUIWINDOW - *lplpDoc = 0; - - // Fill in some other info for the browser - lpFrameInfo->fMDIApp = FALSE; - lpFrameInfo->hwndFrame = ((_IOleInPlaceFrameEx *)*lplpFrame)->window; - lpFrameInfo->haccel = 0; - lpFrameInfo->cAccelEntries = 0; - - // Give the browser the dimensions of where it can draw. We give it our entire window to fill. - // We do this in InPlace_OnPosRectChange() which is called right when a window is first - // created anyway, so no need to duplicate it here. -// GetClientRect(lpFrameInfo->hwndFrame, lprcPosRect); -// GetClientRect(lpFrameInfo->hwndFrame, lprcClipRect); - - 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; -} - -// Called when the position of the browser object is changed, such as when we call the IWebBrowser2's put_Width(), -// put_Height(), put_Left(), or put_Right(). -HRESULT STDMETHODCALLTYPE InPlace_OnPosRectChange(IOleInPlaceSite FAR* This, LPCRECT lprcPosRect) -{ - IOleObject *browserObject; - IOleInPlaceObject *inplace; - - // We need to get the browser's IOleInPlaceObject object so we can call its SetObjectRects - // function. - browserObject = *((IOleObject **)((char *)This - sizeof(IOleObject *) - sizeof(IOleClientSite))); - if (!browserObject->lpVtbl->QueryInterface(browserObject, &IID_IOleInPlaceObject, (void**)&inplace)) - { - // Give the browser the dimensions of where it can draw. - 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) -{ - // Give the browser the HWND to our window that contains the browser object. We - // stored that HWND in our IOleInPlaceFrame struct. Nevermind that the function - // declaration for Frame_GetWindow says that 'This' is an IOleInPlaceFrame *. Remember - // that in EmbedBrowserObject(), we allocated our own IOleInPlaceFrameEx struct which - // contained an embedded IOleInPlaceFrame struct within it. And then we lied when - // Site_GetWindowContext() returned that IOleInPlaceFrameEx. So that's what the - // browser is passing us. It doesn't know that. But we do. So we can recast it and - // use it as so here. - *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 **)GetWindowLong(hwnd, GWL_USERDATA))) - { - // Unembed the browser object, and release its resources. - browserObject = *browserHandle; - browserObject->lpVtbl->Close(browserObject, OLECLOSE_NOSAVE); - browserObject->lpVtbl->Release(browserObject); - - GlobalFree(browserHandle); - - return; - } - - // You must have called this for a window that wasn't successfully passed to EmbedBrowserObject(). - // Bad boy! - _ASSERT(0); -} - - - - - - -#define WEBPAGE_GOBACK 0 -#define WEBPAGE_GOFORWARD 1 -#define WEBPAGE_GOHOME 2 -#define WEBPAGE_SEARCH 3 -#define WEBPAGE_REFRESH 4 -#define WEBPAGE_STOP 5 - -/******************************* DoPageAction() ************************** - * Implements the functionality of a "Back". "Forward", "Home", "Search", - * "Refresh", or "Stop" button. - * - * hwnd = Handle to the window hosting the browser object. - * action = One of the following: - * 0 = Move back to the previously viewed web page. - * 1 = Move forward to the previously viewed web page. - * 2 = Move to the home page. - * 3 = Search. - * 4 = Refresh the page. - * 5 = Stop the currently loading page. - * - * 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. - */ - -void DoPageAction(HWND hwnd, DWORD action) -{ - 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 **)GetWindowLong(hwnd, GWL_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 the desired function - switch (action) - { - case WEBPAGE_GOBACK: - { - // Call the IWebBrowser2 object's GoBack function. - webBrowser2->lpVtbl->GoBack(webBrowser2); - break; - } - - case WEBPAGE_GOFORWARD: - { - // Call the IWebBrowser2 object's GoForward function. - webBrowser2->lpVtbl->GoForward(webBrowser2); - break; - } - - case WEBPAGE_GOHOME: - { - // Call the IWebBrowser2 object's GoHome function. - webBrowser2->lpVtbl->GoHome(webBrowser2); - break; - } - - case WEBPAGE_SEARCH: - { - // Call the IWebBrowser2 object's GoSearch function. - webBrowser2->lpVtbl->GoSearch(webBrowser2); - break; - } - - case WEBPAGE_REFRESH: - { - // Call the IWebBrowser2 object's Refresh function. - webBrowser2->lpVtbl->Refresh(webBrowser2); - break; - } - - case WEBPAGE_STOP: - { - // Call the IWebBrowser2 object's Stop function. - webBrowser2->lpVtbl->Stop(webBrowser2); - break; - } - } - - // Release the IWebBrowser2 object. - webBrowser2->lpVtbl->Release(webBrowser2); - } -} - - - - - -/******************************* 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... - * - *

This is a picture.

- * - * hwnd = Handle to the window hosting the browser object. - * string = Pointer to nul-terminated string containing the HTML BODY. - * (NOTE: No 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 **)GetWindowLong(hwnd, GWL_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)) - { - // 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); -} - - - - - - -/******************************* DisplayHTMLPage() **************************** - * Displays a URL, or HTML file on disk. - * - * hwnd = Handle to the window hosting the browser object. - * webPageName = Pointer to nul-terminated name of the URL/file. - * - * 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 DisplayHTMLPage(HWND hwnd, LPTSTR webPageName) -{ - IWebBrowser2 *webBrowser2; - VARIANT myURL; - 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 **)GetWindowLong(hwnd, GWL_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. - - // Our URL (ie, web address, such as "http://www.microsoft.com" or an HTM filename on disk - // such as "c:\myfile.htm") must be passed to the IWebBrowser2's Navigate2() function as a BSTR. - // A BSTR is like a pascal version of a double-byte character string. In other words, the - // first unsigned short is a count of how many characters are in the string, and then this - // is followed by those characters, each expressed as an unsigned short (rather than a - // char). The string is not nul-terminated. The OS function SysAllocString can allocate and - // copy a UNICODE C string to a BSTR. Of course, we'll need to free that BSTR after we're done - // with it. If we're not using UNICODE, we first have to convert to a UNICODE string. - // - // What's more, our BSTR needs to be stuffed into a VARIENT struct, and that VARIENT struct is - // then passed to Navigate2(). Why? The VARIENT struct makes it possible to define generic - // 'datatypes' that can be used with all languages. Not all languages support things like - // nul-terminated C strings. So, by using a VARIENT, whose first field tells what sort of - // data (ie, string, float, etc) is in the VARIENT, COM interfaces can be used by just about - // any language. - VariantInit(&myURL); - myURL.vt = VT_BSTR; - -#ifndef UNICODE - { - wchar_t *buffer; - DWORD size; - - size = MultiByteToWideChar(CP_ACP, 0, webPageName, -1, 0, 0); - if (!(buffer = (wchar_t *)GlobalAlloc(GMEM_FIXED, sizeof(wchar_t) * size))) goto badalloc; - MultiByteToWideChar(CP_ACP, 0, webPageName, -1, buffer, size); - myURL.bstrVal = SysAllocString(buffer); - GlobalFree(buffer); - } -#else - myURL.bstrVal = SysAllocString(webPageName); -#endif - if (!myURL.bstrVal) - { -badalloc: webBrowser2->lpVtbl->Release(webBrowser2); - return(-6); - } - - // Call the Navigate2() function to actually display the page. - webBrowser2->lpVtbl->Navigate2(webBrowser2, &myURL, 0, 0, 0, 0); - - // Free any resources (including the BSTR we allocated above). - VariantClear(&myURL); - - // 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); - - // Success - return(0); - } - - return(-5); -} - - - - - -/******************************* 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 **)GetWindowLong(hwnd, GWL_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) -{ - HRESULT hr; - 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; - hr = - CoGetClassObject( - &CLSID_WebBrowser, - CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, NULL, &IID_IClassFactory, (void **)&pClassFactory) && pClassFactory; - - if (!hr||!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; - SetWindowLong(hwnd, GWL_USERDATA, (LONG)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 WebBrowser_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); - - // Another window created with an embedded browser object - - // Success - return(0); - } - - case WM_DESTROY: - { - // Detach the browser object from this window, and free resources. - UnEmbedBrowserObject(hwnd); - return(TRUE); - } - - - } - - return(DefWindowProc(hwnd, uMsg, wParam, lParam)); -} - -static const char* WEBBROWSER_CLASSNAME = "WEBBROWSER"; -static HINSTANCE gs_hInstance = NULL; -static HWND gs_hWndWebBrowser = NULL; -static HWND gs_hWndParent = NULL; - - -int WebBrowser_Show(HWND hParent, const char* addr, const RECT* rc) -{ - if (gs_hWndWebBrowser) - return 0; - - gs_hWndParent = hParent; - gs_hWndWebBrowser = CreateWindowEx(0, WEBBROWSER_CLASSNAME, "web browser", WS_CHILD|WS_VISIBLE, - rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, - hParent, NULL, gs_hInstance, 0); - - if (!gs_hWndWebBrowser) - return 0; - - DisplayHTMLPage(gs_hWndWebBrowser, (LPTSTR)addr); - - ShowWindow(gs_hWndWebBrowser, SW_SHOW); - UpdateWindow(gs_hWndWebBrowser); - - SetFocus(gs_hWndWebBrowser); - return 1; -} - -void WebBrowser_Move(const RECT* rc) -{ - MoveWindow(gs_hWndWebBrowser, rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, 1 ); -} - -void WebBrowser_Hide() -{ - if (!gs_hWndWebBrowser) - return; - - ShowWindow(gs_hWndWebBrowser, SW_HIDE); - - if (IsWindow(gs_hWndWebBrowser)) - DestroyWindow(gs_hWndWebBrowser); - gs_hWndWebBrowser = NULL; - - SetFocus(gs_hWndParent); -} - -int WebBrowser_IsVisible() -{ - return (gs_hWndWebBrowser != NULL); -} - -void WebBrowser_Destroy() -{ - WebBrowser_Hide(); -} - -int WebBrowser_Startup(HINSTANCE hInstance) -{ - if (OleInitialize(NULL) != S_OK) - { - return 0; - } - - { - WNDCLASSEX wc; - ZeroMemory(&wc, sizeof(WNDCLASSEX)); - wc.cbSize = sizeof(WNDCLASSEX); - wc.hInstance = hInstance; - wc.lpfnWndProc = WebBrowser_WindowProc; - wc.lpszClassName = WEBBROWSER_CLASSNAME; - RegisterClassEx(&wc); - } - gs_hInstance = hInstance; - return 1; -} - -void WebBrowser_Cleanup() -{ - if (gs_hInstance) - UnregisterClass(WEBBROWSER_CLASSNAME, gs_hInstance); - - OleUninitialize(); -} +//#include +//#include // Defines of stuff like IWebBrowser2. This is an include file with Visual C 6 and above +//#include // Defines of stuff like IHTMLDocument2. This is an include file with Visual C 6 and above +//#include // Defines of stuff like IDocHostUIHandler. This is an include file with Visual C 6 and above +////#include // for _ASSERT() +// +//#define _ASSERT(x) +// +// +// +//// A running count of how many windows we have open that contain a browser object +//unsigned char WindowCount = 0; +// +//// The class name of our Window to host the browser. It can be anything of your choosing. +//static const TCHAR ClassName[] = "Browser Example"; +// +//// This is used by DisplayHTMLStr(). It can be global because we never change it. +//static const SAFEARRAYBOUND ArrayBound = {1, 0}; +// +// +// +// +// +// +// +// +// +// +//// Our IOleInPlaceFrame functions that the browser may call +//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); +// +//// Our IOleInPlaceFrame VTable. This is the array of pointers to the above functions in our C +//// program that the browser may call in order to interact with our frame window that contains +//// the browser object. We must define a particular set of functions that comprise the +//// IOleInPlaceFrame set of functions (see above), and then stuff pointers to those functions +//// in their respective 'slots' in this table. We want the browser to use this VTable with our +//// IOleInPlaceFrame structure. +//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}; +// +//// We need to return an IOleInPlaceFrame struct to the browser object. And one of our IOleInPlaceFrame +//// functions (Frame_GetWindow) is going to need to access our window handle. So let's create our own +//// struct that starts off with an IOleInPlaceFrame struct (and that's important -- the IOleInPlaceFrame +//// struct *must* be first), and then has an extra data field where we can store our own window's HWND. +//// +//// And because we may want to create multiple windows, each hosting its own browser object (to +//// display its own web page), then we need to create a IOleInPlaceFrame struct for each window. So, +//// we're not going to declare our IOleInPlaceFrame struct globally. We'll allocate it later using +//// GlobalAlloc, and then stuff the appropriate HWND in it then, and also stuff a pointer to +//// MyIOleInPlaceFrameTable in it. But let's just define it here. +//typedef struct { +// IOleInPlaceFrame frame; // The IOleInPlaceFrame must be first! +// +// /////////////////////////////////////////////////// +// // Here you add any extra variables that you need +// // to access in your IOleInPlaceFrame functions. +// // You don't want those functions to access global +// // variables, because then you couldn't use more +// // than one browser object. (ie, You couldn't have +// // multiple windows, each with its own embedded +// // browser object to display a different web page). +// // +// // So here is where I added my extra HWND that my +// // IOleInPlaceFrame function Frame_GetWindow() needs +// // to access. +// /////////////////////////////////////////////////// +// HWND window; +//} _IOleInPlaceFrameEx; +// +// +// +// +// +// +//// Our IOleClientSite functions that the browser may call +//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); +// +//// Our IOleClientSite VTable. This is the array of pointers to the above functions in our C +//// program that the browser may call in order to interact with our frame window that contains +//// the browser object. We must define a particular set of functions that comprise the +//// IOleClientSite set of functions (see above), and then stuff pointers to those functions +//// in their respective 'slots' in this table. We want the browser to use this VTable with our +//// IOleClientSite structure. +//IOleClientSiteVtbl MyIOleClientSiteTable = {Site_QueryInterface, +//Site_AddRef, +//Site_Release, +//Site_SaveObject, +//Site_GetMoniker, +//Site_GetContainer, +//Site_ShowObject, +//Site_OnShowWindow, +//Site_RequestNewObjectLayout}; +// +// +// +// +// +// +//// Our IDocHostUIHandler functions that the browser may call +//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); +// +//// Our IDocHostUIHandler VTable. This is the array of pointers to the above functions in our C +//// program that the browser may call in order to replace/set certain user interface considerations +//// (such as whether to display a pop-up context menu when the user right-clicks on the embedded +//// browser object). We must define a particular set of functions that comprise the +//// IDocHostUIHandler set of functions (see above), and then stuff pointers to those functions +//// in their respective 'slots' in this table. We want the browser to use this VTable with our +//// IDocHostUIHandler structure. +//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}; +// +//// We'll allocate our IDocHostUIHandler object dynamically with GlobalAlloc() for reasons outlined later. +// +// +// +//// Our IOleInPlaceSite functions that the browser may call +//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); +// +//// Our IOleInPlaceSite VTable. This is the array of pointers to the above functions in our C +//// program that the browser may call in order to interact with our frame window that contains +//// the browser object. We must define a particular set of functions that comprise the +//// IOleInPlaceSite set of functions (see above), and then stuff pointers to those functions +//// in their respective 'slots' in this table. We want the browser to use this VTable with our +//// IOleInPlaceSite structure. +//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}; +// +//// We need to pass our IOleClientSite structure to OleCreate (which in turn gives it to the browser). +//// But the browser is also going to ask our IOleClientSite's QueryInterface() to return a pointer to +//// our IOleInPlaceSite and/or IDocHostUIHandler structs. So we'll need to have those pointers handy. +//// Plus, some of our IOleClientSite and IOleInPlaceSite functions will need to have the HWND to our +//// window, and also a pointer to our IOleInPlaceFrame struct. So let's create a single struct that +//// has the IOleClientSite, IOleInPlaceSite, IDocHostUIHandler, and IOleInPlaceFrame structs all inside +//// it (so we can easily get a pointer to any one from any of those structs' functions). As long as the +//// IOleClientSite struct is the very first thing in this custom struct, it's all ok. We can still pass +//// it to OleCreate() and pretend that it's an ordinary IOleClientSite. We'll call this new struct a +//// _IOleClientSiteEx. +//// +//// And because we may want to create multiple windows, each hosting its own browser object (to +//// display its own web page), then we need to create a unique _IOleClientSiteEx struct for +//// each window. So, we're not going to declare this struct globally. We'll allocate it later +//// using GlobalAlloc, and then initialize the structs within it. +// +//typedef struct { +// IOleInPlaceSite inplace; // My IOleInPlaceSite object. Must be first with in _IOleInPlaceSiteEx. +// +// /////////////////////////////////////////////////// +// // Here you add any extra variables that you need +// // to access in your IOleInPlaceSite functions. +// // +// // So here is where I added my IOleInPlaceFrame +// // struct. If you need extra variables, add them +// // at the end. +// /////////////////////////////////////////////////// +// _IOleInPlaceFrameEx frame; // My IOleInPlaceFrame object. Must be first within my _IOleInPlaceFrameEx +//} _IOleInPlaceSiteEx; +// +//typedef struct { +// IDocHostUIHandler ui; // My IDocHostUIHandler object. Must be first. +// +// /////////////////////////////////////////////////// +// // Here you add any extra variables that you need +// // to access in your IDocHostUIHandler functions. +// /////////////////////////////////////////////////// +//} _IDocHostUIHandlerEx; +// +//typedef struct { +// IOleClientSite client; // My IOleClientSite object. Must be first. +// _IOleInPlaceSiteEx inplace; // My IOleInPlaceSite object. A convenient place to put it. +// _IDocHostUIHandlerEx ui; // My IDocHostUIHandler object. Must be first within my _IDocHostUIHandlerEx. +// +// /////////////////////////////////////////////////// +// // Here you add any extra variables that you need +// // to access in your IOleClientSite functions. +// /////////////////////////////////////////////////// +//} _IOleClientSiteEx; +// +// +// +// +// +// +// +// +// +// +// +// +// +//// This is a simple C example. There are lots more things you can control about the browser object, but +//// we don't do it in this example. _Many_ of the functions we provide below for the browser to call, will +//// never actually be called by the browser in our example. Why? Because we don't do certain things +//// with the browser that would require it to call those functions (even though we need to provide +//// at least some stub for all of the functions). +//// +//// So, for these "dummy functions" that we don't expect the browser to call, we'll just stick in some +//// assembly code that causes a debugger breakpoint and tells the browser object that we don't support +//// the functionality. That way, if you try to do more things with the browser object, and it starts +//// calling these "dummy functions", you'll know which ones you should add more meaningful code to. +//#define NOTIMPLEMENTED _ASSERT(0); return(E_NOTIMPL) +// +// +// +// +// +////////////////////////////////////// My IDocHostUIHandler functions ////////////////////////////////////// +//// The browser object asks us for the pointer to our IDocHostUIHandler object by calling our IOleClientSite's +//// QueryInterface (ie, Site_QueryInterface) and specifying a REFIID of IID_IDocHostUIHandler. +//// +//// NOTE: You need at least IE 4.0. Previous versions do not ask for, nor utilize, our IDocHostUIHandler functions. +// +//HRESULT STDMETHODCALLTYPE UI_QueryInterface(IDocHostUIHandler FAR* This, REFIID riid, LPVOID FAR* ppvObj) +//{ +// // The browser assumes that our IDocHostUIHandler object is associated with our IOleClientSite +// // object. So it is possible that the browser may call our IDocHostUIHandler's QueryInterface() +// // to ask us to return a pointer to our IOleClientSite, in the same way that the browser calls +// // our IOleClientSite's QueryInterface() to ask for a pointer to our IDocHostUIHandler. +// // +// // Rather than duplicate much of the code in IOleClientSite's QueryInterface, let's just get +// // a pointer to our _IOleClientSiteEx object, substitute it as the 'This' arg, and call our +// // our IOleClientSite's QueryInterface. Note that since our _IDocHostUIHandlerEx is embedded right +// // inside our _IOleClientSiteEx, and comes immediately after the _IOleInPlaceSiteEx, we can employ +// // the following trickery to get the pointer to our _IOleClientSiteEx. +// 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); +//} +// +//// Called when the browser object is about to display its context menu. +//HRESULT STDMETHODCALLTYPE UI_ShowContextMenu(IDocHostUIHandler FAR* This, DWORD dwID, POINT __RPC_FAR *ppt, IUnknown __RPC_FAR *pcmdtReserved, IDispatch __RPC_FAR *pdispReserved) +//{ +// // If desired, we can pop up your own custom context menu here. Of course, +// // we would need some way to get our window handle, so what we'd probably +// // do is like what we did with our IOleInPlaceFrame object. We'd define and create +// // our own IDocHostUIHandlerEx object with an embedded IDocHostUIHandler at the +// // start of it. Then we'd add an extra HWND field to store our window handle. +// // It could look like this: +// // +// // typedef struct _IDocHostUIHandlerEx { +// // IDocHostUIHandler ui; // The IDocHostUIHandler must be first! +// // HWND window; +// // } IDocHostUIHandlerEx; +// // +// // Of course, we'd need a unique IDocHostUIHandlerEx object for each window, so +// // EmbedBrowserObject() would have to allocate one of those too. And that's +// // what we'd pass to our browser object (and it would in turn pass it to us +// // here, instead of 'This' being a IDocHostUIHandler *). +// +// // We will return S_OK to tell the browser not to display its default context menu, +// // or return S_FALSE to let the browser show its default context menu. For this +// // example, we wish to disable the browser's default context menu. +// return(S_OK); +//} +// +//// Called at initialization of the browser object UI. We can set various features of the browser object here. +//HRESULT STDMETHODCALLTYPE UI_GetHostInfo(IDocHostUIHandler FAR* This, DOCHOSTUIINFO __RPC_FAR *pInfo) +//{ +// pInfo->cbSize = sizeof(DOCHOSTUIINFO); +// +// // Set some flags. We don't want any 3D border. You can do other things like hide +// // the scroll bar (DOCHOSTUIFLAG_SCROLL_NO), display picture display (DOCHOSTUIFLAG_NOPICS), +// // disable any script running when the page is loaded (DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE), +// // open a site in a new browser window when the user clicks on some link (DOCHOSTUIFLAG_OPENNEWWIN), +// // and lots of other things. See the MSDN docs on the DOCHOSTUIINFO struct passed to us. +// pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER; +// +// // Set what happens when the user double-clicks on the object. Here we use the default. +// pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; +// +// return(S_OK); +//} +// +//// Called when the browser object shows its UI. This allows us to replace its menus and toolbars by creating our +//// own and displaying them here. +//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) +//{ +// // We've already got our own UI in place so just return S_OK to tell the browser +// // not to display its menus/toolbars. Otherwise we'd return S_FALSE to let it do +// // that. +// return(S_OK); +//} +// +//// Called when browser object hides its UI. This allows us to hide any menus/toolbars we created in ShowUI. +//HRESULT STDMETHODCALLTYPE UI_HideUI(IDocHostUIHandler FAR* This) +//{ +// return(S_OK); +//} +// +//// Called when the browser object wants to notify us that the command state has changed. We should update any +//// controls we have that are dependent upon our embedded object, such as "Back", "Forward", "Stop", or "Home" +//// buttons. +//HRESULT STDMETHODCALLTYPE UI_UpdateUI(IDocHostUIHandler FAR* This) +//{ +// // We update our UI in our window message loop so we don't do anything here. +// return(S_OK); +//} +// +//// Called from the browser object's IOleInPlaceActiveObject object's EnableModeless() function. Also +//// called when the browser displays a modal dialog box. +//HRESULT STDMETHODCALLTYPE UI_EnableModeless(IDocHostUIHandler FAR* This, BOOL fEnable) +//{ +// return(S_OK); +//} +// +//// Called from the browser object's IOleInPlaceActiveObject object's OnDocWindowActivate() function. +//// This informs off of when the object is getting/losing the focus. +//HRESULT STDMETHODCALLTYPE UI_OnDocWindowActivate(IDocHostUIHandler FAR* This, BOOL fActivate) +//{ +// return(S_OK); +//} +// +//// Called from the browser object's IOleInPlaceActiveObject object's OnFrameWindowActivate() function. +//HRESULT STDMETHODCALLTYPE UI_OnFrameWindowActivate(IDocHostUIHandler FAR* This, BOOL fActivate) +//{ +// return(S_OK); +//} +// +//// Called from the browser object's IOleInPlaceActiveObject object's ResizeBorder() function. +//HRESULT STDMETHODCALLTYPE UI_ResizeBorder(IDocHostUIHandler FAR* This, LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR *pUIWindow, BOOL fRameWindow) +//{ +// return(S_OK); +//} +// +//// Called from the browser object's TranslateAccelerator routines to translate key strokes to commands. +//HRESULT STDMETHODCALLTYPE UI_TranslateAccelerator(IDocHostUIHandler FAR* This, LPMSG lpMsg, const GUID __RPC_FAR *pguidCmdGroup, DWORD nCmdID) +//{ +// // We don't intercept any keystrokes, so we do nothing here. But for example, if we wanted to +// // override the TAB key, perhaps do something with it ourselves, and then tell the browser +// // not to do anything with this keystroke, we'd do: +// // +// // if (pMsg && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB) +// // { +// // // Here we do something as a result of a TAB key press. +// // +// // // Tell the browser not to do anything with it. +// // return(S_FALSE); +// // } +// // +// // // Otherwise, let the browser do something with this message. +// // return(S_OK); +// +// // For our example, we want to make sure that the user can invoke some key to popup the context +// // menu, so we'll tell it to ignore all messages. +// return(S_FALSE); +//} +// +//// Called by the browser object to find where the host wishes the browser to get its options in the registry. +//// We can use this to prevent the browser from using its default settings in the registry, by telling it to use +//// some other registry key we've setup with the options we want. +//HRESULT STDMETHODCALLTYPE UI_GetOptionKeyPath(IDocHostUIHandler FAR* This, LPOLESTR __RPC_FAR *pchKey, DWORD dw) +//{ +// // Let the browser use its default registry settings. +// return(S_FALSE); +//} +// +//// Called by the browser object when it is used as a drop target. We can supply our own IDropTarget object, +//// IDropTarget functions, and IDropTarget VTable if we want to determine what happens when someone drags and +//// drops some object on our embedded browser object. +//HRESULT STDMETHODCALLTYPE UI_GetDropTarget(IDocHostUIHandler FAR* This, IDropTarget __RPC_FAR *pDropTarget, IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget) +//{ +// // Return our IDropTarget object associated with this IDocHostUIHandler object. I don't +// // know why we don't do this via UI_QueryInterface(), but we don't. +// +// // NOTE: If we want/need an IDropTarget interface, then we would have had to setup our own +// // IDropTarget functions, IDropTarget VTable, and create an IDropTarget object. We'd want to put +// // a pointer to the IDropTarget object in our own custom IDocHostUIHandlerEx object (like how +// // we may add an HWND field for the use of UI_ShowContextMenu). So when we created our +// // IDocHostUIHandlerEx object, maybe we'd add a 'idrop' field to the end of it, and +// // store a pointer to our IDropTarget object there. Then we could return this pointer as so: +// // +// // *pDropTarget = ((IDocHostUIHandlerEx FAR *)This)->idrop; +// // return(S_OK); +// +// // But for our purposes, we don't need an IDropTarget object, so we'll tell whomever is calling +// // us that we don't have one. +// return(S_FALSE); +//} +// +//// Called by the browser when it wants a pointer to our IDispatch object. This object allows us to expose +//// our own automation interface (ie, our own COM objects) to other entities that are running within the +//// context of the browser so they can call our functions if they want. An example could be a javascript +//// running in the URL we display could call our IDispatch functions. We'd write them so that any args passed +//// to them would use the generic datatypes like a BSTR for utmost flexibility. +//HRESULT STDMETHODCALLTYPE UI_GetExternal(IDocHostUIHandler FAR* This, IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) +//{ +// // Return our IDispatch object associated with this IDocHostUIHandler object. I don't +// // know why we don't do this via UI_QueryInterface(), but we don't. +// +// // NOTE: If we want/need an IDispatch interface, then we would have had to setup our own +// // IDispatch functions, IDispatch VTable, and create an IDispatch object. We'd want to put +// // a pointer to the IDispatch object in our custom _IDocHostUIHandlerEx object (like how +// // we may add an HWND field for the use of UI_ShowContextMenu). So when we defined our +// // _IDocHostUIHandlerEx object, maybe we'd add a 'idispatch' field to the end of it, and +// // store a pointer to our IDispatch object there. Then we could return this pointer as so: +// // +// // *ppDispatch = ((_IDocHostUIHandlerEx FAR *)This)->idispatch; +// // return(S_OK); +// +// // But for our purposes, we don't need an IDispatch object, so we'll tell whomever is calling +// // us that we don't have one. Note: We must set ppDispatch to 0 if we don't return our own +// // IDispatch object. +// *ppDispatch = 0; +// return(S_FALSE); +//} +// +//// Called by the browser object to give us an opportunity to modify the URL to be loaded. +//HRESULT STDMETHODCALLTYPE UI_TranslateUrl(IDocHostUIHandler FAR* This, DWORD dwTranslate, OLECHAR __RPC_FAR *pchURLIn, OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut) +//{ +// // We don't need to modify the URL. Note: We need to set ppchURLOut to 0 if we don't +// // return an OLECHAR (buffer) containing a modified version of pchURLIn. +// *ppchURLOut = 0; +// return(S_FALSE); +//} +// +//// Called by the browser when it does cut/paste to the clipboard. This allows us to block certain clipboard +//// formats or support additional clipboard formats. +//HRESULT STDMETHODCALLTYPE UI_FilterDataObject(IDocHostUIHandler FAR* This, IDataObject __RPC_FAR *pDO, IDataObject __RPC_FAR *__RPC_FAR *ppDORet) +//{ +// // Return our IDataObject object associated with this IDocHostUIHandler object. I don't +// // know why we don't do this via UI_QueryInterface(), but we don't. +// +// // NOTE: If we want/need an IDataObject interface, then we would have had to setup our own +// // IDataObject functions, IDataObject VTable, and create an IDataObject object. We'd want to put +// // a pointer to the IDataObject object in our custom _IDocHostUIHandlerEx object (like how +// // we may add an HWND field for the use of UI_ShowContextMenu). So when we defined our +// // _IDocHostUIHandlerEx object, maybe we'd add a 'idata' field to the end of it, and +// // store a pointer to our IDataObject object there. Then we could return this pointer as so: +// // +// // *ppDORet = ((_IDocHostUIHandlerEx FAR *)This)->idata; +// // return(S_OK); +// +// // But for our purposes, we don't need an IDataObject object, so we'll tell whomever is calling +// // us that we don't have one. Note: We must set ppDORet to 0 if we don't return our own +// // IDataObject object. +// *ppDORet = 0; +// return(S_FALSE); +//} +// +// +// +// +// +// +// +// +// +// +// +// +// +//////////////////////////////////////// My IOleClientSite functions ///////////////////////////////////// +//// We give the browser object a pointer to our IOleClientSite object when we call OleCreate() or DoVerb(). +// +///************************* Site_QueryInterface() ************************* +// * The browser object calls this when it wants a pointer to one of our +// * IOleClientSite, IDocHostUIHandler, or IOleInPlaceSite structures. They +// * are all accessible via the _IOleClientSiteEx struct we allocated in +// * EmbedBrowserObject() and passed to DoVerb() and OleCreate(). +// * +// * This = A pointer to whatever _IOleClientSiteEx struct we passed to +// * OleCreate() or DoVerb(). +// * riid = A GUID struct that the browser passes us to clue us as to +// * which type of struct (object) it would like a pointer +// * returned for. +// * ppvObject = Where the browser wants us to return a pointer to the +// * appropriate struct. (ie, It passes us a handle to fill in). +// * +// * RETURNS: S_OK if we return the struct, or E_NOINTERFACE if we don't have +// * the requested struct. +// */ +// +//HRESULT STDMETHODCALLTYPE Site_QueryInterface(IOleClientSite FAR* This, REFIID riid, void ** ppvObject) +//{ +// // It just so happens that the first arg passed to us is our _IOleClientSiteEx struct we allocated +// // and passed to DoVerb() and OleCreate(). Nevermind that 'This' is declared is an IOleClientSite *. +// // Remember that in EmbedBrowserObject(), we allocated our own _IOleClientSiteEx struct, and lied +// // to OleCreate() and DoVerb() -- passing our _IOleClientSiteEx struct and saying it was an +// // IOleClientSite struct. It's ok. An _IOleClientSiteEx starts with an embedded IOleClientSite, so +// // the browser didn't mind. So that's what the browser object is passing us now. The browser doesn't +// // know that it's really an _IOleClientSiteEx struct. But we do. So we can recast it and use it as +// // so here. +// +// // If the browser is asking us to match IID_IOleClientSite, then it wants us to return a pointer to +// // our IOleClientSite struct. Then the browser will use the VTable in that struct to call our +// // IOleClientSite functions. It will also pass this same pointer to all of our IOleClientSite +// // functions. +// // +// // Actually, we're going to lie to the browser again. We're going to return our own _IOleClientSiteEx +// // struct, and tell the browser that it's a IOleClientSite struct. It's ok. The first thing in our +// // _IOleClientSiteEx is an embedded IOleClientSite, so the browser doesn't mind. We want the browser +// // to continue passing our _IOleClientSiteEx pointer wherever it would normally pass a IOleClientSite +// // pointer. +// // +// // The IUnknown interface uses the same VTable as the first object in our _IOleClientSiteEx +// // struct (which happens to be an IOleClientSite). So if the browser is asking us to match +// // IID_IUnknown, then we'll also return a pointer to our _IOleClientSiteEx. +// +// if (!memcmp(riid, &IID_IUnknown, sizeof(GUID)) || !memcmp(riid, &IID_IOleClientSite, sizeof(GUID))) +// *ppvObject = &((_IOleClientSiteEx *)This)->client; +// +// // If the browser is asking us to match IID_IOleInPlaceSite, then it wants us to return a pointer to +// // our IOleInPlaceSite struct. Then the browser will use the VTable in that struct to call our +// // IOleInPlaceSite functions. It will also pass this same pointer to all of our IOleInPlaceSite +// // functions (except for Site_QueryInterface, Site_AddRef, and Site_Release. Those will always get +// // the pointer to our _IOleClientSiteEx. +// // +// // Actually, we're going to lie to the browser. We're going to return our own _IOleInPlaceSiteEx +// // struct, and tell the browser that it's a IOleInPlaceSite struct. It's ok. The first thing in +// // our _IOleInPlaceSiteEx is an embedded IOleInPlaceSite, so the browser doesn't mind. We want the +// // browser to continue passing our _IOleInPlaceSiteEx pointer wherever it would normally pass a +// // IOleInPlaceSite pointer. +// else if (!memcmp(riid, &IID_IOleInPlaceSite, sizeof(GUID))) +// *ppvObject = &((_IOleClientSiteEx *)This)->inplace; +// +// // If the browser is asking us to match IID_IDocHostUIHandler, then it wants us to return a pointer to +// // our IDocHostUIHandler struct. Then the browser will use the VTable in that struct to call our +// // IDocHostUIHandler functions. It will also pass this same pointer to all of our IDocHostUIHandler +// // functions (except for Site_QueryInterface, Site_AddRef, and Site_Release. Those will always get +// // the pointer to our _IOleClientSiteEx. +// // +// // Actually, we're going to lie to the browser. We're going to return our own _IDocHostUIHandlerEx +// // struct, and tell the browser that it's a IDocHostUIHandler struct. It's ok. The first thing in +// // our _IDocHostUIHandlerEx is an embedded IDocHostUIHandler, so the browser doesn't mind. We want the +// // browser to continue passing our _IDocHostUIHandlerEx pointer wherever it would normally pass a +// // IDocHostUIHandler pointer. My, we're really playing dirty tricks on the browser here. heheh. +// else if (!memcmp(riid, &IID_IDocHostUIHandler, sizeof(GUID))) +// *ppvObject = &((_IOleClientSiteEx *)This)->ui; +// +// // For other types of objects the browser wants, just report that we don't have any such objects. +// // NOTE: If you want to add additional functionality to your browser hosting, you may need to +// // provide some more objects here. You'll have to investigate what the browser is asking for +// // (ie, what REFIID it is passing). +// 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) +//{ +// // Tell the browser that we are a simple object and don't support a container +// *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 ///////////////////////////////////// +//// The browser object asks us for the pointer to our IOleInPlaceSite object by calling our IOleClientSite's +//// QueryInterface (ie, Site_QueryInterface) and specifying a REFIID of IID_IOleInPlaceSite. +// +//HRESULT STDMETHODCALLTYPE InPlace_QueryInterface(IOleInPlaceSite FAR* This, REFIID riid, LPVOID FAR* ppvObj) +//{ +// // The browser assumes that our IOleInPlaceSite object is associated with our IOleClientSite +// // object. So it is possible that the browser may call our IOleInPlaceSite's QueryInterface() +// // to ask us to return a pointer to our IOleClientSite, in the same way that the browser calls +// // our IOleClientSite's QueryInterface() to ask for a pointer to our IOleInPlaceSite. +// // +// // Rather than duplicate much of the code in IOleClientSite's QueryInterface, let's just get +// // a pointer to our _IOleClientSiteEx object, substitute it as the 'This' arg, and call our +// // our IOleClientSite's QueryInterface. Note that since our IOleInPlaceSite is embedded right +// // inside our _IOleClientSiteEx, and comes immediately after the IOleClientSite, we can employ +// // the following trickery to get the pointer to our _IOleClientSiteEx. +// 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) +//{ +// // Return the HWND of the window that contains this browser object. We stored that +// // HWND in our _IOleInPlaceSiteEx struct. Nevermind that the function declaration for +// // Site_GetWindow says that 'This' is an IOleInPlaceSite *. Remember that in +// // EmbedBrowserObject(), we allocated our own _IOleInPlaceSiteEx struct which +// // contained an embedded IOleInPlaceSite struct within it. And when the browser +// // called Site_QueryInterface() to get a pointer to our IOleInPlaceSite object, we +// // returned a pointer to our _IOleClientSiteEx. The browser doesn't know this. But +// // we do. That's what we're really being passed, so we can recast it and use it as +// // so here. +// *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) +//{ +// // Tell the browser we can in place activate +// return(S_OK); +//} +// +//HRESULT STDMETHODCALLTYPE InPlace_OnInPlaceActivate(IOleInPlaceSite FAR* This) +//{ +// // Tell the browser we did it ok +// 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) +//{ +// // Give the browser the pointer to our IOleInPlaceFrame struct. We stored that pointer +// // in our _IOleInPlaceSiteEx struct. Nevermind that the function declaration for +// // Site_GetWindowContext says that 'This' is an IOleInPlaceSite *. Remember that in +// // EmbedBrowserObject(), we allocated our own _IOleInPlaceSiteEx struct which +// // contained an embedded IOleInPlaceSite struct within it. And when the browser +// // called Site_QueryInterface() to get a pointer to our IOleInPlaceSite object, we +// // returned a pointer to our _IOleClientSiteEx. The browser doesn't know this. But +// // we do. That's what we're really being passed, so we can recast it and use it as +// // so here. +// // +// // Actually, we're giving the browser a pointer to our own _IOleInPlaceSiteEx struct, +// // but telling the browser that it's a IOleInPlaceSite struct. No problem. Our +// // _IOleInPlaceSiteEx starts with an embedded IOleInPlaceSite, so the browser is +// // cool with it. And we want the browser to pass a pointer to this _IOleInPlaceSiteEx +// // wherever it would pass a IOleInPlaceSite struct to our IOleInPlaceSite functions. +// *lplpFrame = (LPOLEINPLACEFRAME)&((_IOleInPlaceSiteEx *)This)->frame; +// +// // We have no OLEINPLACEUIWINDOW +// *lplpDoc = 0; +// +// // Fill in some other info for the browser +// lpFrameInfo->fMDIApp = FALSE; +// lpFrameInfo->hwndFrame = ((_IOleInPlaceFrameEx *)*lplpFrame)->window; +// lpFrameInfo->haccel = 0; +// lpFrameInfo->cAccelEntries = 0; +// +// // Give the browser the dimensions of where it can draw. We give it our entire window to fill. +// // We do this in InPlace_OnPosRectChange() which is called right when a window is first +// // created anyway, so no need to duplicate it here. +//// GetClientRect(lpFrameInfo->hwndFrame, lprcPosRect); +//// GetClientRect(lpFrameInfo->hwndFrame, lprcClipRect); +// +// 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; +//} +// +//// Called when the position of the browser object is changed, such as when we call the IWebBrowser2's put_Width(), +//// put_Height(), put_Left(), or put_Right(). +//HRESULT STDMETHODCALLTYPE InPlace_OnPosRectChange(IOleInPlaceSite FAR* This, LPCRECT lprcPosRect) +//{ +// IOleObject *browserObject; +// IOleInPlaceObject *inplace; +// +// // We need to get the browser's IOleInPlaceObject object so we can call its SetObjectRects +// // function. +// browserObject = *((IOleObject **)((char *)This - sizeof(IOleObject *) - sizeof(IOleClientSite))); +// if (!browserObject->lpVtbl->QueryInterface(browserObject, &IID_IOleInPlaceObject, (void**)&inplace)) +// { +// // Give the browser the dimensions of where it can draw. +// 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) +//{ +// // Give the browser the HWND to our window that contains the browser object. We +// // stored that HWND in our IOleInPlaceFrame struct. Nevermind that the function +// // declaration for Frame_GetWindow says that 'This' is an IOleInPlaceFrame *. Remember +// // that in EmbedBrowserObject(), we allocated our own IOleInPlaceFrameEx struct which +// // contained an embedded IOleInPlaceFrame struct within it. And then we lied when +// // Site_GetWindowContext() returned that IOleInPlaceFrameEx. So that's what the +// // browser is passing us. It doesn't know that. But we do. So we can recast it and +// // use it as so here. +// *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; +// } +// +// // You must have called this for a window that wasn't successfully passed to EmbedBrowserObject(). +// // Bad boy! +// _ASSERT(0); +//} +// +// +// +// +// +// +//#define WEBPAGE_GOBACK 0 +//#define WEBPAGE_GOFORWARD 1 +//#define WEBPAGE_GOHOME 2 +//#define WEBPAGE_SEARCH 3 +//#define WEBPAGE_REFRESH 4 +//#define WEBPAGE_STOP 5 +// +///******************************* DoPageAction() ************************** +// * Implements the functionality of a "Back". "Forward", "Home", "Search", +// * "Refresh", or "Stop" button. +// * +// * hwnd = Handle to the window hosting the browser object. +// * action = One of the following: +// * 0 = Move back to the previously viewed web page. +// * 1 = Move forward to the previously viewed web page. +// * 2 = Move to the home page. +// * 3 = Search. +// * 4 = Refresh the page. +// * 5 = Stop the currently loading page. +// * +// * 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. +// */ +// +//void DoPageAction(HWND hwnd, DWORD action) +//{ +// 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 the desired function +// switch (action) +// { +// case WEBPAGE_GOBACK: +// { +// // Call the IWebBrowser2 object's GoBack function. +// webBrowser2->lpVtbl->GoBack(webBrowser2); +// break; +// } +// +// case WEBPAGE_GOFORWARD: +// { +// // Call the IWebBrowser2 object's GoForward function. +// webBrowser2->lpVtbl->GoForward(webBrowser2); +// break; +// } +// +// case WEBPAGE_GOHOME: +// { +// // Call the IWebBrowser2 object's GoHome function. +// webBrowser2->lpVtbl->GoHome(webBrowser2); +// break; +// } +// +// case WEBPAGE_SEARCH: +// { +// // Call the IWebBrowser2 object's GoSearch function. +// webBrowser2->lpVtbl->GoSearch(webBrowser2); +// break; +// } +// +// case WEBPAGE_REFRESH: +// { +// // Call the IWebBrowser2 object's Refresh function. +// webBrowser2->lpVtbl->Refresh(webBrowser2); +// break; +// } +// +// case WEBPAGE_STOP: +// { +// // Call the IWebBrowser2 object's Stop function. +// webBrowser2->lpVtbl->Stop(webBrowser2); +// break; +// } +// } +// +// // Release the IWebBrowser2 object. +// webBrowser2->lpVtbl->Release(webBrowser2); +// } +//} +// +// +// +// +// +///******************************* 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... +// * +// *

This is a picture.

+// * +// * hwnd = Handle to the window hosting the browser object. +// * string = Pointer to nul-terminated string containing the HTML BODY. +// * (NOTE: No 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)) +// { +// // 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); +//} +// +// +// +// +// +// +///******************************* DisplayHTMLPage() **************************** +// * Displays a URL, or HTML file on disk. +// * +// * hwnd = Handle to the window hosting the browser object. +// * webPageName = Pointer to nul-terminated name of the URL/file. +// * +// * 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 DisplayHTMLPage(HWND hwnd, LPTSTR webPageName) +//{ +// IWebBrowser2 *webBrowser2; +// VARIANT myURL; +// 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. +// +// // Our URL (ie, web address, such as "http://www.microsoft.com" or an HTM filename on disk +// // such as "c:\myfile.htm") must be passed to the IWebBrowser2's Navigate2() function as a BSTR. +// // A BSTR is like a pascal version of a double-byte character string. In other words, the +// // first unsigned short is a count of how many characters are in the string, and then this +// // is followed by those characters, each expressed as an unsigned short (rather than a +// // char). The string is not nul-terminated. The OS function SysAllocString can allocate and +// // copy a UNICODE C string to a BSTR. Of course, we'll need to free that BSTR after we're done +// // with it. If we're not using UNICODE, we first have to convert to a UNICODE string. +// // +// // What's more, our BSTR needs to be stuffed into a VARIENT struct, and that VARIENT struct is +// // then passed to Navigate2(). Why? The VARIENT struct makes it possible to define generic +// // 'datatypes' that can be used with all languages. Not all languages support things like +// // nul-terminated C strings. So, by using a VARIENT, whose first field tells what sort of +// // data (ie, string, float, etc) is in the VARIENT, COM interfaces can be used by just about +// // any language. +// VariantInit(&myURL); +// myURL.vt = VT_BSTR; +// +//#ifndef UNICODE +// { +// wchar_t *buffer; +// DWORD size; +// +// size = MultiByteToWideChar(CP_ACP, 0, webPageName, -1, 0, 0); +// if (!(buffer = (wchar_t *)GlobalAlloc(GMEM_FIXED, sizeof(wchar_t) * size))) goto badalloc; +// MultiByteToWideChar(CP_ACP, 0, webPageName, -1, buffer, size); +// myURL.bstrVal = SysAllocString(buffer); +// GlobalFree(buffer); +// } +//#else +// myURL.bstrVal = SysAllocString(webPageName); +//#endif +// if (!myURL.bstrVal) +// { +//badalloc: webBrowser2->lpVtbl->Release(webBrowser2); +// return(-6); +// } +// +// // Call the Navigate2() function to actually display the page. +// webBrowser2->lpVtbl->Navigate2(webBrowser2, &myURL, 0, 0, 0, 0); +// +// // Free any resources (including the BSTR we allocated above). +// VariantClear(&myURL); +// +// // 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); +// +// // Success +// return(0); +// } +// +// return(-5); +//} +// +// +// +// +// +///******************************* 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) +//{ +// HRESULT hr; +// 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; +// hr = +// CoGetClassObject( +// &CLSID_WebBrowser, +// CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, NULL, &IID_IClassFactory, (void **)&pClassFactory) && pClassFactory; +// +// if (!hr||!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); +// +// // 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 WebBrowser_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); +// +// // Another window created with an embedded browser object +// +// // Success +// return(0); +// } +// +// case WM_DESTROY: +// { +// // Detach the browser object from this window, and free resources. +// UnEmbedBrowserObject(hwnd); +// return(TRUE); +// } +// +// +// } +// +// return(DefWindowProc(hwnd, uMsg, wParam, lParam)); +//} +// +//static const char* WEBBROWSER_CLASSNAME = "WEBBROWSER"; +//static HINSTANCE gs_hInstance = NULL; +//static HWND gs_hWndWebBrowser = NULL; +//static HWND gs_hWndParent = NULL; +// +// +//int WebBrowser_Show(HWND hParent, const char* addr, const RECT* rc) +//{ +// if (gs_hWndWebBrowser) +// return 0; +// +// gs_hWndParent = hParent; +// gs_hWndWebBrowser = CreateWindowEx(0, WEBBROWSER_CLASSNAME, "web browser", WS_CHILD|WS_VISIBLE, +// rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, +// hParent, NULL, gs_hInstance, 0); +// +// if (!gs_hWndWebBrowser) +// return 0; +// +// DisplayHTMLPage(gs_hWndWebBrowser, (LPTSTR)addr); +// +// ShowWindow(gs_hWndWebBrowser, SW_SHOW); +// UpdateWindow(gs_hWndWebBrowser); +// +// SetFocus(gs_hWndWebBrowser); +// return 1; +//} +// +//void WebBrowser_Move(const RECT* rc) +//{ +// MoveWindow(gs_hWndWebBrowser, rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, 1 ); +//} +// +//void WebBrowser_Hide() +//{ +// if (!gs_hWndWebBrowser) +// return; +// +// ShowWindow(gs_hWndWebBrowser, SW_HIDE); +// +// if (IsWindow(gs_hWndWebBrowser)) +// DestroyWindow(gs_hWndWebBrowser); +// gs_hWndWebBrowser = NULL; +// +// SetFocus(gs_hWndParent); +//} +// +//int WebBrowser_IsVisible() +//{ +// return (gs_hWndWebBrowser != NULL); +//} +// +//void WebBrowser_Destroy() +//{ +// WebBrowser_Hide(); +//} +// +//int WebBrowser_Startup(HINSTANCE hInstance) +//{ +// if (OleInitialize(NULL) != S_OK) +// { +// return 0; +// } +// +// { +// WNDCLASSEX wc; +// ZeroMemory(&wc, sizeof(WNDCLASSEX)); +// wc.cbSize = sizeof(WNDCLASSEX); +// wc.hInstance = hInstance; +// wc.lpfnWndProc = WebBrowser_WindowProc; +// wc.lpszClassName = WEBBROWSER_CLASSNAME; +// RegisterClassEx(&wc); +// } +// gs_hInstance = hInstance; +// return 1; +//} +// +//void WebBrowser_Cleanup() +//{ +// if (gs_hInstance) +// UnregisterClass(WEBBROWSER_CLASSNAME, gs_hInstance); +// +// OleUninitialize(); +//} diff --git a/src/CWebBrowser/CWebBrowser.h b/src/CWebBrowser/CWebBrowser.h index de3ea91..3f4ae77 100644 --- a/src/CWebBrowser/CWebBrowser.h +++ b/src/CWebBrowser/CWebBrowser.h @@ -6,14 +6,13 @@ extern "C" { -int WebBrowser_Startup(HINSTANCE hInstance); -void WebBrowser_Cleanup(); -void WebBrowser_Destroy(); -int WebBrowser_Show(HWND parent, const char* addr, const RECT* rcWebBrowser); -void WebBrowser_Hide(); -void WebBrowser_Move(const RECT* rcWebBrowser); - -int WebBrowser_IsVisible(); -const RECT& WebBrowser_GetRect(); + inline int WebBrowser_Startup(HINSTANCE hInstance) { return 0; } + inline void WebBrowser_Cleanup() {} + inline void WebBrowser_Destroy() {} + inline int WebBrowser_Show(HWND parent, const char* addr, const RECT* rcWebBrowser) { return 0; } + inline void WebBrowser_Hide() {} + inline void WebBrowser_Move(const RECT* rcWebBrowser) {} + inline int WebBrowser_IsVisible() { return 0; } + inline const RECT& WebBrowser_GetRect() { static RECT dummy; return dummy; } } \ No newline at end of file diff --git a/src/EterLib/JpegFile.cpp b/src/EterLib/JpegFile.cpp index ec696a9..27fb762 100644 --- a/src/EterLib/JpegFile.cpp +++ b/src/EterLib/JpegFile.cpp @@ -1,312 +1,312 @@ #include "StdAfx.h" #include "JpegFile.h" -#include -#include -#include -#include -#include -#define OUTBUFFER_SIZE 0x8000 -static FILE*fi; -static JOCTET * buffer; -static unsigned char*dest; -static int len; -static int destlen; -static unsigned char*data_d; -static int pos; -static int size_d; -static void file_init_destination(j_compress_ptr cinfo) -{ - struct jpeg_destination_mgr*dmgr = - (struct jpeg_destination_mgr*)(cinfo->dest); - buffer = (JOCTET*)malloc(OUTBUFFER_SIZE); - if(!buffer) { - perror("malloc"); - printf("Out of memory!\n"); - exit(1); - } - dmgr->next_output_byte = buffer; - dmgr->free_in_buffer = OUTBUFFER_SIZE; -} -static unsigned char file_empty_output_buffer(j_compress_ptr cinfo) -{ - struct jpeg_destination_mgr*dmgr = - (struct jpeg_destination_mgr*)(cinfo->dest); - if(fi) - fwrite(buffer, OUTBUFFER_SIZE, 1, fi); - dmgr->next_output_byte = buffer; - dmgr->free_in_buffer = OUTBUFFER_SIZE; - return 1; -} -static void file_term_destination(j_compress_ptr cinfo) -{ struct jpeg_destination_mgr*dmgr = - (struct jpeg_destination_mgr*)(cinfo->dest); - if(fi) - fwrite(buffer, OUTBUFFER_SIZE-dmgr->free_in_buffer, 1, fi); - free(buffer); - buffer = 0; - dmgr->free_in_buffer = 0; -} -static void mem_init_destination(j_compress_ptr cinfo) -{ - struct jpeg_destination_mgr*dmgr = - (struct jpeg_destination_mgr*)(cinfo->dest); - dmgr->next_output_byte = dest; - dmgr->free_in_buffer = destlen; -} -static unsigned char mem_empty_output_buffer(j_compress_ptr cinfo) -{ - printf("jpeg mem overflow!\n"); - exit(1); -} -static void mem_term_destination(j_compress_ptr cinfo) -{ - struct jpeg_destination_mgr*dmgr = - (struct jpeg_destination_mgr*)(cinfo->dest); - len = destlen - dmgr->free_in_buffer; - dmgr->free_in_buffer = 0; -} -int jpeg_save(unsigned char*data_d, int width, int height, int quality, const char*filename) -{ - struct jpeg_destination_mgr mgr; - struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; - int t; - if(filename) { - fi = fopen(filename, "wb"); - if(fi == NULL) - return 0; - } else - fi = NULL; - memset(&cinfo, 0, sizeof(cinfo)); - memset(&jerr, 0, sizeof(jerr)); - memset(&mgr, 0, sizeof(mgr)); - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_compress(&cinfo); - mgr.init_destination = file_init_destination; - mgr.empty_output_buffer = file_empty_output_buffer; - mgr.term_destination = file_term_destination; - cinfo.dest = &mgr; - // init compression - cinfo.image_width = width; - cinfo.image_height = height; - cinfo.input_components = 3; - cinfo.in_color_space = JCS_RGB; - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo,quality,TRUE); - //jpeg_write_tables(&cinfo); - //jpeg_suppress_tables(&cinfo, TRUE); - jpeg_start_compress(&cinfo, FALSE); - for(t=0;tsrc; - mgr->next_input_byte = data_d; - mgr->bytes_in_buffer = size_d; - //printf("init %d\n", size - mgr->bytes_in_buffer); -} -unsigned char mem_fill_input_buffer (j_decompress_ptr cinfo) -{ - struct jpeg_source_mgr* mgr = cinfo->src; - printf("fill %d\n", size_d - mgr->bytes_in_buffer); - return 0; -} -void mem_skip_input_data (j_decompress_ptr cinfo, long num_bytes) -{ - struct jpeg_source_mgr* mgr = cinfo->src; - printf("skip %d +%d\n", size_d - mgr->bytes_in_buffer, num_bytes); - if(num_bytes<=0) - return; - mgr->next_input_byte += num_bytes; - mgr->bytes_in_buffer -= num_bytes; -} -unsigned char mem_resync_to_restart (j_decompress_ptr cinfo, int desired) -{ - struct jpeg_source_mgr* mgr = cinfo->src; - printf("resync %d\n", size_d - mgr->bytes_in_buffer); - mgr->next_input_byte = data_d; - mgr->bytes_in_buffer = size_d; - return 1; -} -void mem_term_source (j_decompress_ptr cinfo) -{ - struct jpeg_source_mgr* mgr = cinfo->src; - //printf("term %d\n", size - mgr->bytes_in_buffer); -} -int jpeg_load_from_mem(unsigned char*_data, int _size, unsigned char*dest, int width, int height) -{ - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - struct jpeg_source_mgr mgr; - int y; - //int x; - data_d = _data; - size_d = _size; - jpeg_create_decompress(&cinfo); - mgr.next_input_byte = data_d; - mgr.bytes_in_buffer = size_d; - mgr.init_source =mem_init_source ; - mgr.fill_input_buffer =mem_fill_input_buffer ; - mgr.skip_input_data =mem_skip_input_data ; - mgr.resync_to_restart =mem_resync_to_restart ; - mgr.term_source =mem_term_source ; - cinfo.err = jpeg_std_error(&jerr); - cinfo.src = &mgr; - jpeg_read_header(&cinfo, TRUE); - jpeg_start_decompress(&cinfo); - for(y=0;y= 0; x--) { - line[x].a = 255; - line[x].r = js[x*3+0]; - line[x].g = js[x*3+1]; - line[x].b = js[x*3+2]; - } - } else if (cinfo.out_color_space == JCS_YCCK) { - fprintf(stderr, "Error: Can't convert YCCK to RGB.\n"); - return 0; - } else if (cinfo.out_color_space == JCS_YCbCr) { - for (x = 0; x < width; x++) { - int y = js[x * 3 + 0]; - int u = js[x * 3 + 1]; - int v = js[x * 3 + 1]; - line[x].a = 255; - line[x].r = y + ((360 * (v - 128)) >> 8); - line[x].g = y - ((88 * (u - 128) + 183 * (v - 128)) >> 8); - line[x].b = y + ((455 * (u - 128)) >> 8); - } - } else if (cinfo.out_color_space == JCS_CMYK) { - for (x = 0; x < width; x++) { - int white = 255 - js[x * 4 + 3]; - line[x].a = 255; - line[x].r = white - ((js[x * 4] * white) >> 8); - line[x].g = white - ((js[x * 4 + 1] * white) >> 8); - line[x].b = white - ((js[x * 4 + 2] * white) >> 8); - } - } - } - free(scanline); - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - fclose(fi); - return 1; -} \ No newline at end of file +//#include +//#include +//#include +////#include +////#include +//#define OUTBUFFER_SIZE 0x8000 +//static FILE*fi; +//static JOCTET * buffer; +//static unsigned char*dest; +//static int len; +//static int destlen; +//static unsigned char*data_d; +//static int pos; +//static int size_d; +//static void file_init_destination(j_compress_ptr cinfo) +//{ +// struct jpeg_destination_mgr*dmgr = +// (struct jpeg_destination_mgr*)(cinfo->dest); +// buffer = (JOCTET*)malloc(OUTBUFFER_SIZE); +// if(!buffer) { +// perror("malloc"); +// printf("Out of memory!\n"); +// exit(1); +// } +// dmgr->next_output_byte = buffer; +// dmgr->free_in_buffer = OUTBUFFER_SIZE; +//} +//static unsigned char file_empty_output_buffer(j_compress_ptr cinfo) +//{ +// struct jpeg_destination_mgr*dmgr = +// (struct jpeg_destination_mgr*)(cinfo->dest); +// if(fi) +// fwrite(buffer, OUTBUFFER_SIZE, 1, fi); +// dmgr->next_output_byte = buffer; +// dmgr->free_in_buffer = OUTBUFFER_SIZE; +// return 1; +//} +//static void file_term_destination(j_compress_ptr cinfo) +//{ struct jpeg_destination_mgr*dmgr = +// (struct jpeg_destination_mgr*)(cinfo->dest); +// if(fi) +// fwrite(buffer, OUTBUFFER_SIZE-dmgr->free_in_buffer, 1, fi); +// free(buffer); +// buffer = 0; +// dmgr->free_in_buffer = 0; +//} +//static void mem_init_destination(j_compress_ptr cinfo) +//{ +// struct jpeg_destination_mgr*dmgr = +// (struct jpeg_destination_mgr*)(cinfo->dest); +// dmgr->next_output_byte = dest; +// dmgr->free_in_buffer = destlen; +//} +//static unsigned char mem_empty_output_buffer(j_compress_ptr cinfo) +//{ +// printf("jpeg mem overflow!\n"); +// exit(1); +//} +//static void mem_term_destination(j_compress_ptr cinfo) +//{ +// struct jpeg_destination_mgr*dmgr = +// (struct jpeg_destination_mgr*)(cinfo->dest); +// len = destlen - dmgr->free_in_buffer; +// dmgr->free_in_buffer = 0; +//} +//int jpeg_save(unsigned char*data_d, int width, int height, int quality, const char*filename) +//{ +// struct jpeg_destination_mgr mgr; +// struct jpeg_compress_struct cinfo; +// struct jpeg_error_mgr jerr; +// int t; +// if(filename) { +// fi = fopen(filename, "wb"); +// if(fi == NULL) +// return 0; +// } else +// fi = NULL; +// memset(&cinfo, 0, sizeof(cinfo)); +// memset(&jerr, 0, sizeof(jerr)); +// memset(&mgr, 0, sizeof(mgr)); +// cinfo.err = jpeg_std_error(&jerr); +// jpeg_create_compress(&cinfo); +// mgr.init_destination = file_init_destination; +// mgr.empty_output_buffer = file_empty_output_buffer; +// mgr.term_destination = file_term_destination; +// cinfo.dest = &mgr; +// // init compression +// cinfo.image_width = width; +// cinfo.image_height = height; +// cinfo.input_components = 3; +// cinfo.in_color_space = JCS_RGB; +// jpeg_set_defaults(&cinfo); +// jpeg_set_quality(&cinfo,quality,TRUE); +// //jpeg_write_tables(&cinfo); +// //jpeg_suppress_tables(&cinfo, TRUE); +// jpeg_start_compress(&cinfo, FALSE); +// for(t=0;tsrc; +// mgr->next_input_byte = data_d; +// mgr->bytes_in_buffer = size_d; +// //printf("init %d\n", size - mgr->bytes_in_buffer); +//} +//unsigned char mem_fill_input_buffer (j_decompress_ptr cinfo) +//{ +// struct jpeg_source_mgr* mgr = cinfo->src; +// printf("fill %d\n", size_d - mgr->bytes_in_buffer); +// return 0; +//} +//void mem_skip_input_data (j_decompress_ptr cinfo, long num_bytes) +//{ +// struct jpeg_source_mgr* mgr = cinfo->src; +// printf("skip %d +%d\n", size_d - mgr->bytes_in_buffer, num_bytes); +// if(num_bytes<=0) +// return; +// mgr->next_input_byte += num_bytes; +// mgr->bytes_in_buffer -= num_bytes; +//} +//unsigned char mem_resync_to_restart (j_decompress_ptr cinfo, int desired) +//{ +// struct jpeg_source_mgr* mgr = cinfo->src; +// printf("resync %d\n", size_d - mgr->bytes_in_buffer); +// mgr->next_input_byte = data_d; +// mgr->bytes_in_buffer = size_d; +// return 1; +//} +//void mem_term_source (j_decompress_ptr cinfo) +//{ +// struct jpeg_source_mgr* mgr = cinfo->src; +// //printf("term %d\n", size - mgr->bytes_in_buffer); +//} +//int jpeg_load_from_mem(unsigned char*_data, int _size, unsigned char*dest, int width, int height) +//{ +// struct jpeg_decompress_struct cinfo; +// struct jpeg_error_mgr jerr; +// struct jpeg_source_mgr mgr; +// int y; +// //int x; +// data_d = _data; +// size_d = _size; +// jpeg_create_decompress(&cinfo); +// mgr.next_input_byte = data_d; +// mgr.bytes_in_buffer = size_d; +// mgr.init_source =mem_init_source ; +// mgr.fill_input_buffer =mem_fill_input_buffer ; +// mgr.skip_input_data =mem_skip_input_data ; +// mgr.resync_to_restart =mem_resync_to_restart ; +// mgr.term_source =mem_term_source ; +// cinfo.err = jpeg_std_error(&jerr); +// cinfo.src = &mgr; +// jpeg_read_header(&cinfo, TRUE); +// jpeg_start_decompress(&cinfo); +// for(y=0;y= 0; x--) { +// line[x].a = 255; +// line[x].r = js[x*3+0]; +// line[x].g = js[x*3+1]; +// line[x].b = js[x*3+2]; +// } +// } else if (cinfo.out_color_space == JCS_YCCK) { +// fprintf(stderr, "Error: Can't convert YCCK to RGB.\n"); +// return 0; +// } else if (cinfo.out_color_space == JCS_YCbCr) { +// for (x = 0; x < width; x++) { +// int y = js[x * 3 + 0]; +// int u = js[x * 3 + 1]; +// int v = js[x * 3 + 1]; +// line[x].a = 255; +// line[x].r = y + ((360 * (v - 128)) >> 8); +// line[x].g = y - ((88 * (u - 128) + 183 * (v - 128)) >> 8); +// line[x].b = y + ((455 * (u - 128)) >> 8); +// } +// } else if (cinfo.out_color_space == JCS_CMYK) { +// for (x = 0; x < width; x++) { +// int white = 255 - js[x * 4 + 3]; +// line[x].a = 255; +// line[x].r = white - ((js[x * 4] * white) >> 8); +// line[x].g = white - ((js[x * 4 + 1] * white) >> 8); +// line[x].b = white - ((js[x * 4 + 2] * white) >> 8); +// } +// } +// } +// free(scanline); +// jpeg_finish_decompress(&cinfo); +// jpeg_destroy_decompress(&cinfo); +// fclose(fi); +// return 1; +//} \ No newline at end of file diff --git a/src/EterLib/JpegFile.h b/src/EterLib/JpegFile.h index fd1176a..f929c78 100644 --- a/src/EterLib/JpegFile.h +++ b/src/EterLib/JpegFile.h @@ -2,8 +2,8 @@ #include -int jpeg_save(unsigned char*data_d, int width, int height, int quality, const char*filename); -int jpeg_save_to_file(unsigned char*data_d, int width, int height, int quality, FILE*fi); -int jpeg_save_to_mem(unsigned char*data_d, int width, int height, int quality, unsigned char*dest, int destsize); -int jpeg_load(const char*filename, unsigned char**dest, int*width, int*height); -int jpeg_load_from_mem(unsigned char*_data, int size_d, unsigned char*dest, int width, int height); \ No newline at end of file +inline int jpeg_save(unsigned char* data_d, int width, int height, int quality, const char* filename) { return 0; } +inline int jpeg_save_to_file(unsigned char* data_d, int width, int height, int quality, FILE* fi) { return 0; } +inline int jpeg_save_to_mem(unsigned char* data_d, int width, int height, int quality, unsigned char* dest, int destsize) { return 0; } +inline int jpeg_load(const char* filename, unsigned char** dest, int* width, int* height) { return 0; } +inline int jpeg_load_from_mem(unsigned char* _data, int size_d, unsigned char* dest, int width, int height) { return 0; } \ No newline at end of file diff --git a/src/EterLib/MSWindow.cpp b/src/EterLib/MSWindow.cpp index c93e202..57e3adb 100644 --- a/src/EterLib/MSWindow.cpp +++ b/src/EterLib/MSWindow.cpp @@ -8,7 +8,7 @@ HINSTANCE CMSWindow::ms_hInstance = NULL; LRESULT CALLBACK MSWindowProcedure(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) { - CMSWindow * pWnd = (CMSWindow *) GetWindowLong(hWnd, GWL_USERDATA); + CMSWindow * pWnd = (CMSWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (pWnd) return pWnd->WindowProcedure(hWnd, uiMsg, wParam, lParam); @@ -79,7 +79,7 @@ bool CMSWindow::Create(const char* c_szName, int brush, DWORD cs, DWORD ws, HICO if (!m_hWnd) return false; - SetWindowLong(m_hWnd, GWL_USERDATA, (DWORD) this); + SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (DWORD) this); //DestroyWindow(ImmGetDefaultIMEWnd(m_hWnd)); return true; diff --git a/src/GameLib/FlyingInstance.cpp b/src/GameLib/FlyingInstance.cpp index 16d213d..c782d52 100644 --- a/src/GameLib/FlyingInstance.cpp +++ b/src/GameLib/FlyingInstance.cpp @@ -362,7 +362,7 @@ bool CFlyingInstance::Update() m_v3Velocity.z+=m_pData->m_fGravity * CTimer::Instance().GetElapsedSecond(); D3DXVECTOR3 v3Movement = m_v3Velocity * CTimer::Instance().GetElapsedSecond(); float _fMoveDistance = D3DXVec3Length(&v3Movement); - float fCollisionSphereRadius = max(_fMoveDistance*2, m_pData->m_fCollisionSphereRadius); + float fCollisionSphereRadius = std::max(_fMoveDistance*2, m_pData->m_fCollisionSphereRadius); m_fRemainRange -= _fMoveDistance; m_v3Position += v3Movement; diff --git a/src/ScriptLib/PythonLauncher.cpp b/src/ScriptLib/PythonLauncher.cpp index 0ba4b68..e316cb9 100644 --- a/src/ScriptLib/PythonLauncher.cpp +++ b/src/ScriptLib/PythonLauncher.cpp @@ -1,5 +1,9 @@ #include "StdAfx.h" #include +#ifdef BYTE +#undef BYTE +#endif + #include "eterPack/EterPackManager.h" #include "PythonLauncher.h" diff --git a/src/ScriptLib/PythonLauncher.h b/src/ScriptLib/PythonLauncher.h index aef2b74..c499709 100644 --- a/src/ScriptLib/PythonLauncher.h +++ b/src/ScriptLib/PythonLauncher.h @@ -1,5 +1,8 @@ #pragma once #include +#ifdef BYTE +#undef BYTE +#endif #include "eterBase/Singleton.h" diff --git a/src/ScriptLib/PythonMarshal.cpp b/src/ScriptLib/PythonMarshal.cpp index 510ff5a..61e4693 100644 --- a/src/ScriptLib/PythonMarshal.cpp +++ b/src/ScriptLib/PythonMarshal.cpp @@ -5,6 +5,9 @@ #include "Stdafx.h" #include +#ifdef BYTE +#undef BYTE +#endif /* High water mark to determine when the marshalled object is dangerously deep * and risks coring the interpreter. When the object stack gets this deep, diff --git a/src/ScriptLib/StdAfx.h b/src/ScriptLib/StdAfx.h index 5eff961..363af88 100644 --- a/src/ScriptLib/StdAfx.h +++ b/src/ScriptLib/StdAfx.h @@ -20,6 +20,10 @@ #include #include +#ifdef BYTE +#undef BYTE +#endif + #include "PythonUtils.h" #include "PythonLauncher.h" #include "PythonMarshal.h" diff --git a/src/UserInterface/PythonPlayerModule.cpp b/src/UserInterface/PythonPlayerModule.cpp index 1ee0511..c659bdd 100644 --- a/src/UserInterface/PythonPlayerModule.cpp +++ b/src/UserInterface/PythonPlayerModule.cpp @@ -896,7 +896,7 @@ PyObject * playerSetItemCount(PyObject* poSelf, PyObject* poArgs) if (!PyTuple_GetInteger(poArgs, 0, &iSlotIndex)) return Py_BuildException(); - BYTE bCount; + uint8_t bCount; if (!PyTuple_GetInteger(poArgs, 1, &bCount)) return Py_BuildException(); @@ -915,7 +915,7 @@ PyObject * playerSetItemCount(PyObject* poSelf, PyObject* poArgs) if (!PyTuple_GetInteger(poArgs, 1, &Cell.cell)) return Py_BuildException(); - BYTE bCount; + uint8_t bCount; if (!PyTuple_GetInteger(poArgs, 2, &bCount)) return Py_BuildException(); @@ -1290,7 +1290,7 @@ PyObject * playerIsEquipmentSlot(PyObject* poSelf, PyObject* poArgs) PyObject * playerIsDSEquipmentSlot(PyObject* poSelf, PyObject* poArgs) { - BYTE bWindowType; + uint8_t bWindowType; if (!PyTuple_GetInteger(poArgs, 0, &bWindowType)) return Py_BuildException(); int iSlotIndex; @@ -2124,7 +2124,7 @@ PyObject * playerIsAvailableBeltInventoryCell(PyObject* poSelf, PyObject* poArgs // 용혼석 강화 PyObject* playerSendDragonSoulRefine(PyObject* poSelf, PyObject* poArgs) { - BYTE bSubHeader; + uint8_t bSubHeader; PyObject* pDic; TItemPos RefineItemPoses[DS_REFINE_WINDOW_MAX_NUM]; if (!PyTuple_GetByte(poArgs, 0, &bSubHeader)) @@ -2139,7 +2139,7 @@ PyObject* playerSendDragonSoulRefine(PyObject* poSelf, PyObject* poArgs) { if (!PyTuple_GetObject(poArgs, 1, &pDic)) return Py_BuildException(); - int pos = 0; + Py_ssize_t pos = 0; PyObject* key, *value; int size = PyDict_Size(pDic); diff --git a/src/UserInterface/PythonSoundManagerModule.cpp b/src/UserInterface/PythonSoundManagerModule.cpp index 1547d29..8112b41 100644 --- a/src/UserInterface/PythonSoundManagerModule.cpp +++ b/src/UserInterface/PythonSoundManagerModule.cpp @@ -39,7 +39,7 @@ PyObject * sndPlayMusic(PyObject * poSelf, PyObject * poArgs) return Py_BuildException(); CSoundManager& rkSndMgr=CSoundManager::Instance(); - rkSndMgr.PlayMusic(szFileName); + rkSndMgr.PlaySound2D(szFileName); return Py_BuildNone(); } @@ -112,7 +112,7 @@ PyObject * sndSetSoundVolumef(PyObject * poSelf, PyObject * poArgs) return Py_BuildException(); CSoundManager& rkSndMgr=CSoundManager::Instance(); - rkSndMgr.SetSoundVolumeRatio(fVolume); + rkSndMgr.SetSoundVolume(fVolume); return Py_BuildNone(); } @@ -124,7 +124,7 @@ PyObject * sndSetSoundVolume(PyObject * poSelf, PyObject * poArgs) return Py_BuildException(); CSoundManager& rkSndMgr=CSoundManager::Instance(); - rkSndMgr.SetSoundVolumeGrade(iVolume); + rkSndMgr.SetSoundVolume(iVolume); return Py_BuildNone(); } diff --git a/src/UserInterface/PythonSystem.cpp b/src/UserInterface/PythonSystem.cpp index 13415cd..2474b5d 100644 --- a/src/UserInterface/PythonSystem.cpp +++ b/src/UserInterface/PythonSystem.cpp @@ -649,7 +649,7 @@ void CPythonSystem::ChangeSystem() else fVoiceVolume = (float)pow(10.0f, (-1.0f + (float)m_Config.voice_volume / 5.0f)); */ - rkSndMgr.SetSoundVolumeGrade(m_Config.voice_volume); + rkSndMgr.SetSoundVolume(m_Config.voice_volume); } void CPythonSystem::Clear() diff --git a/src/UserInterface/UserInterface.cpp b/src/UserInterface/UserInterface.cpp index 78d8295..0a339e1 100644 --- a/src/UserInterface/UserInterface.cpp +++ b/src/UserInterface/UserInterface.cpp @@ -45,7 +45,6 @@ extern "C" { FILE __iob_func[3] = { *stdin,*stdout,*stderr }; } #pragma comment( lib, "dmoguids.lib" ) //#pragma comment( lib, "wsock32.lib" ) #include -#include bool __IS_TEST_SERVER_MODE__=false; extern bool SetDefaultCodePage(DWORD codePage); @@ -218,8 +217,6 @@ bool PackInitialize(const char * c_pszFolder) CEterPackManager::Instance().SetCacheMode(); CEterPackManager::Instance().SetSearchMode(bPackFirst); - CSoundData::SetPackMode(); // Miles 파일 콜백을 셋팅 - std::string strPackName, strTexCachePackName; for (DWORD i = 1; i < TextLoader.GetLineCount() - 1; i += 2) { @@ -385,9 +382,7 @@ bool Main(HINSTANCE hInstance, LPSTR lpCmdLine) system("patchupdater.exe"); return false; } -#ifndef __VTUNE__ - ilInit(); -#endif + if (!Setup(lpCmdLine)) return false; diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index 0d79cda..96323f6 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -1,6 +1,4 @@ add_subdirectory(cryptopp) - - add_subdirectory(lzo-2.10) if (WIN32)