(转)WebBrowser Control的一个简单C++封装

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值