使用write()方法在Embedded IWebBrowser2中完成DocumentComplete事件

DocumentComplete event in Embedded IWebBrowser2 using write() method

本文关键字:DocumentComplete 事件 IWebBrowser2 Embedded write 方法 使用      更新时间:2023-10-16

我一直在努力寻找,但仍然没有找到任何解决方案。我使用的是本机win32 c++(没有MFC、ATL或.NET)

我正在用IHTMLDocument2->write()加载一个html文档。我希望在页面准备好显示时获得事件,这意味着所有图像和元素都已下载并呈现

在嵌入式浏览器对象之后从这里嵌入web控件(IWebBrowser2),嵌入javascript';s onkeydown和onkeyup没有开火,从这里开始http://www.codeproject.com/Articles/3365/Embed-an-HTML-control-in-your-own-window-using-pla我设法让一个嵌入式web浏览器正常工作,并加载了一个html bstr。

我修改了控件,如下所示。现在我可以从文档中获取事件,但永远无法获取DISPID_DOCUMENTCOMPLETE。获取此事件的唯一解决方法是当html中有一个具有src属性的iframe:时

<html>
  ...
  <body>
    <iframe src="...">...</iframe>
  </body>
</html>

然后,当src准备好显示时,<iframe src="...">创建的窗口启动DISPID_DOCUMENTCOMPLETE。(写入内容后需要刷新浏览器)

如果<iframe>没有"src",则触发事件,但从不呈现iframe内容。

在http://msdn.microsoft.com/en-us/library/aa768282.aspx它说文档中的每个窗口都会触发一个documentComplete事件,但由于我没有使用"Navigate"加载html内容,而且documentComplete从未被触发,我怀疑documentComplete只在"Navigate(导航)"之后才会被触发,而不是在使用"write()"时,也没有在使用"write()+close()"加载html时被触发。

