现在的位置: 首页 > 综合 > 正文

对Dialog添加视图CHtmlView,并获取滚动条的滚动范围

2018年07月17日 ⁄ 综合 ⁄ 共 5475字 ⁄ 字号 评论关闭

View头文件WebView.h:

#ifndef __WEBVIEW_H__
#define __WEBVIEW_H__


#pragma once

class CWebView : public CHtmlView
{
public: // 仅从序列化创建
	CWebView();
	virtual ~CWebView();
	DECLARE_DYNCREATE(CWebView)

// 操作
public:
	int	 GetScrollHeight();	// 返回滚动条的高度
	// 对于有多个iframe的网页,所有页面加载完成,调用该方法,只调用一次
	static void OnLoad(VARIANT *pVarResult, LONG_PTR lpUserData);

// 重写
public:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	virtual void OnInitialUpdate(); // 构造后第一次调用

	// 页面加载完成调用,对于有多个iframe的网页,可能会调用多次
	virtual void OnDocumentComplete(LPCTSTR lpszURL);

#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

// 生成的消息映射函数
protected:
	DECLARE_MESSAGE_MAP()
};
#endif // __WEBVIEW_H__

实现WebView.c:

// WebView.cpp : implementation file
//

#include "stdafx.h"
#include "WebView.h"
#include "DOMEventHandler.h"

#include <afxctl.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CWebView

IMPLEMENT_DYNCREATE(CWebView, CHtmlView)

BEGIN_MESSAGE_MAP(CWebView, CHtmlView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CHtmlView::OnFilePrint)
END_MESSAGE_MAP()

// CBENBEN_IEView 构造/析构

CWebView::CWebView()
{
}

CWebView::~CWebView()
{
}

BOOL CWebView::PreCreateWindow(CREATESTRUCT& cs)
{
	return CHtmlView::PreCreateWindow(cs);
}

// 构造后第一次调用
void CWebView::OnInitialUpdate()
{
	CHtmlView::OnInitialUpdate();
}

// 获取滚动条的高度
int CWebView::GetScrollHeight()
{
	CWebView *pView = (CWebView *)this;

	HRESULT hr;
	CComPtr<IDispatch> spDisp;

	// 获取COM组件的IDispatch的接口
	spDisp = pView->GetHtmlDocument();
	if (!spDisp)
		return 0;
	
	// 查询IID为IID_IHTMLDocument2的接口
	IHTMLDocument2 *pHtmlDoc = NULL;
	hr = spDisp->QueryInterface(IID_IHTMLDocument2, (void **)&pHtmlDoc);
	ASSERT(SUCCEEDED(hr));
	if (!pHtmlDoc)
		return 0;

	// 取得IHTMLElement类型的body接口
	IHTMLElement *pHtmlElement = NULL;
	hr = pHtmlDoc->get_body(&pHtmlElement);
	ASSERT(SUCCEEDED(hr));
	if (!pHtmlElement)
		return 0;

	// 查询IID为IID_IHTMLElement2的接口
	IHTMLElement2 *pHtmlElement2 = NULL;
	hr = pHtmlElement->QueryInterface(IID_IHTMLElement2, (void **)&pHtmlElement2);
	ASSERT(SUCCEEDED(hr));
	if (!pHtmlElement2)
		return 0;

	// 取得网页中滚动条的滚动范围
	long lScrollHeight;
	pHtmlElement2->get_scrollHeight(&lScrollHeight);

	return lScrollHeight;
}

// 页面加载完成调用,对于有多个iframe的网页,可能会调用多次
void CWebView::OnDocumentComplete( LPCTSTR lpszURL )
{
	IHTMLDocument *pHtmlDoc = (IHTMLDocument *)GetHtmlDocument();
	CComQIPtr<IHTMLDocument2> pHtmlDoc2(pHtmlDoc);
	if(pHtmlDoc2)
	{
		CComPtr<IHTMLWindow2> pHtmlWnd2;
		pHtmlDoc2->get_parentWindow(&pHtmlWnd2);
		if(pHtmlWnd2)
		{
			VARIANT vEvent = CDOMEventHandler::CreateEventHandlerVariant(&CWebView::OnLoad, (LONG_PTR)this);
			pHtmlWnd2->put_onload(vEvent);
		}
	}

	CHtmlView::OnDocumentComplete(lpszURL);
}

// 对于有多个iframe的网页,所有页面加载完成,调用该方法,只调用一次
void CWebView::OnLoad( VARIANT *pVarResult, LONG_PTR lpUserData )
{
	CWebView *pWebView = reinterpret_cast<CWebView *>(lpUserData);
}

