vckbase上看到的,但调试老出错,总结一下
代码在vs2010下test通过
功能如下:
可以用于对话框和其它窗口
SetCmdMap 用于设置“app:command”链接的命令映射。.
SetHTML 用于将字符串转换为 HTML 文档。
SetHideContextMenu隐藏菜单
CreateFromStatic关联到一个CStatic
要用的头
#include
#include
用法
m_wndPic.InitImage(&m_Pic);
nObjOutputHTML.SetHideContextMenu(TRUE);
nObjOutputHTML.CreateFromStatic(IDC_STATIC_SS,this);
nObjOutputHTML.Navigate(_T("about:blank")); nObjOutputHTML.SetHTML(m_Text);
存在的问题
IsIEWindow和OnBeforeNavigate2字符集的问题
OnDestroy中m_pBrowserApp没有销毁,用Quit?
如果不Navigate(_T("about:blank")); 就不能SetHTML
头文件如下:
#pragma once
#ifdef _WIN32_WCE
#error "CHtmlView is not supported for Windows CE."
#endif
// 该结构在命令映射中定义一个入口,这个映射将文本串映射到命令IDs,
// 如果命令映射中有一个映射到 ID_APP_ABOUT 的入口 “about”,并且
// HTML 有一个链接锚 ,那么单击该链接时将执行
struct HTMLCMDMAP{LPCTSTR name;int nID;};// command name used in
"app:name" HREF in
//这个类将 CHtmlView 转换为普通的能在对话框和框架中使用的控制
class CHtmlCtrl : public CHtmlView
{
DECLARE_DYNCREATE(CHtmlCtrl)
public:
CHtmlCtrl():m_bHideMenu(FALSE),
m_cmdmap(NULL){}; // protected constructor used by dynamic creation
virtual ~CHtmlCtrl(){};
HTMLCMDMAP* m_cmdmap;//
command map
BOOL m_bHideMenu;// hide context menu
// get/set HideContextMenu property
BOOL GetHideContextMenu(){ return m_bHideMenu;
}
void SetHideContextMenu(BOOL val){
m_bHideMenu=val; }
// Set doc contents from string
HRESULT SetHTML(LPCTSTR strHTML);
// set command map
void SetCmdMap(HTMLCMDMAP* val){ m_cmdmap = val;
}
// create control in same place as static
control
BOOL CreateFromStatic(UINT nID, CWnd*
pParent);
// create control from scratch
BOOL Create(const RECT& rc, CWnd*
pParent, UINT nID,DWORD dwStyle =
WS_CHILD|WS_VISIBLE,CCreateContext* pContext = NULL)
{
return CHtmlView::Create(NULL,
NULL, dwStyle, rc, pParent,nID, pContext);
}
// 重写该函数可以截获子窗口消息,从而禁用上下文菜单。
virtual BOOL PreTranslateMessage(MSG*
pMsg);
// 通常,CHtmlView 自己是在 PostNcDestroy
销毁的,但对于一个界面控制来说
// 我们不想那样做,因为控制一般都是作为另一个窗口对象的成员实现的。
virtual void PostNcDestroy(){}
// 重写以便旁路掉对 MFC doc/view 框架的依赖,CHtmView
仅仅在这里依附于框架。
afx_msg void OnDestroy();
afx_msg int OnMouseActivate(CWnd* pDesktopWnd,
UINT nHitTest,UINT msg);
// 重写以便截获 "app:" 伪协议
virtual void OnBeforeNavigate2( LPCTSTR
lpszURL,DWORD nFlags,LPCTSTR
lpszTargetFrameName,CByteArray&
baPostedData,LPCTSTR lpszHeaders,BOOL* pbCancel );
// 你可以重写处理 "app:"
命令的代码。注意只是在不使用命令映射机制时才需要重写
virtual void OnAppCmd(LPCTSTR
lpszCmd);
DECLARE_MESSAGE_MAP();
};
实现文件
// CHtmlCtrl 实现 -- 控件中的 web 浏览器,只要改写 CHtmlVie
// 你就可以摆脱框架 - 从而将此控制用于对话框和其它任何窗口。
//
// 特性s:
// - SetCmdMap 用于设置“app:command”链接的命令映射。.
// - SetHTML 用于将字符串转换为 HTML 文档。.
#include "StdAfx.h"
#include "HtmlCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// macro to declare a typedef for ATL
smart poitners; eg SPIHTMLDocument2
#define DECLARE_SMARTPTR(ifacename) typedef
CComQIPtr
SP##ifacename;
// smart pointer to IHTMLDocument2
DECLARE_SMARTPTR(IHTMLDocument2)
// useful macro for checking
HRESULTs
#define HRCHECK(x) hr = x; if (!SUCCEEDED(hr)) { \
TRACE(_T("hr=%p\n"),hr);\
return hr;\
}
IMPLEMENT_DYNAMIC(CHtmlCtrl,
CHtmlView)
BEGIN_MESSAGE_MAP(CHtmlCtrl, CHtmlView)
ON_WM_DESTROY()
ON_WM_MOUSEACTIVATE()
END_MESSAGE_MAP()
//
// Create control in same position as an existing static control
with given
// the same ID (could be any kind of control, really)
//
BOOL CHtmlCtrl::CreateFromStatic(UINT nID, CWnd* pParent)
{
CStatic wndStatic;
if (!wndStatic.SubclassDlgItem(nID,
pParent))
return FALSE;
// Get static control
rect, convert to parent's client coords.
CRect rc;
wndStatic.GetWindowRect(&rc);
pParent->ScreenToClient(&rc);
wndStatic.DestroyWindow();
return Create(rc,
pParent, nID);
}
// Override to avoid CView stuff that assumes a frame.
//
void CHtmlCtrl::OnDestroy()
{
m_pBrowserApp = NULL; // will call Release
CWnd::OnDestroy(); // bypass
CView doc/frame stuff
}
// Override to avoid CView stuff that assumes a frame.
//
int CHtmlCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest,
UINT msg)
{
// bypass CView doc/frame stuff
return CWnd::OnMouseActivate(pDesktopWnd,
nHitTest, msg);
}
// Return TRUE iff hwnd is internet
explorer window.
inline BOOL IsIEWindow(HWND hwnd)
{
static LPCSTR IEWNDCLASSNAME = "Internet
Explorer_Server";
char classname[32]; // always char, never
TCHAR
GetClassName(hwnd, (LPWSTR)classname,
sizeof(classname));
return strcmp(classname,
IEWNDCLASSNAME)==0;
}
//
// Override to trap "Internet Explorer_Server" window context menu
messages.
//
BOOL CHtmlCtrl::PreTranslateMessage(MSG* pMsg)
{
if (m_bHideMenu) {
switch
(pMsg->message) {
case WM_CONTEXTMENU:
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
if
(IsIEWindow(pMsg->hwnd)) {
if
(pMsg->message==WM_RBUTTONUP)
//
let parent handle context menu
GetParent()->SendMessage(WM_CONTEXTMENU,
pMsg->wParam, pMsg->lParam);
return
TRUE; // eat it
}
}
}
return
CHtmlView::PreTranslateMessage(pMsg);
}
//
// Override to pass "app:" links to virtual fn instead of
browser.
//
void CHtmlCtrl::OnBeforeNavigate2( LPCTSTR lpszURL,
DWORD nFlags, LPCTSTR lpszTargetFrameName,
CByteArray& baPostedData,
LPCTSTR lpszHeaders, BOOL* pbCancel )
{
LPCTSTR APP_PROTOCOL = _T("app:");
int len = _tcslen(APP_PROTOCOL);
if (_tcsnicmp(lpszURL, APP_PROTOCOL, len)==0)
{
OnAppCmd(lpszURL +
len); // call
virtual handler fn
*pbCancel =
TRUE; // cancel navigation
}
}
//
// Called when the browser attempts to navigate to "app:foo".
Default handler
// searches command map for "foo" command, and sends parent a
WM_COMMAND
// message with the ID if found. Call SetCmdMap to set the command
map. Only
// override OnAppCmd if you want to do something more
complex.
//
void CHtmlCtrl::OnAppCmd(LPCTSTR lpszCmd)
{
if (m_cmdmap) {
for (int i=0; m_cmdmap[i].name;
i++) {
if
(_tcsicmp(lpszCmd, m_cmdmap[i].name) == 0)
//
Use PostMessage to avoid problems with exit command. (Let
//
browser finish navigation before issuing command.)
GetParent()->PostMessage(WM_COMMAND,
m_cmdmap[i].nID);
}
}
}
//
// Set document contents from string
//
HRESULT CHtmlCtrl::SetHTML(LPCTSTR strHTML)
{
HRESULT hr;
// Get document
object
SPIHTMLDocument2 doc =
GetHtmlDocument();
// Create string as
one-element BSTR safe array for IHTMLDocument2::write.
CComSafeArray
sar;
sar.Create(1,0);
sar[0] = CComBSTR(strHTML);
// open doc and
write
LPDISPATCH lpdRet;
HRCHECK(doc->open(CComBSTR("text/html"),
CComVariant(CComBSTR("_self")),
CComVariant(CComBSTR("")),
CComVariant((bool)1),
&lpdRet));
HRCHECK(doc->write(sar)); //
write contents to doc
HRCHECK(doc->close()); //
close
lpdRet->Release(); //
release IDispatch returned
return S_OK;
}