WebBrowser Control的一个简单C++封装

想在自己的窗口中放上一个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,没有做异常处理。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值