我还试图覆盖"它的"互联网协议,所以当导航到"its://..."我设法加载了文档(想法来自这里:http://sumatrapdf.googlecode.com/svn/trunk/src/utils/HtmlWindow.cpp)。然后,我得到了每个导航的DISPID_DOCUMENTCOMPLETE,但在10-12次导航后,程序chrash(它释放EventSink对象的次数比引用的次数多…奇怪)。经过几天的尝试,我得出的结论是,我没有太多的经验来实现这一点,而且这不是一个真正好的解决方案,只是一个丑陋的变通方法,我决定回到IHTMLDocument2->write()。

我还尝试将getDISPID_HTMLEMENTEVENTS2_ONDREADYSTATECHANGE附加到DIID_HTMLDocumentEvents2,但根本没有成功。

有什么解决办法吗?

EmbBrowser.h:

(EmbBrowserEventSink是一个简单的IDIspatch实现,IBrowserEventListener是一个带有onDocumentComplete和onClick方法的接口)

    #pragma once
#include <stdio.h>
#include <Windows.h>
#include <string>
#include <Exdisp.h>
#include <comdef.h> // for variant_t
#include <exception>
#include <mshtml.h>    // Defines of stuff like IHTMLDocument2. This is an include file with Visual C 6 and above
#include "EmbBrowserEventSink.h"
//------------------------------------------------------------------------------
class EmbBrowser : public IUnknown, public IOleClientSite, public IOleInPlaceSite, public IStorage{
public:
  EmbBrowser(HWND _mainWindow, IBrowserEventListener *browserEventListener = NULL);
  ~EmbBrowser();
  HRESULT STDMETHODCALLTYPE setEventListener(IBrowserEventListener *browserEventListener) {
    this->mBrowserEventListener = browserEventListener;
    return S_OK;
  };
  HRESULT STDMETHODCALLTYPE hideScrollBars();
  HRESULT STDMETHODCALLTYPE displayHTMLStr(LPCTSTR htmlSource);
  HRESULT STDMETHODCALLTYPE pixelToHiMetric(const RECT& _rc, RECT *_metricRc);
  virtual HRESULT STDMETHODCALLTYPE setRect(const RECT &_rc);
  virtual HRESULT STDMETHODCALLTYPE adjustSize(HWND hWnd);
  virtual HRESULT STDMETHODCALLTYPE navigate(LPCTSTR _url);
  // ----- IUnknown -----
  virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void**ppvObject) override;
  virtual ULONG STDMETHODCALLTYPE AddRef(void) override { return ++m_comRefCount; };
  virtual ULONG STDMETHODCALLTYPE Release( void) override  {
    if (!--m_comRefCount) {
      delete this;
    }
    return m_comRefCount;
  };
  // ---------- IOleWindow ----------
  virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE GetWindow(/* [out] */ __RPC__deref_out_opt HWND *phwnd) override;
  virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp( /* [in] */ BOOL fEnterMode) override { return E_NOTIMPL; };
  // ---------- IOleInPlaceSite ----------
  virtual HRESULT STDMETHODCALLTYPE CanInPlaceActivate(void) override { return S_OK; };
  virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivate(void) override;
  virtual HRESULT STDMETHODCALLTYPE OnUIActivate(void) override { return S_OK; };
  virtual HRESULT STDMETHODCALLTYPE GetWindowContext( 
    /* [out] */ __RPC__deref_out_opt IOleInPlaceFrame **ppFrame,
    /* [out] */ __RPC__deref_out_opt IOleInPlaceUIWindow **ppDoc,
    /* [out] */ __RPC__out LPRECT lprcPosRect,
    /* [out] */ __RPC__out LPRECT lprcClipRect,
    /* [out][in] */ __RPC__inout LPOLEINPLACEFRAMEINFO lpFrameInfo) override;
  virtual HRESULT STDMETHODCALLTYPE Scroll(/* [in] */ SIZE scrollExtant) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE OnUIDeactivate(/* [in] */ BOOL fUndoable) override { return S_OK; };
  virtual HWND    STDMETHODCALLTYPE GetControlWindow();
  virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate(void) override;
  virtual HRESULT STDMETHODCALLTYPE DiscardUndoState(void) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE DeactivateAndUndo(void) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE OnPosRectChange(/* [in] */ __RPC__in LPCRECT lprcPosRect) override { return E_NOTIMPL; };
  // ---------- IOleClientSite ----------
  virtual HRESULT STDMETHODCALLTYPE SaveObject(void) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE GetMoniker(
    /* [in] */ DWORD dwAssign,
    /* [in] */ DWORD dwWhichMoniker,
    /* [out] */ __RPC__deref_out_opt IMoniker **ppmk) override
  {
    if((dwAssign == OLEGETMONIKER_ONLYIFTHERE) && (dwWhichMoniker == OLEWHICHMK_CONTAINER)) {
      return E_FAIL;
    }
    return E_NOTIMPL;
  };
  virtual HRESULT STDMETHODCALLTYPE GetContainer(/* [out] */ __RPC__deref_out_opt IOleContainer **ppContainer) override { return E_NOINTERFACE; };
  virtual HRESULT STDMETHODCALLTYPE ShowObject( void) override { return S_OK; };
  virtual HRESULT STDMETHODCALLTYPE OnShowWindow( /* [in] */ BOOL fShow) override { return S_OK; };;
  virtual HRESULT STDMETHODCALLTYPE RequestNewObjectLayout( void) override { return E_NOTIMPL; };
  // ----- IStorage -----
  virtual HRESULT STDMETHODCALLTYPE CreateStream( 
    /* [string][in] */ __RPC__in_string const OLECHAR *pwcsName,
    /* [in] */ DWORD grfMode,
    /* [in] */ DWORD reserved1,
    /* [in] */ DWORD reserved2,
    /* [out] */ __RPC__deref_out_opt IStream **ppstm) override { return E_NOTIMPL; };
  virtual /* [local] */ HRESULT STDMETHODCALLTYPE OpenStream( 
    /* [string][in] */ const OLECHAR *pwcsName,
    /* [unique][in] */ void *reserved1,
    /* [in] */ DWORD grfMode,
    /* [in] */ DWORD reserved2,
    /* [out] */ IStream **ppstm) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE CreateStorage( 
    /* [string][in] */ __RPC__in_string const OLECHAR *pwcsName,
    /* [in] */ DWORD grfMode,
    /* [in] */ DWORD reserved1,
    /* [in] */ DWORD reserved2,
    /* [out] */ __RPC__deref_out_opt IStorage **ppstg) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE OpenStorage( 
    /* [string][unique][in] */ __RPC__in_opt_string const OLECHAR *pwcsName,
    /* [unique][in] */ __RPC__in_opt IStorage *pstgPriority,
    /* [in] */ DWORD grfMode,
    /* [unique][in] */ __RPC__deref_opt_in_opt SNB snbExclude,
    /* [in] */ DWORD reserved,
    /* [out] */ __RPC__deref_out_opt IStorage **ppstg) override { return E_NOTIMPL; };
  virtual /* [local] */ HRESULT STDMETHODCALLTYPE CopyTo( 
    /* [in] */ DWORD ciidExclude,
    /* [size_is][unique][in] */ const IID *rgiidExclude,
    /* [annotation][unique][in] */ 
    __RPC__in_opt  SNB snbExclude,
    /* [unique][in] */ IStorage *pstgDest) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE MoveElementTo( 
    /* [string][in] */ __RPC__in_string const OLECHAR *pwcsName,
    /* [unique][in] */ __RPC__in_opt IStorage *pstgDest,
    /* [string][in] */ __RPC__in_string const OLECHAR *pwcsNewName,
    /* [in] */ DWORD grfFlags) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE Commit(/* [in] */ DWORD grfCommitFlags) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE Revert(void) override { return E_NOTIMPL; };
  virtual /* [local] */ HRESULT STDMETHODCALLTYPE EnumElements( 
    /* [in] */ DWORD reserved1,
    /* [size_is][unique][in] */ void *reserved2,
    /* [in] */ DWORD reserved3,
    /* [out] */ IEnumSTATSTG **ppenum) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE DestroyElement(/* [string][in] */ __RPC__in_string const OLECHAR *pwcsName) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE RenameElement( 
    /* [string][in] */ __RPC__in_string const OLECHAR *pwcsOldName,
    /* [string][in] */ __RPC__in_string const OLECHAR *pwcsNewName) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE SetElementTimes( 
    /* [string][unique][in] */ __RPC__in_opt_string const OLECHAR *pwcsName,
    /* [unique][in] */ __RPC__in_opt const FILETIME *pctime,
    /* [unique][in] */ __RPC__in_opt const FILETIME *patime,
    /* [unique][in] */ __RPC__in_opt const FILETIME *pmtime) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE SetClass(/* [in] */ __RPC__in REFCLSID clsid) override { return S_OK; };
  virtual HRESULT STDMETHODCALLTYPE SetStateBits( 
    /* [in] */ DWORD grfStateBits,
    /* [in] */ DWORD grfMask) override { return E_NOTIMPL; };
  virtual HRESULT STDMETHODCALLTYPE Stat( 
    /* [out] */ __RPC__out STATSTG *pstatstg,
    /* [in] */ DWORD grfStatFlag) override { return E_NOTIMPL; };

protected:
private:
  IOleObject            *m_oleObject;
  LONG                  m_comRefCount;
  HWND                  m_mainWindow;
  RECT                  m_objectRect;
  IWebBrowser2          *m_webBrowser;
  IOleInPlaceObject     *m_oleInPlaceObject;
  HWND                  m_controlWindow;
  DWORD                 mAdviseBrowserEventsCookie;
  IBrowserEventListener *mBrowserEventListener;
  EmbBrowserEventSink   *mEmbBrowserEventSink;
  HRESULT STDMETHODCALLTYPE connectEvents();
  HRESULT STDMETHODCALLTYPE disconnectEvents();
};

