/*
* Dll.c -- A dynamic link library to display a web page in your own 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.
*
* The functions in this DLL callable by a program:
*
* EmbedBrowserObject() -- Embeds a browser object in your own window.
* UnEmbedBrowserObject() -- Detaches the browser object from your window.
* DisplayHTMLPage() -- Displays a URL or HTML file on disk.
* DisplayHTMLStr() -- Displays a (in memory) string of HTML code.
* DoPageAction() -- Moves forward/backward a page, brings up Home or Search page, etc.
* WaitOnReadyState() -- Waits for a page to be in a certain state.
* GetWebPtrs() -- Obtains a IWebBrowser2 and/or IHTMLDocument2 pointer.
* GetWebElement() -- Gets the IHTMLElement object of some element on a web page.
* ResizeBrowser() -- Resizes the IE window to be the same width/height as the app's container window.
*
* For the release (ie, not debug) version, then you should set your linker to
* ignore the default libraries. This will reduce code size.
*/
#include <windows.h>
#include <tchar.h>
#ifndef NDEBUG
#include <assert.h>
#endif
#include "cwebpage.h"
/*
#define DOCHOSTUIFLAG_DIALOG 0x00000001,
#define DOCHOSTUIFLAG_DISABLE_HELP_MENU 0x00000002,
#define DOCHOSTUIFLAG_NO3DBORDER 0x00000004,
#define DOCHOSTUIFLAG_SCROLL_NO 0x00000008,
#define DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE 0x00000010,
#define DOCHOSTUIFLAG_OPENNEWWIN 0x00000020,
#define DOCHOSTUIFLAG_DISABLE_OFFSCREEN 0x00000040,
#define DOCHOSTUIFLAG_FLAT_SCROLLBAR 0x00000080,
#define DOCHOSTUIFLAG_DIV_BLOCKDEFAULT 0x00000100,
#define DOCHOSTUIFLAG_ACTIVATE_CLIENTHIT_ONLY 0x00000200,
#define DOCHOSTUIFLAG_OVERRIDEBEHAVIORFACTORY 0x00000400,
#define DOCHOSTUIFLAG_CODEPAGELINKEDFONTS 0x00000800,
#define DOCHOSTUIFLAG_URL_ENCODING_DISABLE_UTF8 x00001000,
#define DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8 0x00002000,
#define DOCHOSTUIFLAG_ENABLE_FORMS_AUTOCOMPLETE 0x00004000,
#define DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION 0x00010000,
#define DOCHOSTUIFLAG_IME_ENABLE_RECONVERSION 0x00020000,
#define DOCHOSTUIFLAG_THEME 0x00040000,
#define DOCHOSTUIFLAG_NOTHEME 0x00080000,
#define DOCHOSTUIFLAG_NOPICS 0x00100000,
#define DOCHOSTUIFLAG_NO3DOUTERBORDER 0x00200000,
#define DOCHOSTUIFLAG_DELEGATESIDOFDISPATCH 0x00400000
*/
#if defined(VISUAL_C)
#pragma data_seg("Shared")
#endif
/* ============================== SHARED DATA ==============================
* NOTE: I specify this data section to be Shared (ie, each program that uses
* this shares these variables, rather than getting its own copies of these
* variables). This is because, since I have only globals that are read-only
* or whose value is the same for all processes, I don't need a separate copy
* of these for each process that uses this DLL. In Visual C++'s Linker
* settings, I add "/section:Shared,rws"
*/
// Used by UI_TranslateUrl(). These can be global because we never change them.
static const wchar_t AppUrl[] = {L"app:"};
static const wchar_t Blank[] = {L"about:blank"};
// This is used by displayHTMLStr(). It can be global because we never change it.
static const SAFEARRAYBOUND ArrayBound = {1, 0};
static unsigned char _IID_IHTMLWindow3[] = {0xae, 0xf4, 0x50, 0x30, 0xb5, 0x98, 0xcf, 0x11, 0xbb, 0x82, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x0b};
#if defined(VISUAL_C)
#pragma data_seg()
#endif
// Our IOleInPlaceFrame functions that the browser may call
HRESULT STDMETHODCALLTYPE Frame_QueryInterface(IOleInPlaceFrame *, REFIID, LPVOID *);
HRESULT STDMETHODCALLTYPE Frame_AddRef(IOleInPlaceFrame *);
HRESULT STDMETHODCALLTYPE Frame_Release(IOleInPlaceFrame *);
HRESULT STDMETHODCALLTYPE Frame_GetWindow(IOleInPlaceFrame *, HWND *);
HRESULT STDMETHODCALLTYPE Frame_ContextSensitiveHelp(IOleInPlaceFrame *, BOOL);
HRESULT STDMETHODCALLTYPE Frame_GetBorder(IOleInPlaceFrame *, LPRECT);
HRESULT STDMETHODCALLTYPE Frame_RequestBorderSpace(IOleInPlaceFrame *, LPCBORDERWIDTHS);
HRESULT STDMETHODCALLTYPE Frame_SetBorderSpace(IOleInPlaceFrame *, LPCBORDERWIDTHS);
HRESULT STDMETHODCALLTYPE Frame_SetActiveObject(IOleInPlaceFrame *, IOleInPlaceActiveObject *, LPCOLESTR);
HRESULT STDMETHODCALLTYPE Frame_InsertMenus(IOleInPlaceFrame *, HMENU, LPOLEMENUGROUPWIDTHS);
HRESULT STDMETHODCALLTYPE Frame_SetMenu(IOleInPlaceFrame *, HMENU, HOLEMENU, HWND);
HRESULT STDMETHODCALLTYPE Frame_RemoveMenus(IOleInPlaceFrame *, HMENU);
HRESULT STDMETHODCALLTYPE Frame_SetStatusText(IOleInPlaceFrame *, LPCOLESTR);
HRESULT STDMETHODCALLTYPE Frame_EnableModeless(IOleInPlaceFrame *, BOOL);
HRESULT STDMETHODCALLTYPE Frame_TranslateAccelerator(IOleInPlaceFrame *, LPMSG, WORD);
// 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.
static 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 member 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 *, REFIID, void **);
HRESULT STDMETHODCALLTYPE Site_AddRef(IOleClientSite *);
HRESULT STDMETHODCALLTYPE Site_Release(IOleClientSite *);
HRESULT STDMETHODCALLTYPE Site_SaveObject(IOleClientSite *);
HRESULT STDMETHODCALLTYPE Site_GetMoniker(IOleClientSite *, DWORD, DWORD, IMoniker **);
HRESULT STDMETHODCALLTYPE Site_GetContainer(IOleClientSite *, LPOLECONTAINER *);
HRESULT STDMETHODCALLTYPE Site_ShowObject(IOleClientSite *);
HRESULT STDMETHODCALLT