PomeloWu原创©,转载请指明出处
想在自己的窗口中放上一个WebBrowser Contorl,但又不想用MFC;可惜网上除了MFC/ATL以外,使用WebBrowser的资料少得可怜。
在CodeGuru上找到Jeff Glatt 的一篇文章Display a Web Page in a Plain C Win32 Application,写成于2002年,作者的确够厚道,不但给了两份注释完整的代码(一个是exe的源文件,一个是Dll的源文件),还把如何用C一步一步实现虚函数表、接口、继承、多继承清清楚楚剖析了出来,整个一篇绝好的教你凭空(我是想说不依赖于MFC/ATL)把ActiveX控件嵌入自己窗口的指引。
Jeff Glatt的文章端的是精彩至极,但是用Pure C搞COM的确……我反正不是这块料。不过话说回来,有了这篇妙文的指引,做一个C++的包装就只需要医葫芦画瓢啦。下面就是我原样照搬的一个C++的包装类。我是把这个类做成一个Lib文件(Jeff Glatt也就lib文件没做啦),算是个“求同存异”吧。略为有点不一样的是,Jeff Glatt考虑了打开多个窗口的问题,而我的代码,一个类就一个窗体了。
下面是源代码:
类CWebBrowser:
/********************************************************************
@created: 2006/01/16
@version: 0.1
@filename: WebBrowser.h
@file base: WebBrowser
@file ext: h
@author: Pomelo Wu
@purpose: Declaration for class CWebBrowser, a wrapper of
IWebBrowser2.
@remark: To use this class, include 'Exdisp.h' before this file.
Besides, use OleInitialize instead of CoInitialize, and
do not forget OleUninitialize.
@revision history:
-- Date Ver. Modifier Description--
2006/01/16 0.1 Pomelo Create
*********************************************************************/
#ifndef __WEBBROWSER_H__
#define __WEBBROWSER_H__
// This is for a simple C++ wrapper. There are lots more things we can control about the browser object,
// but we don't do it all in this. _Many_ of the functions we provide for the browser to call, will
// never actually be called by the browser in our sample. 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 we try to do more things with the browser object, and it starts
// calling these "dummy functions", we'll know which ones we should add more meaningful code to.
#define NOTIMPLEMENTED _ASSERT(0); return(E_NOTIMPL)
//=============================================================================
/*
@class CWebBrowser
@author Pomelo Wu
@brief A wrapper class of IWebBrowser2 interface.
*/
//=============================================================================
class CWebBrowser
{
public:
// Constructor
CWebBrowser(void);
// Destructor
~CWebBrowser(void);
private:
// Data members
IOleObject *m_pBrowserObj;
public:
// Interfaces
/*************************** 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*/);
/***************************** 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.
*/
long EmbedBrowserObject(HWND hwnd);
/******************************* 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*/, LPCTSTR webPageName);
/******************************* DisplayHTMLStr() ****************************
* Takes a string containing some HTML BODY, and displays it in the specified
* window. For example, perhaps you want to display the HTML text of...
*
* <P>This is a picture.<P><IMG src="mypic.jpg">
*
* hwnd = Handle to the window hosting the browser object.
* string = Pointer to nul-terminated string containing the HTML BODY.
* (NOTE: No <BODY></BODY> tags are required in the string).
*
* RETURNS: 0 if success, or non-zero if an error.
*
* NOTE: EmbedBrowserObject() must have been successfully called once with the
* specified window, prior to calling this function. You need call
* EmbedBrowserObject() once only, and then you can make multiple calls to
* this function to display numerous pages in the specified window.
*/
long DisplayHTMLStr(HWND /*hwnd*/, LPCTSTR string);
private:
// Methods
};
#endif //__WEBBROWSER_H__
/********************************************************************
@created: 2006/01/16
@version: 0.1
@filename: WebBrowser.cpp
@file base: WebBrowser
@file ext: cpp
@author: Pomelo Wu
@purpose: Implementation for class CWebBrowser, a wrapper of
IWebBrowser2.
@remark: NULL
@revision history:
-- Date Ver. Modifier Description--
2006/01/16 0.1 Pomelo Create
*********************************************************************/
#include <Exdisp.h> /* Defines of stuff like IWebBrowser2. This is an include file with Visual C 6 and above */
#include <Mshtml.h> /* Defines of stuff like IHTMLDocument2. This is an include file with Visual C 6 and above */
/* If you gets some error when compling under VS2005, move mshtml.h to top*/
#include <crtdbg.h> /* for _ASSERT() */
#include "WBStorage.h"
#include "WBClientsite.h"
#include "WebBrowser.h"
#include "Global.h"
/* This is used by DisplayHTMLStr(). It can be global because we never change it. */
static const SAFEARRAYBOUND ArrayBound = {1, 0};
CWebBrowser::CWebBrowser(void)
{
m_pBrowserObj = NULL;
}
CWebBrowser::~CWebBrowser(void)
{
}
void CWebBrowser::UnEmbedBrowserObject(HWND /*hwnd*/)
{
//
//
// Not implemented for multiple browsing...
//
//IOleObject **ppBrowserHandle;
//IOleObject *pBrowserObject;
//
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 ((ppBrowserHandle = (IOleObject **)GetWindowLong(hwnd, GWL_USERDATA)))
//{
// // Unembed the browser object, and release its resources.
// pBrowserObject = *ppBrowserHandle;
// pBrowserObject->Close(OLECLOSE_NOSAVE);
// pBrowserObject->Release();
//}
//
if (m_pBrowserObj)
{
// Unembed the browser object, and release its resources.
m_pBrowserObj->Close(OLECLOSE_NOSAVE);
m_pBrowserObj->Release();
return;
}
// You must have called this for a window that wasn't successfully passed to EmbedBrowserObject().
// Bad boy!
_ASSERT(0);
}
long CWebBrowser::DisplayHTMLStr(HWND /*hwnd*/, LPCTSTR string)
{
IWebBrowser2 *pWebBrowser2;
LPDISPATCH lpDispatch;
IHTMLDocument2 *pHtmlDoc2;
SAFEARRAY *psfArray;
VARIANT varMyURL;
VARIANT *pVar;
BSTR bstr;
// Assume an error.
bstr = 0;
//
//
// Not implemented for multiple browsing...
//
//IOleObject **ppBrowserHandle;
//IOleObject *pBrowserObject;
//
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 ((ppBrowserHandle = (IOleObject **)GetWindowLong(hwnd, GWL_USERDATA)))
//{
// // Unembed the browser object, and release its resources.
// pBrowserObject = *ppBrowserHandle;
//}
//
// 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 (!m_pBrowserObj->QueryInterface(IID_IWebBrowser2, (void**)&pWebBrowser2))
{
// 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(&varMyURL);
varMyURL.vt = VT_BSTR;
varMyURL.bstrVal = SysAllocString(L"about:blank");
// Call the Navigate2() function to actually display the page.
pWebBrowser2->Navigate2(&varMyURL, 0, 0, 0, 0);
// Free any resources (including the BSTR).
VariantClear(&varMyURL);
// 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 (!pWebBrowser2->get_Document(&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->QueryInterface(IID_IHTMLDocument2, (void**)&pHtmlDoc2))
{
// Our HTML must be in the form of a BSTR. And it must be passed to write() in an
// array of "VARIENT" structures. So let's create all that.
if ((psfArray = SafeArrayCreate(VT_VARIANT, 1, (SAFEARRAYBOUND *)&ArrayBound)))
{
if (!SafeArrayAccessData(psfArray, (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.
pHtmlDoc2->write(psfArray);
// 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(psfArray);
}
// Release the IHTMLDocument2 object.
#ifndef UNICODE
bad:
#endif
pHtmlDoc2->Release();
}
// Release the DISPATCH object.
lpDispatch->Release();
}
// Release the IWebBrowser2 object.
pWebBrowser2->Release();
}
// No error?
if (bstr) return 0;
// An error
return -1;
}
long CWebBrowser::DisplayHTMLPage(HWND /*hwnd*/, LPCTSTR webPageName)
{
IWebBrowser2 *pWebBrowser2;
VARIANT varMyURL;
//
//
// Not implemented for multiple browsing...
//
//IOleObject **ppBrowserHandle;
//IOleObject *pBrowserObject;
//
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 ((ppBrowserHandle = (IOleObject **)GetWindowLong(hwnd, GWL_USERDATA)))
//{
// // Unembed the browser object, and release its resources.
// pBrowserObject = *ppBrowserHandle;
//}
//
// 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 (!m_pBrowserObj->QueryInterface(IID_IWebBrowser2, (void**)&pWebBrowser2))
{
// 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(&varMyURL);
varMyURL.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);
varMyURL.bstrVal = SysAllocString(buffer);
GlobalFree(buffer);
}
#else
varMyURL.bstrVal = SysAllocString(webPageName);
#endif
if (!varMyURL.bstrVal)
{
#ifndef UNICODE
badalloc:
#endif
pWebBrowser2->Release();
return -6;
}
// Call the Navigate2() function to actually display the page.
pWebBrowser2->Navigate2(&varMyURL, 0, 0, 0, 0);
// Free any resources (including the BSTR we allocated above).
VariantClear(&varMyURL);
// 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.
pWebBrowser2->Release();
// Success
return 0;
}
// failed
return -5;
}
long CWebBrowser::EmbedBrowserObject(HWND hwnd)
{
IWebBrowser2 *pWebBrowser2;
RECT rect;
CWBStorage Storage;
CWBClientSite *pClientSite = new CWBClientSite(hwnd);
// 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 OleCreate().
//
// 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 class (as returned by OleCreate()).
//
// 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 'm_pBrowserObj'), then we can call that
// function, and pass it args, as so:
//
// m_pBrowserObj->SetHostNames(SomeString, SomeString);
if (!OleCreate(CLSID_WebBrowser, IID_IOleObject, OLERENDER_DRAW, 0, (IOleClientSite *)pClientSite, &Storage, (void**)&m_pBrowserObj))
{
//
//
// Not implemented for multiple browsing...
//
// 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 **ppObj = &m_pBrowserObj;
//SetWindowLong(hwnd, GWL_USERDATA, (LONG)ppObj);
//
// 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 2 args to SetHostNames. Oh yeah, the L is because we need UNICODE strings.
// And BTW, the host and document names can be anything you want.
m_pBrowserObj->SetHostNames(L"My Host Name", 0);
GetClientRect(hwnd, &rect);
// Let browser object know that it is embedded in an OLE container.
if (!OleSetContainedObject((IUnknown *)m_pBrowserObj, 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.
if (!m_pBrowserObj->DoVerb(OLEIVERB_SHOW, NULL, (IOleClientSite *)pClientSite, -1, hwnd, &rect))
{
// 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.
if (!m_pBrowserObj->QueryInterface(IID_IWebBrowser2, (void**)&pWebBrowser2))
{
// 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().
pWebBrowser2->put_Left(0);
pWebBrowser2->put_Top(0);
pWebBrowser2->put_Width(rect.right);
pWebBrowser2->put_Height(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.
pWebBrowser2->Release();
// Success
return 0;
}
// Something went wrong!
// QueryInterface failed
}
// DoVerb Failed
}
// OleSetContainedObject failed
if (pClientSite)
{
delete pClientSite;
}
UnEmbedBrowserObject(hwnd);
return -3;
}
return -2;
}
类CWBStorage:
/********************************************************************
@created: 2005/12/30
@version: 0.1
@filename: WBStorage.h
@file base: WBStorage
@file ext: h
@author: Pomelo Wu
@purpose: CWBStorage, a class of implementation of IStorage
@remark: NULL
@revision history:
-- Date Ver. Modifier Description--
2006/01/16 0.1 Pomelo Create
*********************************************************************/
#ifndef __WBSTORAGE_H__
#define __WBSTORAGE_H__
#include <objidl.h>
class CWBStorage :
public IStorage
{
public:
// IUnknown methods
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef( void);
virtual ULONG STDMETHODCALLTYPE Release( void);
// IStorage methods
virtual HRESULT STDMETHODCALLTYPE CreateStream(
/* [string][in] */ const OLECHAR *pwcsName,
/* [in] */ DWORD grfMode,
/* [in] */ DWORD reserved1,
/* [in] */ DWORD reserved2,
/* [out] */ IStream **ppstm);
virtual /* [local] */ HRESULT STDMETHODCALLTYPE OpenStream(
/* [string][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ void *reserved1,
/* [in] */ DWORD grfMode,
/* [in] */ DWORD reserved2,
/* [out] */ IStream **ppstm);
virtual HRESULT STDMETHODCALLTYPE CreateStorage(
/* [string][in] */ const OLECHAR *pwcsName,
/* [in] */ DWORD grfMode,
/* [in] */ DWORD reserved1,
/* [in] */ DWORD reserved2,
/* [out] */ IStorage **ppstg);
virtual HRESULT STDMETHODCALLTYPE OpenStorage(
/* [string][unique][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ IStorage *pstgPriority,
/* [in] */ DWORD grfMode,
/* [unique][in] */ SNB snbExclude,
/* [in] */ DWORD reserved,
/* [out] */ IStorage **ppstg);
virtual HRESULT STDMETHODCALLTYPE CopyTo(
/* [in] */ DWORD ciidExclude,
/* [size_is][unique][in] */ const IID *rgiidExclude,
/* [unique][in] */ SNB snbExclude,
/* [unique][in] */ IStorage *pstgDest);
virtual HRESULT STDMETHODCALLTYPE MoveElementTo(
/* [string][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ IStorage *pstgDest,
/* [string][in] */ const OLECHAR *pwcsNewName,
/* [in] */ DWORD grfFlags);
virtual HRESULT STDMETHODCALLTYPE Commit(
/* [in] */ DWORD grfCommitFlags);
virtual HRESULT STDMETHODCALLTYPE Revert( void);
virtual /* [local] */ HRESULT STDMETHODCALLTYPE EnumElements(
/* [in] */ DWORD reserved1,
/* [size_is][unique][in] */ void *reserved2,
/* [in] */ DWORD reserved3,
/* [out] */ IEnumSTATSTG **ppenum);
virtual HRESULT STDMETHODCALLTYPE DestroyElement(
/* [string][in] */ const OLECHAR *pwcsName);
virtual HRESULT STDMETHODCALLTYPE RenameElement(
/* [string][in] */ const OLECHAR *pwcsOldName,
/* [string][in] */ const OLECHAR *pwcsNewName);
virtual HRESULT STDMETHODCALLTYPE SetElementTimes(
/* [string][unique][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ const FILETIME *pctime,
/* [unique][in] */ const FILETIME *patime,
/* [unique][in] */ const FILETIME *pmtime);
virtual HRESULT STDMETHODCALLTYPE SetClass(
/* [in] */ REFCLSID clsid);
virtual HRESULT STDMETHODCALLTYPE SetStateBits(
/* [in] */ DWORD grfStateBits,
/* [in] */ DWORD grfMask);
virtual HRESULT STDMETHODCALLTYPE Stat(
/* [out] */ STATSTG *pstatstg,
/* [in] */ DWORD grfStatFlag);
};
#endif //__WBSTORAGE_H__
/********************************************************************
@created: 2006/01/16
@version: 0.1
@filename: WBStorage.cpp
@file base: WBStorage
@file ext: cpp
@author: Pomelo Wu
@purpose: Implementation for class CWBStorage
@remark: NULL
@revision history:
-- Date Ver. Modifier Description--
2006/01/16 0.1 Pomelo Create
*********************************************************************/
#include "WBStorage.h"
// CWBStorage functions /
// NOTE: The browser object doesn't use the IStorage functions, so most of these are us just returning
// E_NOTIMPL so that anyone who *does* call these functions knows nothing is being done here.
HRESULT STDMETHODCALLTYPE CWBStorage::QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
NOTIMPLEMENTED;
}
ULONG STDMETHODCALLTYPE CWBStorage::AddRef( void)
{
return 1;
}
ULONG STDMETHODCALLTYPE CWBStorage::Release( void)
{
return 0;
}
HRESULT STDMETHODCALLTYPE CWBStorage::CreateStream(
/* [string][in] */ const OLECHAR *pwcsName,
/* [in] */ DWORD grfMode,
/* [in] */ DWORD reserved1,
/* [in] */ DWORD reserved2,
/* [out] */ IStream **ppstm)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::OpenStream(
/* [string][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ void *reserved1,
/* [in] */ DWORD grfMode,
/* [in] */ DWORD reserved2,
/* [out] */ IStream **ppstm)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::CreateStorage(
/* [string][in] */ const OLECHAR *pwcsName,
/* [in] */ DWORD grfMode,
/* [in] */ DWORD reserved1,
/* [in] */ DWORD reserved2,
/* [out] */ IStorage **ppstg)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::OpenStorage(
/* [string][unique][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ IStorage *pstgPriority,
/* [in] */ DWORD grfMode,
/* [unique][in] */ SNB snbExclude,
/* [in] */ DWORD reserved,
/* [out] */ IStorage **ppstg)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::CopyTo(
/* [in] */ DWORD ciidExclude,
/* [size_is][unique][in] */ const IID *rgiidExclude,
/* [unique][in] */ SNB snbExclude,
/* [unique][in] */ IStorage *pstgDest)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::MoveElementTo(
/* [string][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ IStorage *pstgDest,
/* [string][in] */ const OLECHAR *pwcsNewName,
/* [in] */ DWORD grfFlags)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::Commit(
/* [in] */ DWORD grfCommitFlags)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::Revert( void)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::EnumElements(
/* [in] */ DWORD reserved1,
/* [size_is][unique][in] */ void *reserved2,
/* [in] */ DWORD reserved3,
/* [out] */ IEnumSTATSTG **ppenum)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::DestroyElement(
/* [string][in] */ const OLECHAR *pwcsName)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::RenameElement(
/* [string][in] */ const OLECHAR *pwcsOldName,
/* [string][in] */ const OLECHAR *pwcsNewName)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::SetElementTimes(
/* [string][unique][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ const FILETIME *pctime,
/* [unique][in] */ const FILETIME *patime,
/* [unique][in] */ const FILETIME *pmtime)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::SetClass(
/* [in] */ REFCLSID clsid)
{
//NOTIMPLEMENTED;
return(S_OK);
}
HRESULT STDMETHODCALLTYPE CWBStorage::SetStateBits(
/* [in] */ DWORD grfStateBits,
/* [in] */ DWORD grfMask)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBStorage::Stat(
/* [out] */ STATSTG *pstatstg,
/* [in] */ DWORD grfStatFlag)
{
NOTIMPLEMENTED;
}
类CWBClientSite:
/********************************************************************
@created: 2006/01/16
@version: 0.1
@filename: WBClientSite.h
@file base: WBClientSite
@file ext: h
@author: Pomelo Wu
@purpose: Declaration for class CWBClientSite, a implemetation of
interface IOleClientSite, IOleInPlaceFrame and IOleInPlaceSite
@remark: NULL
@revision history:
-- Date Ver. Modifier Description--
2006/01/16 0.1 Pomelo Create
*********************************************************************/
#ifndef __WBCLIENTSITE_H__
#define __WBCLIENTSITE_H__
#include <oleidl.h>
class CWBClientSite :
public IOleClientSite, public IOleInPlaceFrame, public IOleInPlaceSite
{
public:
// constructors
CWBClientSite()
{}
CWBClientSite(HWND hwnd)
{
m_hWindow = hwnd;
}
//
// IUnknown methods
//
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef( void);
virtual ULONG STDMETHODCALLTYPE Release( void);
//
// IOleClientSite methods
//
virtual HRESULT STDMETHODCALLTYPE SaveObject( void);
virtual HRESULT STDMETHODCALLTYPE GetMoniker(
/* [in] */ DWORD dwAssign,
/* [in] */ DWORD dwWhichMoniker,
/* [out] */ IMoniker **ppmk);
virtual HRESULT STDMETHODCALLTYPE GetContainer(
/* [out] */ IOleContainer **ppContainer);
virtual HRESULT STDMETHODCALLTYPE ShowObject( void);
virtual HRESULT STDMETHODCALLTYPE OnShowWindow(
/* [in] */ BOOL fShow);
virtual HRESULT STDMETHODCALLTYPE RequestNewObjectLayout( void);
//
// IOleWindow methods
//
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE GetWindow(
/* [out] */ HWND *phwnd);
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(
/* [in] */ BOOL fEnterMode);
//
// IOleInPlaceUIWindow methods
//
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE GetBorder(
/* [out] */ LPRECT lprectBorder);
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE RequestBorderSpace(
/* [unique][in] */ LPCBORDERWIDTHS pborderwidths);
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE SetBorderSpace(
/* [unique][in] */ LPCBORDERWIDTHS pborderwidths);
virtual HRESULT STDMETHODCALLTYPE SetActiveObject(
/* [unique][in] */ IOleInPlaceActiveObject *pActiveObject,
/* [unique][string][in] */ LPCOLESTR pszObjName);
//
// IOleInPlaceFrame methods
//
virtual HRESULT STDMETHODCALLTYPE InsertMenus(
/* [in] */ HMENU hmenuShared,
/* [out][in] */ LPOLEMENUGROUPWIDTHS lpMenuWidths);
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE SetMenu(
/* [in] */ HMENU hmenuShared,
/* [in] */ HOLEMENU holemenu,
/* [in] */ HWND hwndActiveObject);
virtual HRESULT STDMETHODCALLTYPE RemoveMenus(
/* [in] */ HMENU hmenuShared);
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE SetStatusText(
/* [unique][in] */ LPCOLESTR pszStatusText);
virtual HRESULT STDMETHODCALLTYPE EnableModeless(
/* [in] */ BOOL fEnable);
virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(
/* [in] */ LPMSG lpmsg,
/* [in] */ WORD wID);
//
// IOleInPlaceSite methods
//
virtual HRESULT STDMETHODCALLTYPE CanInPlaceActivate( void);
virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivate( void);
virtual HRESULT STDMETHODCALLTYPE OnUIActivate( void);
virtual HRESULT STDMETHODCALLTYPE GetWindowContext(
/* [out] */ IOleInPlaceFrame **ppFrame,
/* [out] */ IOleInPlaceUIWindow **ppDoc,
/* [out] */ LPRECT lprcPosRect,
/* [out] */ LPRECT lprcClipRect,
/* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo);
virtual HRESULT STDMETHODCALLTYPE Scroll(
/* [in] */ SIZE scrollExtant);
virtual HRESULT STDMETHODCALLTYPE OnUIDeactivate(
/* [in] */ BOOL fUndoable);
virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate( void);
virtual HRESULT STDMETHODCALLTYPE DiscardUndoState( void);
virtual HRESULT STDMETHODCALLTYPE DeactivateAndUndo( void);
virtual HRESULT STDMETHODCALLTYPE OnPosRectChange(
/* [in] */ LPCRECT lprcPosRect);
/* //
// We don't want those functions to access global
// variables, because then we couldn't use more
// than one browser object. (ie, we 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 the
// CWBIOleInPlaceFrame function Frame_GetWindow() needs
// to access.
// */
HWND m_hWindow;
};
#endif //__WBCLIENTSITE_H__
/********************************************************************
@created: 2006/01/16
@version: 0.1
@filename: WBClientSite.cpp
@file base: WBClientSite
@file ext: cpp
@author: Pomelo Wu
@purpose: Implementation for class CWBClientSite
@remark: NULL
@revision history:
-- Date Ver. Modifier Description--
2006/01/16 0.1 Pomelo Create
*********************************************************************/
#include "WBClientSite.h"
// Implementation of CWBClientSite, a derived class of IOleClientSite, IOleInPlaceFrame, and IOleInPlaceSite
HRESULT STDMETHODCALLTYPE CWBClientSite::QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
// query the interface of IUnknown
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)))
{
*ppvObject = reinterpret_cast<IUnknown *> (this);
}
// query the interface of IOleClientSite
else if (!memcmp(&riid, &IID_IOleClientSite, sizeof(GUID)))
{
*ppvObject = (IOleClientSite *)this;
}
// query the interface of IOleInPlaceSite
else if (!memcmp(&riid, &IID_IOleInPlaceSite, sizeof(GUID)))
{
*ppvObject = (IOleInPlaceSite *)this;
}
// 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);
}
ULONG STDMETHODCALLTYPE CWBClientSite::AddRef( void)
{
return 1;
}
ULONG STDMETHODCALLTYPE CWBClientSite::Release( void)
{
return 0;
}
// IOleClientSite methods
HRESULT STDMETHODCALLTYPE CWBClientSite::SaveObject( void)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::GetMoniker(
/* [in] */ DWORD dwAssign,
/* [in] */ DWORD dwWhichMoniker,
/* [out] */ IMoniker **ppmk)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::GetContainer(
/* [out] */ IOleContainer **ppContainer)
{
// Tell the browser that we are a simple object and don't support a container
*ppContainer = 0;
return(E_NOINTERFACE);
}
HRESULT STDMETHODCALLTYPE CWBClientSite::ShowObject( void)
{
return(NOERROR);
}
HRESULT STDMETHODCALLTYPE CWBClientSite::OnShowWindow(
/* [in] */ BOOL fShow)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::RequestNewObjectLayout( void)
{
NOTIMPLEMENTED;
}
// IOleWindow methods
HRESULT STDMETHODCALLTYPE CWBClientSite::GetWindow(
/* [out] */ HWND *phwnd)
{
*phwnd = m_hWindow;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::ContextSensitiveHelp(
/* [in] */ BOOL fEnterMode)
{
NOTIMPLEMENTED;
}
// IOleInPlaceUIWindow methods
HRESULT STDMETHODCALLTYPE CWBClientSite::GetBorder(
/* [out] */ LPRECT lprectBorder)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::RequestBorderSpace(
/* [unique][in] */ LPCBORDERWIDTHS pborderwidths)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::SetBorderSpace(
/* [unique][in] */ LPCBORDERWIDTHS pborderwidths)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::SetActiveObject(
/* [unique][in] */ IOleInPlaceActiveObject *pActiveObject,
/* [unique][string][in] */ LPCOLESTR pszObjName)
{
return S_OK;
}
// IOleInPlaceFrame methods
HRESULT STDMETHODCALLTYPE CWBClientSite::InsertMenus(
/* [in] */ HMENU hmenuShared,
/* [out][in] */ LPOLEMENUGROUPWIDTHS lpMenuWidths)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::SetMenu(
/* [in] */ HMENU hmenuShared,
/* [in] */ HOLEMENU holemenu,
/* [in] */ HWND hwndActiveObject)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::RemoveMenus(
/* [in] */ HMENU hmenuShared)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::SetStatusText(
/* [unique][in] */ LPCOLESTR pszStatusText)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::EnableModeless(
/* [in] */ BOOL fEnable)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::TranslateAccelerator(
/* [in] */ LPMSG lpmsg,
/* [in] */ WORD wID)
{
NOTIMPLEMENTED;
}
// IOleInPlaceSite methods
HRESULT STDMETHODCALLTYPE CWBClientSite::CanInPlaceActivate( void)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::OnInPlaceActivate( void)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::OnUIActivate( void)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::GetWindowContext(
/* [out] */ IOleInPlaceFrame **ppFrame,
/* [out] */ IOleInPlaceUIWindow **ppDoc,
/* [out] */ LPRECT lprcPosRect,
/* [out] */ LPRECT lprcClipRect,
/* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
*ppFrame = (IOleInPlaceFrame *)this; // maybe incorrect
// We have no OLEINPLACEUIWINDOW
*ppDoc = 0;
// Fill in some other info for the browser
lpFrameInfo->fMDIApp = FALSE;
lpFrameInfo->hwndFrame = m_hWindow; // maybe incorrect
lpFrameInfo->haccel = 0;
lpFrameInfo->cAccelEntries = 0;
// Give the browser the dimensions of where it can draw. We give it our entire window to fill
GetClientRect(lpFrameInfo->hwndFrame, lprcPosRect);
GetClientRect(lpFrameInfo->hwndFrame, lprcClipRect);
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::Scroll(
/* [in] */ SIZE scrollExtant)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::OnUIDeactivate(
/* [in] */ BOOL fUndoable)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::OnInPlaceDeactivate( void)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::DiscardUndoState( void)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::DeactivateAndUndo( void)
{
NOTIMPLEMENTED;
}
HRESULT STDMETHODCALLTYPE CWBClientSite::OnPosRectChange(
/* [in] */ LPCRECT lprcPosRect)
{
return S_OK;
}
调用示例:
// Sample.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Resource.h"
#include <mshtml.h> // Defines of stuff like IHTMLDocument2. This is an include file with Visual C 6 and above
#include <exdisp.h> // Defines of stuff like IWebBrowser2. This is an include file with Visual C 6 and above
#include "WebBrowser.h"
#pragma comment (lib, "webbrowser.lib")
CWebBrowser *g_pWebBrowser = NULL;
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// COM initialization
OleInitialize(NULL);
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_IEMINI, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_IEMINI));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
OleUninitialize();
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_IEMINI));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_IEMINI);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
//DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
if (g_pWebBrowser)
{
g_pWebBrowser->DisplayHTMLPage(hWnd, L"http://www.microsoft.com");
}
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
if (g_pWebBrowser)
{
g_pWebBrowser->UnEmbedBrowserObject(hWnd);
delete g_pWebBrowser;
}
break;
case WM_CREATE:
g_pWebBrowser = new CWebBrowser;
if (g_pWebBrowser)
g_pWebBrowser->EmbedBrowserObject(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
BTW,没有做异常处理。
注:源码下载地址:http://download.csdn.net/download/pomelowu/970394
转自:http://blog.csdn.net/pomelowu/article/details/582363