EmbBrowser.cpp

#include "StdAfx.h"
#include "EmbBrowser.h"
EmbBrowser::EmbBrowser(HWND _mainWindow, IBrowserEventListener *browserEventListener) : m_mainWindow(_mainWindow),
  mBrowserEventListener(browserEventListener), m_comRefCount(0), mEmbBrowserEventSink(NULL), mAdviseBrowserEventsCookie(0)
{
  ::SetRect(&m_objectRect, -300, -300, 300, 300);
  HRESULT hr = ::OleCreate(CLSID_WebBrowser, IID_IOleObject, OLERENDER_DRAW, 0, this, this, (void**)&m_oleObject);
  if (FAILED(hr)) {
    throw new exception("OleCreate() failed");
  }
  hr = m_oleObject->SetClientSite(this);
  hr = OleSetContainedObject(m_oleObject, TRUE);
  if (FAILED(m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, -1, m_mainWindow, &m_objectRect))) {
    throw new exception("DoVerb(OLEIVERB_INPLACEACTIVATE) failed");
  }
  hr = m_oleObject->QueryInterface(&m_webBrowser);
  if (FAILED(hr)) {
    throw new exception("QueryInterface(IWebBrowser) failed");
  }
  this->navigate(L"about:blank");
}
EmbBrowser::~EmbBrowser() {
  this->m_webBrowser->Release();
  this->m_oleObject->Close(OLECLOSE_NOSAVE);
  this->m_oleObject->Release();
}
HRESULT STDMETHODCALLTYPE EmbBrowser::navigate(LPCTSTR _url) {
  BSTR url;
  url = SysAllocString(_url);
  variant_t flags(0x02u); // navNoHistory;
  HRESULT hr = m_webBrowser->Navigate(url, &flags, NULL, NULL, NULL);
  SysFreeString(url);
  return hr;
}
HRESULT STDMETHODCALLTYPE EmbBrowser::hideScrollBars() {
  HRESULT           hr;
  IDispatch         *pDocDispatch = 0;
  IHTMLDocument2    *pHtmlDocument = 0;
  IHTMLElement      *pBodyElm = 0;
  IHTMLBodyElement  *pBody = 0;
  VARIANT           v;
  hr = m_webBrowser->get_Document(&pDocDispatch);
  if (FAILED(hr) || !pDocDispatch) {
    goto hideScrollBar_clean;
  }
  hr = pDocDispatch->QueryInterface(IID_IHTMLDocument2, (void **) &pHtmlDocument);
  if (FAILED(hr) && !pHtmlDocument) {
    goto hideScrollBar_clean;
  }
  hr = pHtmlDocument->get_body(&pBodyElm);
  if (FAILED(hr) && !pBodyElm) {
    goto hideScrollBar_clean;
  }
  hr = pBodyElm->QueryInterface(IID_IHTMLBodyElement, (void **) &pBody);
  if (FAILED(hr) && !pBody) {
    goto hideScrollBar_clean;
  }
  v.vt = VT_INT;
  v.intVal = 0;
  pBody->put_scroll(L"no");
  pBody->put_leftMargin(v);
  pBody->put_topMargin(v);

hideScrollBar_clean:
  if (pBody) {
    pBody->Release();
  }
  if (pBodyElm) {
    pBodyElm->Release();
  }
  if (pHtmlDocument) {
    pHtmlDocument->Release();
  }
  if (pDocDispatch) {
    pDocDispatch->Release();
  }
  return hr;
}
HRESULT STDMETHODCALLTYPE EmbBrowser::displayHTMLStr(LPCTSTR htmlSource) {
  // This is used by DisplayHTMLStr(). It can be global because we never change it.
  static const SAFEARRAYBOUND ArrayBound = {1, 0};
  HRESULT                   hr;
  IDispatch                 *pDispatch = 0;
  IHTMLDocument2            *pHtmlDoc2 = 0;
  SAFEARRAY                 *sfArray = 0;
  VARIANT                   *pVar = 0;
  BSTR                      bstr = 0;
  hr = m_webBrowser->get_Document(&pDispatch);
  if (FAILED(hr) || !pDispatch) {
    goto displayHTMLStr_clean;
  }
  hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **) &pHtmlDoc2);
  if (FAILED(hr) || !pHtmlDoc2) {
    goto displayHTMLStr_clean;
  }
  // Our HTML must be in the form of a BSTR. And it must be passed to write() in an
  // array of "VARIENT" structs. So let's create all that.
  sfArray = SafeArrayCreate(VT_VARIANT, 1, (SAFEARRAYBOUND *) &ArrayBound);
  if (!sfArray) {
    goto displayHTMLStr_clean;
  }
  hr = SafeArrayAccessData(sfArray, (void**) &pVar);
  if (FAILED(hr)) {
    goto displayHTMLStr_clean;
  }
  pVar->vt = VT_BSTR;