DOMEventHandler.h 为判断网页是否加载完成而添加的类

#ifndef __DOMEVENTHANDLER_H__
#define __DOMEVENTHANDLER_H__

#pragma once


typedef void (*PFN_DOM_EVENT_CALLBACK)(VARIANT* pVarResult, LONG_PTR lpUserData);
class CDOMEventHandler : public IDispatch
{
public:
	CDOMEventHandler(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData);
	~CDOMEventHandler(void);
	HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject);
	DWORD __stdcall AddRef();
	DWORD __stdcall Release();
	STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo){ return E_NOTIMPL; }
	STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID  lcid, ITypeInfo FAR* FAR*  ppTInfo){ return E_NOTIMPL; }
	STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId) { return S_OK; }
	STDMETHOD(Invoke)(DISPID dispIdMember
		, REFIID riid
		, LCID lcid
		, WORD wFlags
		, DISPPARAMS* pDispParams
		, VARIANT* pVarResult
		, EXCEPINFO * pExcepInfo
		, UINT * puArgErr
		);  
	static LPDISPATCH CreateEventHandler(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData);
	static VARIANT CreateEventHandlerVariant(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData);
private:
	PFN_DOM_EVENT_CALLBACK  m_pfCallback;
	long                    m_lRefCount;
	LONG_PTR                m_lpUserData;
};
#endif // __DOMEVENTHANDLER_H__

DOMEventHandler.cpp 为判断网页是否加载完成而添加的类

// DOMEventHandler.cpp : implementation file
//

#include "StdAfx.h"
#include "DOMEventHandler.h"


CDOMEventHandler::CDOMEventHandler(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData)
: m_lRefCount(0)
, m_pfCallback(pfnCallback)
, m_lpUserData(lpUserData)
{
}

CDOMEventHandler::~CDOMEventHandler(void)
{
}

HRESULT __stdcall CDOMEventHandler::QueryInterface(REFIID riid, void** ppvObject)
{
	*ppvObject = NULL;
	if (IsEqualGUID(riid, IID_IUnknown))
		*ppvObject = reinterpret_cast<void**>(this);
	if (IsEqualGUID(riid, IID_IDispatch))
		*ppvObject = reinterpret_cast<void**>(this);
	if (*ppvObject)
	{
		((IUnknown*)*ppvObject)->AddRef();
		return S_OK;
	}
	else
	{
		return E_NOINTERFACE;
	}
}

DWORD __stdcall CDOMEventHandler::AddRef()
{
	return InterlockedIncrement(&m_lRefCount);
}

DWORD __stdcall CDOMEventHandler::Release()
{
	if (InterlockedDecrement(&m_lRefCount) == 0)
	{
		delete this;
		return 0;
	}

	return m_lRefCount;
}

HRESULT CDOMEventHandler::Invoke(DISPID dispIdMember,
								 REFIID riid,
								 LCID lcid,
								 WORD wFlags,
								 DISPPARAMS* pDispParams,
								 VARIANT* pVarResult,
								 EXCEPINFO * pExcepInfo,
								 UINT * puArgErr)
{
	if (dispIdMember == DISPID_VALUE)
	{
		if( m_pfCallback )
			(*m_pfCallback)(pVarResult, m_lpUserData);
	}
	return S_OK;
}

LPDISPATCH CDOMEventHandler::CreateEventHandler(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData)
{
	CDOMEventHandler * pHandler = new CDOMEventHandler( pfnCallback, lpUserData);
	return reinterpret_cast<LPDISPATCH>(pHandler);
}

VARIANT CDOMEventHandler::CreateEventHandlerVariant(PFN_DOM_EVENT_CALLBACK pfnCallback, LONG_PTR lpUserData)
{
	VARIANT variant;
	variant.vt = VT_DISPATCH;
	variant.pdispVal = CDOMEventHandler::CreateEventHandler( pfnCallback, lpUserData);
	return variant;
}

最后在CMyDialog::OnInitDialog()中添加:

	// 创建并加载网页视图
	m_pWebView = new CWebView;
	m_pWebView->Create(NULL, NULL, WS_CHILD | WS_VISIBLE, rcWebView, this, 2009);
	m_pWebView->ShowWindow(SW_HIDE);
	Navigate2("www.baidu.com",NULL,NULL);

抱歉!评论已关闭.