我知道互联网上有很多关于此的文章,我尝试了很多。虽然我可以让我的浏览器在互联网上加载网页,但我无法设法让它从内存中加载HTML。
大多数时候,以下两种方法都没有任何明显的效果;其他时候,他们会抛出错误。虽然其他人说" for(auto& Array: PArrays)
和pPSI
都没有指向有效的对象"但我不知道这是否属实。我用注释标记了导致错误的行。
如果您想重现问题,我的问题的最后是完整的代码。
pHtmlDoc2
错误:
Test.exe中的0x51539FB1(mshtml.dll)抛出异常:0xC0000005: 访问冲突读取位置0x00000030
此代码在CodeProject上从this article修改。在该源代码中,它运行良好,但在我尝试适应我的代码时它不起作用:
void WebBrowser::setHTML(const wchar_t *htmlSource) {
HRESULT hr;
IDispatch *pDispatch = 0;
IHTMLDocument2 *pHtmlDoc2 = 0;
IPersistStreamInit *pPSI = 0;
IStream *pStream = 0;
HGLOBAL hHTMLContent;
Navigate(L"about:blank");
hr = webBrowser2->get_Document(&pDispatch);
if (SUCCEEDED(hr) && pDispatch) hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc2);
//BSTR p = 0;
//if (SUCCEEDED(hr)) hr = pHtmlDoc2->get_readyState(&p);
if (SUCCEEDED(hr) && pHtmlDoc2) hr = pHtmlDoc2->QueryInterface(IID_IPersistStreamInit, (void **)&pPSI);
// allocate global memory to copy the HTML content to
hHTMLContent = ::GlobalAlloc(GMEM_MOVEABLE, (::wcslen(htmlSource) + 1) * sizeof(TCHAR));
if (hHTMLContent)
{
wchar_t * p_content(static_cast<wchar_t *>(GlobalLock(hHTMLContent)));
::wcscpy(p_content, htmlSource); // Debbug: p_content contains HTML string
GlobalUnlock(hHTMLContent);
// create a stream object based on the HTML content
if (SUCCEEDED(hr) && pPSI) hr = ::CreateStreamOnHGlobal(hHTMLContent, TRUE, &pStream);
{
hr = pPSI->InitNew(); //////////// <- Sometime throw error.
if (SUCCEEDED(hr)) hr = pPSI->Load(pStream);
}
}
if (pStream) pStream->Release();
if (pPSI) pPSI->Release();
if (pHtmlDoc2) pHtmlDoc2->Release();
if (pDispatch) pDispatch->Release();
}
错误:
Test.exe中的0x51577F2E(mshtml.dll)抛出异常:0xC0000005: 访问冲突读取位置0x000002C4
可能的第三种方法,来自Microsoft的Loading HTML content from a Stream,建议我从void WebBrowser::setHTML2(const wchar_t *htmlSource) {
HRESULT hr;
IDispatch *pDispatch = 0;
IHTMLDocument2 *pHtmlDoc2 = 0;
this->Navigate(L"about:blank");
hr = this->webBrowser2->get_Document(&pDispatch);
if (SUCCEEDED(hr) && pDispatch) hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc2);
if (SUCCEEDED(hr) && pHtmlDoc2)
{
BSTR bstr = SysAllocString(htmlSource);
SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1);
if (psaStrings)
{
VARIANT *param;
hr = SafeArrayAccessData(psaStrings, (LPVOID*)¶m);
if (SUCCEEDED(hr) && param)
{
param->vt = VT_BSTR;
param->bstrVal = bstr;
//if (SUCCEEDED(hr)) hr = SafeArrayUnaccessData(psaStrings);
if (SUCCEEDED(hr))
{
hr = pHtmlDoc2->write(psaStrings); //////////// <- Sometime throw error.
}
}
SafeArrayDestroy(psaStrings);
}
}
if (pHtmlDoc2) pHtmlDoc2->Release();
if (pDispatch) pDispatch->Release();
}
事件中加载流,我已经尝试过但未能弄清楚如何实现。
以下是完整代码。我创建一个新的Win32项目并创建/修改以下文件:
DWebBrowserEvents2::DocumentComplete
#include <comdef.h>
#include <Exdisp.h>
#include <ExDispid.h>
#include <MsHTML.h>
#include <Mshtmhst.h>
#include <string>
#include <tchar.h>
#include <Windows.h>
using namespace std;
class WebBrowser :
public IOleClientSite,
public IOleInPlaceSite,
public IStorage
{
public:
WebBrowser(HWND hWndParent);
bool CreateBrowser();
void SetText(const wchar_t* t);
void setHTML(const wchar_t *htmlSource);
void setHTML2(const wchar_t *htmlSource);
RECT PixelToHiMetric(const RECT& _rc);
virtual void SetRect(const RECT& _rc);
// ----- Control methods -----
void GoBack();
void GoForward();
void Refresh();
void Navigate(wstring szUrl);
// ----- IUnknown -----
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
void**ppvObject) override;
virtual ULONG STDMETHODCALLTYPE AddRef(void);
virtual ULONG STDMETHODCALLTYPE Release(void);
// ---------- IOleWindow ----------
virtual HRESULT STDMETHODCALLTYPE GetWindow(
__RPC__deref_out_opt HWND *phwnd) override;
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(
BOOL fEnterMode) override;
// ---------- IOleInPlaceSite ----------
virtual HRESULT STDMETHODCALLTYPE CanInPlaceActivate(void) override;
virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivate(void) override;
virtual HRESULT STDMETHODCALLTYPE OnUIActivate(void) override;
virtual HRESULT STDMETHODCALLTYPE 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) override;
virtual HRESULT STDMETHODCALLTYPE Scroll(
SIZE scrollExtant) override;
virtual HRESULT STDMETHODCALLTYPE OnUIDeactivate(
BOOL fUndoable) override;
virtual HWND GetControlWindow();
virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate(void) override;
virtual HRESULT STDMETHODCALLTYPE DiscardUndoState(void) override;
virtual HRESULT STDMETHODCALLTYPE DeactivateAndUndo(void) override;
virtual HRESULT STDMETHODCALLTYPE OnPosRectChange(
__RPC__in LPCRECT lprcPosRect) override;
// ---------- IOleClientSite ----------
virtual HRESULT STDMETHODCALLTYPE SaveObject(void) override;
virtual HRESULT STDMETHODCALLTYPE GetMoniker(
DWORD dwAssign,
DWORD dwWhichMoniker,
__RPC__deref_out_opt IMoniker **ppmk) override;
virtual HRESULT STDMETHODCALLTYPE GetContainer(
__RPC__deref_out_opt IOleContainer **ppContainer) override;
virtual HRESULT STDMETHODCALLTYPE ShowObject(void) override;
virtual HRESULT STDMETHODCALLTYPE OnShowWindow(
BOOL fShow) override;
virtual HRESULT STDMETHODCALLTYPE RequestNewObjectLayout(void) override;
// ----- IStorage -----
virtual HRESULT STDMETHODCALLTYPE CreateStream(
__RPC__in_string const OLECHAR *pwcsName,
DWORD grfMode,
DWORD reserved1,
DWORD reserved2,
__RPC__deref_out_opt IStream **ppstm) override;
virtual HRESULT STDMETHODCALLTYPE OpenStream(
const OLECHAR *pwcsName,
void *reserved1,
DWORD grfMode,
DWORD reserved2,
IStream **ppstm) override;
virtual HRESULT STDMETHODCALLTYPE CreateStorage(
__RPC__in_string const OLECHAR *pwcsName,
DWORD grfMode,
DWORD reserved1,
DWORD reserved2,
__RPC__deref_out_opt IStorage **ppstg) override;
virtual HRESULT STDMETHODCALLTYPE OpenStorage(
__RPC__in_opt_string const OLECHAR *pwcsName,
__RPC__in_opt IStorage *pstgPriority,
DWORD grfMode,
__RPC__deref_opt_in_opt SNB snbExclude,
DWORD reserved,
__RPC__deref_out_opt IStorage **ppstg) override;
virtual HRESULT STDMETHODCALLTYPE CopyTo(
DWORD ciidExclude,
const IID *rgiidExclude,
__RPC__in_opt SNB snbExclude,
IStorage *pstgDest) override;
virtual HRESULT STDMETHODCALLTYPE MoveElementTo(
__RPC__in_string const OLECHAR *pwcsName,
__RPC__in_opt IStorage *pstgDest,
__RPC__in_string const OLECHAR *pwcsNewName,
DWORD grfFlags) override;
virtual HRESULT STDMETHODCALLTYPE Commit(
DWORD grfCommitFlags) override;
virtual HRESULT STDMETHODCALLTYPE Revert(void) override;
virtual HRESULT STDMETHODCALLTYPE EnumElements(
DWORD reserved1,
void *reserved2,
DWORD reserved3,
IEnumSTATSTG **ppenum) override;
virtual HRESULT STDMETHODCALLTYPE DestroyElement(
__RPC__in_string const OLECHAR *pwcsName) override;
virtual HRESULT STDMETHODCALLTYPE RenameElement(
__RPC__in_string const OLECHAR *pwcsOldName,
__RPC__in_string const OLECHAR *pwcsNewName) override;
virtual HRESULT STDMETHODCALLTYPE SetElementTimes(
__RPC__in_opt_string const OLECHAR *pwcsName,
__RPC__in_opt const FILETIME *pctime,
__RPC__in_opt const FILETIME *patime,
__RPC__in_opt const FILETIME *pmtime) override;
virtual HRESULT STDMETHODCALLTYPE SetClass(
__RPC__in REFCLSID clsid) override;
virtual HRESULT STDMETHODCALLTYPE SetStateBits(
DWORD grfStateBits,
DWORD grfMask) override;
virtual HRESULT STDMETHODCALLTYPE Stat(
__RPC__out STATSTG *pstatstg,
DWORD grfStatFlag) override;
protected:
IOleObject* oleObject;
IOleInPlaceObject* oleInPlaceObject;
IWebBrowser2* webBrowser2;
LONG iComRefCount;
RECT rObject;
HWND hWndParent;
HWND hWndControl;
};
#include "stdafx.h"
#include "Browser.h"
namespace tkString
{
wchar_t* Format(const wchar_t* format, ...)
{
va_list args;
va_start(args, format);
wchar_t *w = NULL;
int len = _vsnwprintf(NULL, 0, format, args) + 1;
if (len > 0)
{
w = new wchar_t[len];
w[0] = 0;
_vsnwprintf_s(w, len, len, format, args);
}
va_end(args);
return w;
}
}
void WebBrowser::SetText(const wchar_t* t)
{
const wchar_t* html = L"<html><head><meta http-equiv='x-ua-compatible' content='IE=edge'></head><body><code>%ls</code></body></html>";
if (t)
{
wchar_t *w = tkString::Format(html, t);
setHTML(w);
//setHTML2(w);
delete[] w;
}
else this->Navigate(L"https://google.com.vn");
}
void WebBrowser::setHTML(const wchar_t *htmlSource) {
HRESULT hr;
IDispatch *pDispatch = 0;
IHTMLDocument2 *pHtmlDoc2 = 0;
IPersistStreamInit *pPSI = 0;
IStream *pStream = 0;
HGLOBAL hHTMLContent;
Navigate(L"about:blank");
hr = webBrowser2->get_Document(&pDispatch);
if (SUCCEEDED(hr) && pDispatch) hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc2);
//BSTR p = 0;
//if (SUCCEEDED(hr)) hr = pHtmlDoc2->get_readyState(&p);
if (SUCCEEDED(hr) && pHtmlDoc2) hr = pHtmlDoc2->QueryInterface(IID_IPersistStreamInit, (void **)&pPSI);
// allocate global memory to copy the HTML content to
hHTMLContent = ::GlobalAlloc(GMEM_MOVEABLE, (::wcslen(htmlSource) + 1) * sizeof(TCHAR));
if (hHTMLContent)
{
wchar_t * p_content(static_cast<wchar_t *>(GlobalLock(hHTMLContent)));
::wcscpy(p_content, htmlSource);
GlobalUnlock(hHTMLContent);
// create a stream object based on the HTML content
if (SUCCEEDED(hr) && pPSI) hr = ::CreateStreamOnHGlobal(hHTMLContent, TRUE, &pStream);
if (SUCCEEDED(hr) && pStream) hr = pPSI->InitNew();
if (SUCCEEDED(hr)) hr = pPSI->Load(pStream);
}
if (pStream) pStream->Release();
if (pPSI) pPSI->Release();
if (pHtmlDoc2) pHtmlDoc2->Release();
if (pDispatch) pDispatch->Release();
}
void WebBrowser::setHTML2(const wchar_t *htmlSource) {
HRESULT hr;
IDispatch *pDispatch = 0;
IHTMLDocument2 *pHtmlDoc2 = 0;
this->Navigate(L"about:blank");
hr = this->webBrowser2->get_Document(&pDispatch);
if (SUCCEEDED(hr) && pDispatch) hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc2);
if (SUCCEEDED(hr) && pHtmlDoc2)
{
BSTR bstr = SysAllocString(htmlSource);
SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1);
if (psaStrings)
{
VARIANT *param;
hr = SafeArrayAccessData(psaStrings, (LPVOID*)¶m);
if (SUCCEEDED(hr) && param)
{
param->vt = VT_BSTR;
param->bstrVal = bstr;
//if (SUCCEEDED(hr)) hr = SafeArrayUnaccessData(psaStrings);
if (SUCCEEDED(hr)) hr = pHtmlDoc2->write(psaStrings);
}
SafeArrayDestroy(psaStrings);
}
}
if (pHtmlDoc2) pHtmlDoc2->Release();
if (pDispatch) pDispatch->Release();
}
WebBrowser::WebBrowser(HWND _hWndParent)
{
iComRefCount = 0;
::SetRect(&rObject, 0, 0, 600, 400);
hWndParent = _hWndParent;
if (CreateBrowser() == FALSE)
{
return;
}
webBrowser2->put_Visible(TRUE);
ShowWindow(GetControlWindow(), SW_SHOW);
this->Navigate(_T("about:blank"));
}
bool WebBrowser::CreateBrowser()
{
HRESULT hr;
hr = ::OleCreate(CLSID_WebBrowser,
IID_IOleObject, OLERENDER_DRAW, 0, this, this,
(void**)&oleObject);
if (FAILED(hr))
{
MessageBox(NULL, _T("Cannot create oleObject CLSID_WebBrowser"),
_T("Error"),
MB_ICONERROR);
return FALSE;
}
hr = oleObject->SetClientSite(this);
hr = OleSetContainedObject(oleObject, TRUE);
RECT posRect;
::SetRect(&rObject, 0, 0, 600, 400);
hr = oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE,
NULL, this, -1, hWndParent, &posRect);
if (FAILED(hr))
{
MessageBox(NULL, _T("oleObject->DoVerb() failed"),
_T("Error"),
MB_ICONERROR);
return FALSE;
}
hr = oleObject->QueryInterface(&webBrowser2);
if (FAILED(hr))
{
MessageBox(NULL, _T("oleObject->QueryInterface(&webBrowser2) failed"),
_T("Error"),
MB_ICONERROR);
return FALSE;
}
return TRUE;
}
RECT WebBrowser::PixelToHiMetric(const RECT& _rc)
{
static bool s_initialized = false;
static int s_pixelsPerInchX, s_pixelsPerInchY;
if (!s_initialized)
{
HDC hdc = ::GetDC(0);
s_pixelsPerInchX = ::GetDeviceCaps(hdc, LOGPIXELSX);
s_pixelsPerInchY = ::GetDeviceCaps(hdc, LOGPIXELSY);
::ReleaseDC(0, hdc);
s_initialized = true;
}
RECT rc;
rc.left = MulDiv(2540, _rc.left, s_pixelsPerInchX);
rc.top = MulDiv(2540, _rc.top, s_pixelsPerInchY);
rc.right = MulDiv(2540, _rc.right, s_pixelsPerInchX);
rc.bottom = MulDiv(2540, _rc.bottom, s_pixelsPerInchY);
return rc;
}
void WebBrowser::SetRect(const RECT& _rc)
{
rObject = _rc;
{
RECT hiMetricRect = PixelToHiMetric(rObject);
SIZEL sz;
sz.cx = hiMetricRect.right - hiMetricRect.left;
sz.cy = hiMetricRect.bottom - hiMetricRect.top;
oleObject->SetExtent(DVASPECT_CONTENT, &sz);
}
if (oleInPlaceObject != 0)
{
oleInPlaceObject->SetObjectRects(&rObject, &rObject);
}
}
// ----- Control methods -----
void WebBrowser::GoBack()
{
this->webBrowser2->GoBack();
}
void WebBrowser::GoForward()
{
this->webBrowser2->GoForward();
}
void WebBrowser::Refresh()
{
this->webBrowser2->Refresh();
}
void WebBrowser::Navigate(wstring szUrl)
{
bstr_t url(szUrl.c_str());
variant_t flags(0x02u); //navNoHistory
this->webBrowser2->Navigate(url, &flags, 0, 0, 0);
}
// ----- IUnknown -----
HRESULT STDMETHODCALLTYPE WebBrowser::QueryInterface(REFIID riid,
void**ppvObject)
{
if (riid == __uuidof(IUnknown))
{
(*ppvObject) = static_cast<IOleClientSite*>(this);
}
else if (riid == __uuidof(IOleInPlaceSite))
{
(*ppvObject) = static_cast<IOleInPlaceSite*>(this);
}
else
{
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG STDMETHODCALLTYPE WebBrowser::AddRef(void)
{
iComRefCount++;
return iComRefCount;
}
ULONG STDMETHODCALLTYPE WebBrowser::Release(void)
{
iComRefCount--;
return iComRefCount;
}
// ---------- IOleWindow ----------
HRESULT STDMETHODCALLTYPE WebBrowser::GetWindow(
__RPC__deref_out_opt HWND *phwnd)
{
(*phwnd) = hWndParent;
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::ContextSensitiveHelp(
BOOL fEnterMode)
{
return E_NOTIMPL;
}
// ---------- IOleInPlaceSite ----------
HRESULT STDMETHODCALLTYPE WebBrowser::CanInPlaceActivate(void)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceActivate(void)
{
OleLockRunning(oleObject, TRUE, FALSE);
oleObject->QueryInterface(&oleInPlaceObject);
oleInPlaceObject->SetObjectRects(&rObject, &rObject);
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::OnUIActivate(void)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::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 = hWndParent;
(*ppFrame) = NULL;
(*ppDoc) = NULL;
(*lprcPosRect).left = rObject.left;
(*lprcPosRect).top = rObject.top;
(*lprcPosRect).right = rObject.right;
(*lprcPosRect).bottom = rObject.bottom;
*lprcClipRect = *lprcPosRect;
lpFrameInfo->fMDIApp = false;
lpFrameInfo->hwndFrame = hwnd;
lpFrameInfo->haccel = NULL;
lpFrameInfo->cAccelEntries = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::Scroll(
SIZE scrollExtant)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::OnUIDeactivate(
BOOL fUndoable)
{
return S_OK;
}
HWND WebBrowser::GetControlWindow()
{
if (hWndControl != 0)
return hWndControl;
if (oleInPlaceObject == 0)
return 0;
oleInPlaceObject->GetWindow(&hWndControl);
return hWndControl;
}
HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceDeactivate(void)
{
hWndControl = 0;
oleInPlaceObject = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::DiscardUndoState(void)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::DeactivateAndUndo(void)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::OnPosRectChange(
__RPC__in LPCRECT lprcPosRect)
{
return E_NOTIMPL;
}
// ---------- IOleClientSite ----------
HRESULT STDMETHODCALLTYPE WebBrowser::SaveObject(void)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::GetMoniker(
DWORD dwAssign,
DWORD dwWhichMoniker,
__RPC__deref_out_opt IMoniker **ppmk)
{
if ((dwAssign == OLEGETMONIKER_ONLYIFTHERE) &&
(dwWhichMoniker == OLEWHICHMK_CONTAINER))
return E_FAIL;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::GetContainer(
__RPC__deref_out_opt IOleContainer **ppContainer)
{
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE WebBrowser::ShowObject(void)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::OnShowWindow(
BOOL fShow)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::RequestNewObjectLayout(void)
{
return E_NOTIMPL;
}
// ----- IStorage -----
HRESULT STDMETHODCALLTYPE WebBrowser::CreateStream(
__RPC__in_string const OLECHAR *pwcsName,
DWORD grfMode,
DWORD reserved1,
DWORD reserved2,
__RPC__deref_out_opt IStream **ppstm)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::OpenStream(
const OLECHAR *pwcsName,
void *reserved1,
DWORD grfMode,
DWORD reserved2,
IStream **ppstm)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::CreateStorage(
__RPC__in_string const OLECHAR *pwcsName,
DWORD grfMode,
DWORD reserved1,
DWORD reserved2,
__RPC__deref_out_opt IStorage **ppstg)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::OpenStorage(
__RPC__in_opt_string const OLECHAR *pwcsName,
__RPC__in_opt IStorage *pstgPriority,
DWORD grfMode,
__RPC__deref_opt_in_opt SNB snbExclude,
DWORD reserved,
__RPC__deref_out_opt IStorage **ppstg)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::CopyTo(
DWORD ciidExclude,
const IID *rgiidExclude,
__RPC__in_opt SNB snbExclude,
IStorage *pstgDest)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::MoveElementTo(
__RPC__in_string const OLECHAR *pwcsName,
__RPC__in_opt IStorage *pstgDest,
__RPC__in_string const OLECHAR *pwcsNewName,
DWORD grfFlags)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::Commit(
DWORD grfCommitFlags)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::Revert(void)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::EnumElements(
DWORD reserved1,
void *reserved2,
DWORD reserved3,
IEnumSTATSTG **ppenum)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::DestroyElement(
__RPC__in_string const OLECHAR *pwcsName)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::RenameElement(
__RPC__in_string const OLECHAR *pwcsOldName,
__RPC__in_string const OLECHAR *pwcsNewName)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::SetElementTimes(
__RPC__in_opt_string const OLECHAR *pwcsName,
__RPC__in_opt const FILETIME *pctime,
__RPC__in_opt const FILETIME *patime,
__RPC__in_opt const FILETIME *pmtime)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::SetClass(
__RPC__in REFCLSID clsid)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::SetStateBits(
DWORD grfStateBits,
DWORD grfMask)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE WebBrowser::Stat(
__RPC__out STATSTG *pstatstg,
DWORD grfStatFlag)
{
return E_NOTIMPL;
}
Visual Studio创建的其他源文件保持不变。
什么问题导致我的程序无法加载HTML字符串,我该如何解决?或者您是否有任何工作示例(没有MFC或ATL)将HTML字符串加载到WebBrowser?
注意:我知道我可以将HTML字符串写入硬盘并将文件路径传递给浏览器,但我根本不想要涉及硬盘。
注2:为了赢得赏金,请尽可能多地使用我的代码,提供工作代码的完整示例。浏览器应该成功加载HTML字符串。即使它正在加载在线网页,它也应该停止处理这个新命令。
答案 0 :(得分:2)
Navigate(L"about:blank");
发布的源代码不能很好地证明问题。它没有显示任何错误,也没有显示错误&#34; Hello&#34;。只有通过省略 Navigate()调用才能接近nullptr错误。代码根本没有完成,它缺少捕获DocumentComplete
事件所需的管道。只有在此事件被触发后,WebBrowser :: setHtml()中的代码才能正常工作。
让WebBrowser类实现IDispatch和IUnknown接口:
class WebBrowser :
public IDispatch,
public IUnknown,
public IOleClientSite,
public IOleInPlaceSite,
public IStorage
{
private:
HRESULT OnCompleted(DISPPARAMS* args);
wchar_t* htmlSource;
IConnectionPoint* callback;
DWORD eventCookie;
// etc...
};
注意htmlSource变量现在是一个类成员,需要存储该字符串,直到DocumentComplete事件触发为止。
我们需要实施IDispatch。这很容易做到,我把代码内联:
// ---------- IDispatch ----------
HRESULT GetTypeInfoCount(UINT *pctinfo) { return E_FAIL; }
HRESULT GetTypeInfo(UINT, LCID, ITypeInfo **) { return E_FAIL; }
HRESULT GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { return E_FAIL; }
HRESULT Invoke(DISPID dispIdMember, REFIID, LCID, WORD,
DISPPARAMS *pDispParams, VARIANT *pVarResult,
EXCEPINFO*, UINT*) {
if (dispIdMember == DISPID_DOCUMENTCOMPLETE) return OnCompleted(pDispParams);
else return S_OK;
}
需要调整QueryInterface():
HRESULT STDMETHODCALLTYPE WebBrowser::QueryInterface(REFIID riid, void**ppvObject)
{
if (riid == __uuidof(IUnknown)) *ppvObject = static_cast<IUnknown*>(this);
else if (riid == __uuidof(IDispatch)) *ppvObject = static_cast<IDispatch*>(this);
else if (riid == __uuidof(IOleClientSite)) *ppvObject = static_cast<IOleClientSite*>(this);
else if (riid == __uuidof(IOleInPlaceSite)) *ppvObject = static_cast<IOleInPlaceSite*>(this);
else
return E_NOINTERFACE;
AddRef();
return S_OK;
}
构造函数需要订阅事件接口:
WebBrowser::WebBrowser(HWND _hWndParent)
{
//...
// appended:
htmlSource = nullptr;
IConnectionPointContainer* container = nullptr;
webBrowser2->QueryInterface(IID_IConnectionPointContainer, (void**)&container);
container->FindConnectionPoint(__uuidof(DWebBrowserEvents2), &callback);
IUnknown* punk = nullptr;
this->QueryInterface(IID_IUnknown, (void**)&punk);
callback->Advise(punk, &eventCookie);
punk->Release();
container->Release();
}
setText()函数变得非常简单,我们根本不会担心setHtml()。我们只是设置htmlSource成员,以便我们知道在DocumentComplete事件触发时该怎么做:
void WebBrowser::SetText(const wchar_t* t)
{
const wchar_t* html = L"<html><head><meta http-equiv='x-ua-compatible' content='IE=edge'></head><body><code>%ls</code></body></html>";
if (htmlSource) delete[] htmlSource;
htmlSource = tkString::Format(html, t);
this->Navigate(L"about::blank");
}
最后是DocumentComplete事件触发时运行的添加函数。大多数代码都是从setHtml移动的:
HRESULT WebBrowser::OnCompleted(DISPPARAMS* args) {
HRESULT hr;
IDispatch *pDispatch = 0;
IHTMLDocument2 *pHtmlDoc2 = 0;
IPersistStreamInit *pPSI = 0;
IStream *pStream = 0;
HGLOBAL hHTMLContent;
if (!htmlSource) return S_OK;
hr = webBrowser2->get_Document(&pDispatch);
if (SUCCEEDED(hr) && pDispatch) hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc2);
if (SUCCEEDED(hr) && pHtmlDoc2) hr = pHtmlDoc2->QueryInterface(IID_IPersistStreamInit, (void **)&pPSI);
// allocate global memory to copy the HTML content to
hHTMLContent = ::GlobalAlloc(GMEM_MOVEABLE, (::wcslen(htmlSource) + 1) * sizeof(TCHAR));
if (hHTMLContent)
{
wchar_t * p_content(static_cast<wchar_t *>(GlobalLock(hHTMLContent)));
::wcscpy(p_content, htmlSource);
GlobalUnlock(hHTMLContent);
// create a stream object based on the HTML content
if (SUCCEEDED(hr) && pPSI) hr = ::CreateStreamOnHGlobal(hHTMLContent, TRUE, &pStream);
if (SUCCEEDED(hr) && pStream) hr = pPSI->InitNew();
if (SUCCEEDED(hr)) hr = pPSI->Load(pStream);
}
if (pStream) pStream->Release();
if (pPSI) pPSI->Release();
if (pHtmlDoc2) pHtmlDoc2->Release();
if (pDispatch) pDispatch->Release();
delete[] htmlSource;
htmlSource = nullptr;
return S_OK;
}
我会留下适当的清理作为// todo。现在运行此代码可以产生预期的结果:
答案 1 :(得分:0)
基于Hans Passant's answer,bellow是完整的工作代码,适合任何想要测试的人 创建名为“Win32Project1”的新Win32项目,并添加/编辑以下文件:
#pragma once
#include <comdef.h>
#include <Exdisp.h>
#include <ExDispid.h>
#include <MsHTML.h>
#include <Mshtmhst.h>
#include <string>
#include <tchar.h>
#include <Windows.h>
class WebBrowser :
public IDispatch,
public IOleClientSite,
public IOleInPlaceSite,
public IStorage
{
public:
WebBrowser(HWND hWndParent);
void SetText(const wchar_t* t);
void setHTML(const wchar_t *htmlText, bool shouldWrapinBODYtag = true);
// ----- Create Browser -----
HRESULT RegisterGIWebBrowser();
HRESULT GetGIWebBrowser(IWebBrowser2** pwb);
bool CreateBrowser();
// ----- For Resize Window -----
RECT PixelToHiMetric(const RECT& _rc);
virtual void SetRect(const RECT& _rc);
virtual HWND GetControlWindow();
// ----- Control methods -----
void GoBack();
void GoForward();
void Refresh();
void Navigate(const wchar_t *szUrl);
// ----- IUnknown -----
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void**ppvObject) override;
virtual ULONG STDMETHODCALLTYPE AddRef(void);
virtual ULONG STDMETHODCALLTYPE Release(void);
// ---------- IOleWindow ----------
virtual HRESULT STDMETHODCALLTYPE GetWindow(__RPC__deref_out_opt HWND *phwnd) override;
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
// ---------- IOleInPlaceSite ----------
virtual HRESULT STDMETHODCALLTYPE WebBrowser::CanInPlaceActivate(void) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::OnUIActivate(void) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceActivate(void) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::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) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::Scroll(SIZE scrollExtant) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::OnUIDeactivate(BOOL fUndoable) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::DiscardUndoState(void) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::DeactivateAndUndo(void) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::OnPosRectChange(__RPC__in LPCRECT lprcPosRect) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceDeactivate(void) override;
// ---------- IOleClientSite ----------
virtual HRESULT STDMETHODCALLTYPE WebBrowser::SaveObject(void) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::GetContainer(__RPC__deref_out_opt IOleContainer **ppContainer) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::ShowObject(void) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::OnShowWindow(BOOL fShow) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::RequestNewObjectLayout(void) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, __RPC__deref_out_opt IMoniker **ppmk) override;
// ----- IStorage -----
virtual HRESULT STDMETHODCALLTYPE WebBrowser::CreateStream(__RPC__in_string const OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, __RPC__deref_out_opt IStream **ppstm) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::OpenStream(const OLECHAR *pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::CreateStorage(__RPC__in_string const OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, __RPC__deref_out_opt IStorage **ppstg) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::OpenStorage(__RPC__in_opt_string const OLECHAR *pwcsName, __RPC__in_opt IStorage *pstgPriority, DWORD grfMode, __RPC__deref_opt_in_opt SNB snbExclude, DWORD reserved, __RPC__deref_out_opt IStorage **ppstg) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::CopyTo(DWORD ciidExclude, const IID *rgiidExclude, __RPC__in_opt SNB snbExclude, IStorage *pstgDest) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::MoveElementTo(__RPC__in_string const OLECHAR *pwcsName, __RPC__in_opt IStorage *pstgDest, __RPC__in_string const OLECHAR *pwcsNewName, DWORD grfFlags) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::Commit(DWORD grfCommitFlags) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::Revert(void) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::EnumElements(DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenum) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::DestroyElement(__RPC__in_string const OLECHAR *pwcsName) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::RenameElement(__RPC__in_string const OLECHAR *pwcsOldName, __RPC__in_string const OLECHAR *pwcsNewName) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::SetElementTimes(__RPC__in_opt_string const OLECHAR *pwcsName, __RPC__in_opt const FILETIME *pctime, __RPC__in_opt const FILETIME *patime, __RPC__in_opt const FILETIME *pmtime) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::SetClass(__RPC__in REFCLSID clsid) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::SetStateBits(DWORD grfStateBits, DWORD grfMask) override;
virtual HRESULT STDMETHODCALLTYPE WebBrowser::Stat(__RPC__out STATSTG *pstatstg, DWORD grfStatFlag) override;
// ---------- IDispatch ----------
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(__RPC__out UINT *pctinfo) override;
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT, LCID, __RPC__deref_out_opt ITypeInfo **) override;
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(__RPC__in REFIID riid, __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames, __RPC__in_range(0, 16384) UINT cNames, LCID lcid, __RPC__out_ecount_full(cNames) DISPID *rgDispId) override;
virtual HRESULT STDMETHODCALLTYPE Invoke(_In_ DISPID dispIdMember, _In_ REFIID, _In_ LCID, _In_ WORD, _In_ DISPPARAMS *pDispParams, _Out_opt_ VARIANT *pVarResult, _Out_opt_ EXCEPINFO*, _Out_opt_ UINT*) override;
private:
IOleObject* oleObject;
IOleInPlaceObject* oleInPlaceObject;
IWebBrowser2* webBrowser2;
LONG iComRefCount;
RECT rObject;
HWND hWndParent;
HWND hWndControl;
HRESULT OnCompleted(DISPPARAMS* args);
wchar_t* htmlSource;
IConnectionPoint* callback;
DWORD eventCookie;
DWORD dwGIWebBrowserCookie;
bool isFullyCreated;
};
#include "stdafx.h"
#include "WebBrowser.h"
namespace tkString
{
wchar_t* Format(const wchar_t* format, ...)
{
va_list args;
va_start(args, format);
wchar_t* w = NULL;
int len = _vscwprintf(format, args) + 1;
if (len > 1)
{
w = new wchar_t[len];
w[0] = 0;
_vsnwprintf_s(w, len, len, format, args);
}
va_end(args);
return w;
}
}
void WebBrowser::SetText(const wchar_t* t)
{
if (isFullyCreated)
{
// TODO: escape text
const wchar_t* html = L"<html><head><meta http-equiv='x-ua-compatible' content='IE=edge'></head><body><code>%ls</code></body></html>";
if (htmlSource) delete[] htmlSource;
htmlSource = tkString::Format(html, t);
this->Navigate(L"about:blank");
}
else {}
}
void WebBrowser::setHTML(const wchar_t* htmlText, bool shouldWrapinBODYtag)
{
if (isFullyCreated)
{
if (htmlSource) delete[] htmlSource;
htmlSource = NULL;
if (shouldWrapinBODYtag)
{
const wchar_t* html = L"<html><head><meta http-equiv='x-ua-compatible' content='IE=edge'></head><body>%ls</body></html>";
htmlSource = tkString::Format(html, htmlText);
}
else
{
if (htmlText)
{
size_t len = wcslen(htmlText) + 1;
htmlSource = new wchar_t[len];
wmemcpy(htmlSource, htmlText, len);
}
}
this->Navigate(L"about:blank");
}
else {}
}
HRESULT WebBrowser::OnCompleted(DISPPARAMS* args)
{
HRESULT hr;
IDispatch *pDispatch = 0;
IHTMLDocument2 *pHtmlDoc2 = 0;
IPersistStreamInit *pPSI = 0;
IStream *pStream = 0;
HGLOBAL hHTMLContent;
if (!htmlSource) return S_OK;
hr = webBrowser2->get_Document(&pDispatch);
if (SUCCEEDED(hr) && pDispatch) hr = pDispatch->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc2);
if (SUCCEEDED(hr) && pHtmlDoc2) hr = pHtmlDoc2->QueryInterface(IID_IPersistStreamInit, (void **)&pPSI);
// allocate global memory to copy the HTML content to
size_t len = wcslen(htmlSource) + 1;
hHTMLContent = ::GlobalAlloc(GMEM_MOVEABLE, len * sizeof(wchar_t));
if (hHTMLContent)
{
wchar_t * p_content(static_cast<wchar_t *>(GlobalLock(hHTMLContent)));
wmemcpy_s(p_content, len, htmlSource, len);
GlobalUnlock(hHTMLContent);
// create a stream object based on the HTML content
if (SUCCEEDED(hr) && pPSI) hr = ::CreateStreamOnHGlobal(hHTMLContent, TRUE, &pStream);
if (SUCCEEDED(hr) && pStream) hr = pPSI->InitNew();
if (SUCCEEDED(hr)) hr = pPSI->Load(pStream);
}
if (pStream) pStream->Release();
if (pPSI) pPSI->Release();
if (pHtmlDoc2) pHtmlDoc2->Release();
if (pDispatch) pDispatch->Release();
delete[] htmlSource;
htmlSource = nullptr;
return S_OK;
}
// ----- Control methods -----
void WebBrowser::Navigate(const wchar_t *szUrl)
{
HRESULT hr = E_FAIL;
IWebBrowser2 *pwb = NULL;
hr = GetGIWebBrowser(&pwb);
if (SUCCEEDED(hr) && pwb)
{
bstr_t url(szUrl);
variant_t flags(0x02u); //navNoHistory
pwb->Navigate(url, &flags, 0, 0, 0);
}
else { /* Handle error */ }
}
void WebBrowser::GoBack() { this->webBrowser2->GoBack(); }
void WebBrowser::GoForward() { this->webBrowser2->GoForward(); }
void WebBrowser::Refresh() { this->webBrowser2->Refresh(); }
WebBrowser::WebBrowser(HWND _hWndParent) :
isFullyCreated(false)
{
HRESULT hr = E_FAIL;
htmlSource = nullptr;
IConnectionPointContainer* container = nullptr;
IUnknown* punk = nullptr;
iComRefCount = 0;
::SetRect(&rObject, 0, 0, 300, 300);
hWndParent = _hWndParent;
if (CreateBrowser())
{
this->Navigate(L"about:blank");
hr = RegisterGIWebBrowser();
if (SUCCEEDED(hr))
{
webBrowser2->put_Visible(TRUE);
ShowWindow(GetControlWindow(), SW_SHOW);
hr = webBrowser2->QueryInterface(IID_IConnectionPointContainer, (void**)&container);
if (SUCCEEDED(hr) && container) hr = container->FindConnectionPoint(__uuidof(DWebBrowserEvents2), &callback);
if (SUCCEEDED(hr) && container) hr = this->QueryInterface(IID_IUnknown, (void**)&punk);
if (SUCCEEDED(hr) && container) hr = callback->Advise(punk, &eventCookie);
if (SUCCEEDED(hr) && eventCookie) isFullyCreated = true;
if (punk) punk->Release();
if (container) container->Release();
}
}
}
bool WebBrowser::CreateBrowser()
{
HRESULT hr;
hr = ::OleCreate(CLSID_WebBrowser, IID_IOleObject, OLERENDER_DRAW, 0, this, this, (void**)&oleObject);
if (SUCCEEDED(hr) && oleObject)
{
if (SUCCEEDED(hr)) hr = oleObject->SetClientSite(this);
if (SUCCEEDED(hr)) hr = OleSetContainedObject(oleObject, TRUE);
if (SUCCEEDED(hr))
{
RECT posRect;
::SetRect(&posRect, -300, -300, 300, 300);
hr = oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, -1, hWndParent, &posRect);
}
hr = oleObject->QueryInterface(&webBrowser2);
}
if (FAILED(hr) || !webBrowser2)
{
MessageBox(NULL, L"Create Browser failed!", L"Error", MB_ICONERROR);
return false;
}
return true;
}
RECT WebBrowser::PixelToHiMetric(const RECT& _rc)
{
static bool s_initialized = false;
static int s_pixelsPerInchX, s_pixelsPerInchY;
if (!s_initialized)
{
HDC hdc = ::GetDC(0);
s_pixelsPerInchX = ::GetDeviceCaps(hdc, LOGPIXELSX);
s_pixelsPerInchY = ::GetDeviceCaps(hdc, LOGPIXELSY);
::ReleaseDC(0, hdc);
s_initialized = true;
}
RECT rc;
rc.left = MulDiv(2540, _rc.left, s_pixelsPerInchX);
rc.top = MulDiv(2540, _rc.top, s_pixelsPerInchY);
rc.right = MulDiv(2540, _rc.right, s_pixelsPerInchX);
rc.bottom = MulDiv(2540, _rc.bottom, s_pixelsPerInchY);
return rc;
}
void WebBrowser::SetRect(const RECT& _rc)
{
rObject = _rc;
{
RECT hiMetricRect = PixelToHiMetric(rObject);
SIZEL sz;
sz.cx = hiMetricRect.right - hiMetricRect.left;
sz.cy = hiMetricRect.bottom - hiMetricRect.top;
oleObject->SetExtent(DVASPECT_CONTENT, &sz);
}
if (oleInPlaceObject != 0)
{
oleInPlaceObject->SetObjectRects(&rObject, &rObject);
}
}
HWND WebBrowser::GetControlWindow() { if (!hWndControl && oleInPlaceObject) oleInPlaceObject->GetWindow(&hWndControl); return hWndControl; }
// Register IWebBrowser2 instance for use in threads
HRESULT WebBrowser::RegisterGIWebBrowser()
{
HRESULT hr = E_FAIL;
IUnknown* pIUnknown = NULL;
IGlobalInterfaceTable* pIGlobalInterfaceTable = NULL;
dwGIWebBrowserCookie = 0;
hr = ::CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&pIGlobalInterfaceTable);
if (SUCCEEDED(hr) && pIGlobalInterfaceTable) hr = webBrowser2->QueryInterface(IID_IUnknown, (void**)&pIUnknown);
if (SUCCEEDED(hr) && pIUnknown) hr = pIGlobalInterfaceTable->RegisterInterfaceInGlobal(pIUnknown, __uuidof(IWebBrowser2), &dwGIWebBrowserCookie);
if (pIUnknown) pIUnknown->Release();
if (pIGlobalInterfaceTable) pIGlobalInterfaceTable->Release();
if (SUCCEEDED(hr) && dwGIWebBrowserCookie) return hr;
return E_FAIL;
}
// Get IWebBrowser2 instance from threads
HRESULT WebBrowser::GetGIWebBrowser(IWebBrowser2** pwb)
{
HRESULT hr = E_FAIL;
IGlobalInterfaceTable* pIGlobalInterfaceTable = NULL;
*pwb = NULL;
if (dwGIWebBrowserCookie) hr = ::CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&pIGlobalInterfaceTable);
if (SUCCEEDED(hr) && pIGlobalInterfaceTable) hr = pIGlobalInterfaceTable->GetInterfaceFromGlobal(dwGIWebBrowserCookie, __uuidof(IWebBrowser2), (void **)pwb);
if (pIGlobalInterfaceTable) pIGlobalInterfaceTable->Release();
return hr;
}
// ----- IUnknown -----
ULONG STDMETHODCALLTYPE WebBrowser::AddRef(void) { return ++iComRefCount; }
ULONG STDMETHODCALLTYPE WebBrowser::Release(void) { return --iComRefCount; }
HRESULT STDMETHODCALLTYPE WebBrowser::QueryInterface(REFIID riid, void**ppvObject)
{
if (riid == __uuidof(IUnknown)) *ppvObject = static_cast<IDispatch*>(this);
else if (riid == __uuidof(IDispatch)) *ppvObject = static_cast<IDispatch*>(this);
else if (riid == __uuidof(IOleClientSite)) *ppvObject = static_cast<IOleClientSite*>(this);
else if (riid == __uuidof(IOleInPlaceSite)) *ppvObject = static_cast<IOleInPlaceSite*>(this);
else
return E_NOINTERFACE;
AddRef();
return S_OK;
}
// ---------- IOleInPlaceSite ----------
HRESULT STDMETHODCALLTYPE WebBrowser::CanInPlaceActivate(void){ return S_OK; }
HRESULT STDMETHODCALLTYPE WebBrowser::OnUIActivate(void){ return S_OK; }
HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceActivate(void)
{
OleLockRunning(oleObject, TRUE, FALSE);
oleObject->QueryInterface(&oleInPlaceObject);
oleInPlaceObject->SetObjectRects(&rObject, &rObject);
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::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 = hWndParent;
(*ppFrame) = NULL;
(*ppDoc) = NULL;
(*lprcPosRect).left = rObject.left;
(*lprcPosRect).top = rObject.top;
(*lprcPosRect).right = rObject.right;
(*lprcPosRect).bottom = rObject.bottom;
*lprcClipRect = *lprcPosRect;
lpFrameInfo->fMDIApp = false;
lpFrameInfo->hwndFrame = hwnd;
lpFrameInfo->haccel = NULL;
lpFrameInfo->cAccelEntries = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE WebBrowser::Scroll(SIZE scrollExtant) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::OnUIDeactivate(BOOL fUndoable) { return S_OK; }
HRESULT STDMETHODCALLTYPE WebBrowser::DiscardUndoState(void) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::DeactivateAndUndo(void) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::OnPosRectChange(__RPC__in LPCRECT lprcPosRect) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceDeactivate(void) { hWndControl = 0; oleInPlaceObject = 0; return S_OK; }
// ---------- IDispatch ----------
HRESULT WebBrowser::GetTypeInfoCount(__RPC__out UINT *pctinfo) { return E_FAIL; }
HRESULT WebBrowser::GetTypeInfo(UINT, LCID, __RPC__deref_out_opt ITypeInfo **) { return E_FAIL; }
HRESULT WebBrowser::GetIDsOfNames(__RPC__in REFIID riid, __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames, __RPC__in_range(0, 16384) UINT cNames, LCID lcid, __RPC__out_ecount_full(cNames) DISPID *rgDispId) { return E_FAIL; }
HRESULT STDMETHODCALLTYPE WebBrowser::Invoke(_In_ DISPID dispIdMember, _In_ REFIID, _In_ LCID, _In_ WORD, _In_ DISPPARAMS *pDispParams, _Out_opt_ VARIANT *pVarResult, _Out_opt_ EXCEPINFO*, _Out_opt_ UINT*)
{
if (dispIdMember == DISPID_DOCUMENTCOMPLETE) return OnCompleted(pDispParams);
else return S_OK;
}
// ---------- IOleWindow ----------
HRESULT STDMETHODCALLTYPE WebBrowser::GetWindow(__RPC__deref_out_opt HWND *phwnd) { (*phwnd) = hWndParent; return S_OK; }
HRESULT STDMETHODCALLTYPE WebBrowser::ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; }
// ---------- IOleClientSite ----------
HRESULT STDMETHODCALLTYPE WebBrowser::SaveObject(void) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::GetContainer(__RPC__deref_out_opt IOleContainer **ppContainer) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::ShowObject(void) { return S_OK; }
HRESULT STDMETHODCALLTYPE WebBrowser::OnShowWindow(BOOL fShow) { return S_OK; }
HRESULT STDMETHODCALLTYPE WebBrowser::RequestNewObjectLayout(void) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, __RPC__deref_out_opt IMoniker **ppmk) { if ((dwAssign == OLEGETMONIKER_ONLYIFTHERE) && (dwWhichMoniker == OLEWHICHMK_CONTAINER))return E_FAIL; return E_NOTIMPL; }
// ----- IStorage -----
HRESULT STDMETHODCALLTYPE WebBrowser::CreateStream(__RPC__in_string const OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, __RPC__deref_out_opt IStream **ppstm) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::OpenStream(const OLECHAR *pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::CreateStorage(__RPC__in_string const OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, __RPC__deref_out_opt IStorage **ppstg) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::OpenStorage(__RPC__in_opt_string const OLECHAR *pwcsName, __RPC__in_opt IStorage *pstgPriority, DWORD grfMode, __RPC__deref_opt_in_opt SNB snbExclude, DWORD reserved, __RPC__deref_out_opt IStorage **ppstg) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::CopyTo(DWORD ciidExclude, const IID *rgiidExclude, __RPC__in_opt SNB snbExclude, IStorage *pstgDest) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::MoveElementTo(__RPC__in_string const OLECHAR *pwcsName, __RPC__in_opt IStorage *pstgDest, __RPC__in_string const OLECHAR *pwcsNewName, DWORD grfFlags) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::Commit(DWORD grfCommitFlags) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::Revert(void) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::EnumElements(DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenum) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::DestroyElement(__RPC__in_string const OLECHAR *pwcsName) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::RenameElement(__RPC__in_string const OLECHAR *pwcsOldName, __RPC__in_string const OLECHAR *pwcsNewName) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::SetElementTimes(__RPC__in_opt_string const OLECHAR *pwcsName, __RPC__in_opt const FILETIME *pctime, __RPC__in_opt const FILETIME *patime, __RPC__in_opt const FILETIME *pmtime) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::SetClass(__RPC__in REFCLSID clsid) { return S_OK; }
HRESULT STDMETHODCALLTYPE WebBrowser::SetStateBits(DWORD grfStateBits, DWORD grfMask) { return E_NOTIMPL; }
HRESULT STDMETHODCALLTYPE WebBrowser::Stat(__RPC__out STATSTG *pstatstg, DWORD grfStatFlag) { return E_NOTIMPL; }
#include "stdafx.h"
#include "Win32Project1.h"
#include "WebBrowser.h"
HWND hWnd = NULL;
HWND tkWebBrowserHWND = NULL;
WebBrowser* tkWebBrowser = NULL;
void callFromThread();
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
OleInitialize(NULL);
MyRegisterClass(hInstance);
if (!InitInstance(hInstance, nCmdShow)) return FALSE;
tkWebBrowserHWND = CreateWindow(L"Static", NULL, WS_CHILD | WS_VISIBLE, 221, 0, 300, 300, hWnd, NULL, hInstance, 0);
tkWebBrowser = new WebBrowser(tkWebBrowserHWND);
// Use one of following command
//tkWebBrowser->SetText(L"Hello!");
//tkWebBrowser->setHTML(L"<h1>Title</h1><div>Content</div>");
//tkWebBrowser->setHTML(L"<html><body><h1>Title 2</h1><div>Content 2</div></body></html>", false);
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)callFromThread, 0, 0, 0);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
void callFromThread()
{
OleInitialize(NULL);
// Use one of following command
//tkWebBrowser->SetText(L"Hello from thread!");
//tkWebBrowser->setHTML(L"<h1>Title from thread</h1><div>Content from thread</div>");
tkWebBrowser->setHTML(L"<html><body><h1>Title 2 from thread</h1><div>Content 2 from thread</div></body></html>", false);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
HINSTANCE hInst;
const wchar_t* szTitle = L"Title";
const wchar_t* szWindowClass = L"Window Class";
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_WIN32PROJECT1));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32PROJECT1);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
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;
}