#ifndef UNICODE
  {
    wchar_t    *buffer;
    DWORD      size;
    size = MultiByteToWideChar(CP_ACP, 0, htmlSource, -1, 0, 0);
    if (!(buffer = (wchar_t *)GlobalAlloc(GMEM_FIXED, sizeof(wchar_t) * size))) {
      goto displayHTMLStr_clean;
    }
    MultiByteToWideChar(CP_ACP, 0, htmlSource, -1, buffer, size);
    bstr = SysAllocString(buffer);
    GlobalFree(buffer);
  }
#else
  bstr = SysAllocString(htmlSource);
#endif
  if (!bstr) {
    hr = E_OUTOFMEMORY;
    goto displayHTMLStr_clean;
  }
  // Connect HTMLDocumentEvents2 to get onDocumentComplete and onClick events
  this->connectEvents();
  //mEmbBrowserEventSink->setFinishedWriting(false);
  hr = pHtmlDoc2->clear();
  if (FAILED(hr)) {
    goto displayHTMLStr_clean;
  }
  hr = pHtmlDoc2->write(sfArray);
  if (FAILED(hr)) {
    goto displayHTMLStr_clean;
  }
  hr = pHtmlDoc2->close();
  if (FAILED(hr)) {
    goto displayHTMLStr_clean;
  }
  //mEmbBrowserEventSink->setFinishedWriting(true);
  //hr = m_webBrowser->Refresh();
  //if (FAILED(hr)) {
  //  goto displayHTMLStr_clean;
  //}
  //this->mBrowserEventListener->onDocumentComplete(true);

