Событие DocumentComplete во встроенном IWebBrowser2 с использованием метода write ()

Я долго искал это, но до сих пор не нашел никакого решения. Я использую родной Win32 C ++ (без MFC, ATL или .NET)

Я загружаю HTML-документ с помощью IHTMLDocument2-> write ().
Я хотел бы получить событие, когда страница готова к показу, а это означает, что все изображения и элементы загружаются и отображаются.

Следуя встроенному объекту браузера отсюда встроенный веб-контроль (IWebBrowser2), встроенный javascript onkeydown и onkeyup не запускаются и отсюда http://www.codeproject.com/Articles/3365/Embed-an-HTML-control-in-your-own-window-using-pla Мне удалось заставить встроенный веб-браузер работать нормально и загружать HTML-BSTR.

Я изменил элемент управления, как показано ниже.
Теперь я могу получить события из документа, но никогда не получаю DISPID_DOCUMENTCOMPLETE.
Единственный обходной путь для получения этого события — это когда в html есть iframe с атрибутом src:

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

Затем окно, созданное <iframe src="..."> запускает DISPID_DOCUMENTCOMPLETE, когда src готов к показу. (Требуется обновить браузер после записи содержимого)

Если <iframe> не имеет «src», тогда событие запускается, но содержимое iframe никогда не отображается.

В http://msdn.microsoft.com/en-us/library/aa768282.aspx он говорит, что одно событие documentComplete будет запущено для каждого окна в документе, но, поскольку я не использую «Navigate» для загрузки html-содержимого, а DocumentComplete никогда не запускается, я подозреваю, что DocumentComplete запускается только после «Navigate», а не когда не используя «write ()» ни при использовании «write () + close ()» для загрузки html.

Я также пытался переопределить «свой» интернет-протокол, поэтому при переходе к «свое: // …» мне удалось загрузить документ (идея здесь: http://sumatrapdf.googlecode.com/svn/trunk/src/utils/HtmlWindow.cpp). Затем я получил DISPID_DOCUMENTCOMPLETE для каждой навигации, но после 10-12 навигаций программа зависает (объект EventSink освобождается больше раз, чем ссылается … странно). После нескольких дней попыток я пришел к выводу, что я не настолько опытен, чтобы заставить это работать, и так как это было не очень хорошее решение, просто уродливый обходной путь, я решил вернуться к IHTMLDocument2-> write ().

Я также пытался присоединить к DIID_HTMLDocumentEvents2 метод get DISPID_HTMLELEMENTEVENTS2_ONREADYSTATECHANGE, но безуспешно.

Пожалуйста, какое-нибудь решение?

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;
}

4

Решение

Благодаря Реми я попытался снова загрузить с IPersistStreamInit, и теперь, похоже, он работает.
Вот это новый displayHTMLStr ():

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%s\n\n"), 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;
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]