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