displayHTMLStr_clean:
  // Normally, we'd need to free our BSTR, but SafeArrayDestroy() does it for us
  // SysFreeString(bstr);
  if (bstr) {
    SysFreeString(bstr);
  }
  if (sfArray) {
    // SafeArrayDestroy(sfArray);
    SafeArrayUnaccessData(sfArray);
  }
  if (pHtmlDoc2) {
    pHtmlDoc2->Release();
  }
  if (pDispatch) {
    pDispatch->Release();
  }
  return hr;
}
HRESULT STDMETHODCALLTYPE EmbBrowser::connectEvents() {
  HRESULT                   hr;
  IConnectionPointContainer *pCPC = 0;
  IConnectionPoint          *pCP = 0;
  IUnknown                  *pUnkEventSink = 0;
  this->disconnectEvents();
  this->mEmbBrowserEventSink = new EmbBrowserEventSink(m_webBrowser, this->mBrowserEventListener);
  hr = this->mEmbBrowserEventSink->QueryInterface(IID_IUnknown, (void **) &pUnkEventSink);
  if (FAILED(hr) || !pUnkEventSink) {
    goto connectEvents_clean;
  }
  hr = /*pHtmlDoc2*/m_webBrowser->QueryInterface(IID_IConnectionPointContainer, (void **) &pCPC);
  if (FAILED(hr) || !pCPC) {
    goto connectEvents_clean;
  }
  hr = pCPC->FindConnectionPoint(/*DIID_HTMLDocumentEvents2*/ DIID_DWebBrowserEvents2, &pCP);
  if (FAILED(hr) || !pCP) {
    goto connectEvents_clean;
  }
  hr = pCP->Advise(pUnkEventSink, &mAdviseBrowserEventsCookie);
  if (FAILED(hr)) {
    goto connectEvents_clean;
  }
connectEvents_clean:
  if (pCP) {
    pCP->Release();
  }
  if (pCPC) {
    pCPC->Release();
  }
  if (pUnkEventSink) {
    pUnkEventSink->Release();
  }
  return hr;
}
HRESULT STDMETHODCALLTYPE EmbBrowser::disconnectEvents() {
  HRESULT                   hr;
  IDispatch                 *pDispatch = 0;
  IHTMLDocument2            *pHtmlDoc2 = 0;
  IConnectionPointContainer *pCPC = 0;
  IConnectionPoint          *pCP = 0;
  if (!mAdviseHTMLEventsCookie) {
    hr = S_OK;
    goto disconnectHtmlEvents_clean;
  }
  //hr = m_webBrowser->get_Document(&pDispatch);
  //if (FAILED(hr) || !pDispatch) {
  //  goto disconnectHtmlEvents_clean;
  //}
  //hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **) &pHtmlDoc2);
  //if (FAILED(hr) || !pHtmlDoc2) {
  //  goto disconnectHtmlEvents_clean;
  //}
  hr = /*pHtmlDoc2*/this->m_webBrowser->QueryInterface(IID_IConnectionPointContainer, (void **) &pCPC);
  if (FAILED(hr) || !pCPC) {
    goto disconnectHtmlEvents_clean;
  }
  hr = pCPC->FindConnectionPoint(/*DIID_HTMLDocumentEvents2*/ DIID_DWebBrowserEvents2, &pCP);
  if (FAILED(hr) || !pCP) {
    goto disconnectHtmlEvents_clean;
  }
  hr = pCP->Unadvise(mAdviseBrowserEventsCookie);
  if (FAILED(hr)) {
    goto disconnectHtmlEvents_clean;
  }
  mAdviseBrowserEventsCookie= 0;

disconnectHtmlEvents_clean:
  if (pCP) {
    pCP->Release();
  }
  if (pCPC) {
    pCPC->Release();
  }
  if (pHtmlDoc2) {
    pHtmlDoc2->Release();
  }
  if (pDispatch) {
    pDispatch->Release();
  }
  return hr;
}
HRESULT STDMETHODCALLTYPE EmbBrowser::pixelToHiMetric(const RECT& _rc, RECT *_metricRc) {
  static bool s_initialized = false;
  static int s_pixelsPerInchX, s_pixelsPerInchY;
  if (!_metricRc) {
    return E_INVALIDARG;
  }
  if (!s_initialized) {
    HDC hdc = ::GetDC(NULL);
    s_pixelsPerInchX = ::GetDeviceCaps(hdc, LOGPIXELSX);
    s_pixelsPerInchY = ::GetDeviceCaps(hdc, LOGPIXELSY);
    ::ReleaseDC(NULL, hdc);
    s_initialized = true;
  }
  RECT rc;
  _metricRc->left = MulDiv(2540, _rc.left, s_pixelsPerInchX);
  _metricRc->top = MulDiv(2540, _rc.top, s_pixelsPerInchY);
  _metricRc->right = MulDiv(2540, _rc.right, s_pixelsPerInchX);
  _metricRc->bottom = MulDiv(2540, _rc.bottom, s_pixelsPerInchY);
  return S_OK;
}

