在MFC对话框中显示html网页

    技术2022-11-29  48

         最近在写一个小软件,想在MFC对话框中显示帮助文档,都是html格式的,上网找了好多资料,用一个CHtmlCtrl类的东西,但是网上找的这个类放在VS2005下编译不过去,老是提示错误。于是几经修改,可以使用,下面贴代码(环境:Win7 + VS2005 SP1):

    头文件:

    #pragma once #include <afxhtml.h> #include <atlsafe.h> // 该结构在命令映射中定义一个入口,这个映射将文本串映射到命令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<ifacename> 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, (LPSTR)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 = (int)_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<VARIANT> 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; }

    使用方法,在自己的对话框上拖进来一个static,然后修改一下ID为IDC_STATIC_HELP,然后在对话框的初始化函数,也就是OnInitDialog()中添加下面代码,注意下面的m_html是一个类成员变量,定义在头文件中 ,CHtmlCtrl m_html;

    BOOL CHelpDialog::OnInitDialog() { CDialog::OnInitDialog(); m_html.SetHideContextMenu(TRUE); m_html.CreateFromStatic(IDC_STATIC_HELP,this); m_html.Navigate(m_strUrl); //CString m_Text = " 李民录 "; //m_html.SetHTML(m_strUrl); return TRUE; // 除非将焦点设置到控件,否则返回TRUE }

    至此,调用你的对话框,就可以看到效果了。

    如果你想直接显示html文本的话,可以这样写:

    m_html.SetHideContextMenu(TRUE); m_html.CreateFromStatic(IDC_STATIC_HELP,this); m_html.Navigate("about:blank"); //这句话一定要写 CString m_Text = 李民录liminlu0314@163.com> "; m_html.SetHTML(m_Text );"

    运行效果图

    HTML文档

    最新回复(0)