HRESULT STDMETHODCALLTYPE EmbBrowser::setRect(const RECT &_rc) {
  HRESULT hr = E_FAIL;
  m_objectRect = _rc;
  {
    RECT hiMetricRect;
    hr = pixelToHiMetric(m_objectRect, &hiMetricRect);
    SIZEL sz;
    sz.cx = hiMetricRect.right - hiMetricRect.left;
    sz.cy = hiMetricRect.bottom - hiMetricRect.top;
    m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
  }
  if (m_oleInPlaceObject != NULL) {
    hr = m_oleInPlaceObject->SetObjectRects(&m_objectRect, &m_objectRect);
  }
  return S_OK;
}
HRESULT STDMETHODCALLTYPE EmbBrowser::adjustSize(HWND hWnd) {
  RECT rc;
  GetWindowRect(hWnd, &rc);
  rc.bottom -= rc.top;
  rc.top    -= rc.top;
  rc.right  -= rc.left;
  rc.left   -= rc.left;
  return setRect(rc);
}
// -----== IUnknown ==----->
HRESULT STDMETHODCALLTYPE EmbBrowser::QueryInterface(REFIID riid, void **ppvObject) {
  if (riid == __uuidof(IUnknown)) {
    (*ppvObject) = static_cast<IUnknown *> (this);
  } else if (riid == __uuidof(IOleClientSite)) {
    (*ppvObject) = static_cast<IOleClientSite *> (this);
  } else if (riid == __uuidof(IOleInPlaceSite)) {
    (*ppvObject) = static_cast<IOleInPlaceSite *> (this);
  } else if(riid == __uuidof(IStorage)) {
    (*ppvObject) = static_cast<IStorage *> (this);
  } else if (riid == __uuidof(IOleWindow)) {
    (*ppvObject) = static_cast<IOleWindow *> (this);
  } else {
    (*ppvObject) = 0;
    return E_NOINTERFACE;
  }
  AddRef(); // implicit AddRef()
  return S_OK;
}
// ----------== IOleWindow ==---------->
HRESULT STDMETHODCALLTYPE EmbBrowser::GetWindow(__RPC__deref_out_opt HWND *phwnd) {
  (*phwnd) = m_mainWindow;
  return S_OK;
}
// ----------== IOleInPlaceSite ==---------->
HRESULT STDMETHODCALLTYPE EmbBrowser::OnInPlaceActivate(void) {
  OleLockRunning(m_oleObject, TRUE, FALSE);
  m_oleObject->QueryInterface(&m_oleInPlaceObject);
  m_oleInPlaceObject->SetObjectRects(&m_objectRect, &m_objectRect);
  return S_OK;
}
HRESULT STDMETHODCALLTYPE EmbBrowser::GetWindowContext(__RPC__deref_out_opt IOleInPlaceFrame **ppFrame,
                                                       __RPC__deref_out_opt IOleInPlaceUIWindow **ppDoc,
                                                       __RPC__out LPRECT lprcPosRect,__RPC__out LPRECT lprcClipRect,
                                                       __RPC__inout LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
  HWND hwnd = m_mainWindow;
  (*ppFrame) = NULL;
  (*ppDoc) = NULL;
  (*lprcPosRect).left   = m_objectRect.left;
  (*lprcPosRect).top    = m_objectRect.top;
  (*lprcPosRect).right  = m_objectRect.right;
  (*lprcPosRect).bottom = m_objectRect.bottom;
  *lprcClipRect = *lprcPosRect;
  lpFrameInfo->fMDIApp = false;
  lpFrameInfo->hwndFrame = hwnd;
  lpFrameInfo->haccel = NULL;
  lpFrameInfo->cAccelEntries = 0;
  return S_OK;
}
HWND STDMETHODCALLTYPE EmbBrowser::GetControlWindow() {
  if(m_controlWindow != NULL) {
    return m_controlWindow;
  }
  if(m_oleInPlaceObject == NULL) {
    return NULL;
  }
  m_oleInPlaceObject->GetWindow(&m_controlWindow);
  return m_controlWindow;
}
HRESULT STDMETHODCALLTYPE EmbBrowser::OnInPlaceDeactivate(void) {
  m_controlWindow = NULL;
  m_oleInPlaceObject = NULL;
  return S_OK;
}

多亏了Remy,我再次尝试使用IPersistStreamInit加载,现在它似乎可以工作了。这是新的显示HTMLStr():

HRESULT STDMETHODCALLTYPE EmbBrowser::displayHTMLStr(LPCTSTR htmlSource) {
  HRESULT                   hr;
  IDispatch                 *pDispatch = 0;
  IHTMLDocument2            *pHtmlDoc2 = 0;
  IPersistStreamInit        *pPSI = 0;
  IStream                   *pStream = 0;
  HGLOBAL                   hHTMLContent;
  hr = m_webBrowser->get_Document(&pDispatch);
  if (FAILED(hr) || !pDispatch) {
    goto displayHTMLStr_clean;
  }
  hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **) &pHtmlDoc2);
  if (FAILED(hr) || !pHtmlDoc2) {
    goto displayHTMLStr_clean;
  }
  hr = pHtmlDoc2->QueryInterface(IID_IPersistStreamInit, (void **) &pPSI);
  if (FAILED(hr) || !pPSI) {
    goto displayHTMLStr_clean;
  }
  // allocate global memory to copy the HTML content to
  hHTMLContent = ::GlobalAlloc(GPTR, (::_tcslen(htmlSource) + 1) * sizeof(TCHAR));
  if (!hHTMLContent) {
    hr = E_OUTOFMEMORY;
    goto displayHTMLStr_clean;
  }
  ::_tcscpy((TCHAR *) hHTMLContent, htmlSource);
  // create a stream object based on the HTML content
  hr = ::CreateStreamOnHGlobal(hHTMLContent, TRUE, &pStream);
  if (FAILED(hr) || !pStream) {
    goto displayHTMLStr_clean;
  }
  hr = pPSI->InitNew();
  if (FAILED(hr)) {
    goto displayHTMLStr_clean;
  }
  // Connect HTMLDocumentEvents2 to get onDocumentComplete and onClick events
  this->connectEvents();
  hr = pPSI->Load(pStream);
  _tprintf(_T("Written: n%snn"), htmlSource);

displayHTMLStr_clean:
  if (pStream) {
    pStream->Release();
  }
  if (hHTMLContent) {
    GlobalFree(hHTMLContent);
  }
  if (pPSI) {
    pPSI->Release();
  }
  if (pHtmlDoc2) {
    pHtmlDoc2->Release();
  }
  if (pDispatch) {
    pDispatch->Release();
  }
  return hr;
}
相关文章:
  • 没有找到相关文章