在MFC對話方塊中顯示html網頁

來源:互聯網
上載者:User

     最近在寫一個小軟體,想在MFC對話方塊中顯示協助文檔,都是html格式的,上網找了好多資料,用一個CHtmlCtrl類的東西,但是網上找的這個類放在VS2005下編譯不過去,老是提示錯誤。於是幾經修改,可以使用,下面貼代碼(環境:Win7 + VS2005 SP1):

標頭檔:

#pragma once<br />#include <afxhtml.h><br />#include <atlsafe.h><br />////////////////////////////////////////////////////////////////<br />// 該結構在命令映射中定義一個入口,這個映射將文本串映射到命令IDs,<br />// 如果命令映射中有一個映射到 ID_APP_ABOUT 的入口 “about”,並且<br />// HTML 有一個連結錨 ,那麼單擊該連結時將執行<br />struct HTMLCMDMAP<br />{<br />LPCTSTR name;<br />int nID;<br />};// command name used in "app:name" HREF in<br />//這個類將 CHtmlView 轉換為普通的能在對話方塊和架構中使用的控制<br />class CHtmlCtrl : public CHtmlView<br />{<br />DECLARE_DYNCREATE(CHtmlCtrl)<br />public:<br />CHtmlCtrl():m_bHideMenu(FALSE), m_cmdmap(NULL){}; // protected constructor used by dynamic creation<br />virtual ~CHtmlCtrl(){};<br />HTMLCMDMAP* m_cmdmap;// command map<br />BOOL m_bHideMenu;// hide context menu<br />// get/set HideContextMenu property<br />BOOL GetHideContextMenu(){ return m_bHideMenu; }<br />void SetHideContextMenu(BOOL val){ m_bHideMenu=val; }<br />// Set doc contents from string<br />HRESULT SetHTML(LPCTSTR strHTML);<br />// set command map<br />void SetCmdMap(HTMLCMDMAP* val){ m_cmdmap = val; }<br />// create control in same place as static control<br />BOOL CreateFromStatic(UINT nID, CWnd* pParent);<br />// create control from scratch<br />BOOL Create(const RECT& rc, CWnd* pParent, UINT nID,DWORD dwStyle = WS_CHILD|WS_VISIBLE,CCreateContext* pContext = NULL)<br />{<br />return CHtmlView::Create(NULL, NULL, dwStyle, rc, pParent,nID, pContext);<br />}<br />// 重寫該函數可以截獲子視窗訊息,從而禁用操作功能表。<br />virtual BOOL PreTranslateMessage(MSG* pMsg);<br />// 通常,CHtmlView 自己是在 PostNcDestroy 銷毀的,但對於一個介面控制來說<br />// 我們不想那樣做,因為控制一般都是作為另一個視窗對象的成員實現的。<br />virtual void PostNcDestroy(){}<br />// 重寫以便旁路掉對 MFC doc/view 架構的依賴,CHtmView 僅僅在這裡依附於架構。<br />afx_msg void OnDestroy();<br />afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest,UINT msg);<br />// 重寫以便截獲 "app:" 偽協議<br />virtual void OnBeforeNavigate2( LPCTSTR lpszURL,DWORD nFlags,LPCTSTR lpszTargetFrameName,CByteArray& baPostedData,LPCTSTR lpszHeaders,BOOL* pbCancel );</p><p>// 你可以重寫處理 "app:" 命令的代碼。注意只是在不使用命令映射機制時才需要重寫<br />virtual void OnAppCmd(LPCTSTR lpszCmd);<br />DECLARE_MESSAGE_MAP();<br />};

源檔案:

////////////////////////////////////////////////////////////////// CHtmlCtrl 實現 -- 控制項中的 網頁瀏覽器,只要改寫 CHtmlVie// 你就可以擺脫架構 - 從而將此控制用於對話方塊和其它任何視窗。//// 特性s:// - SetCmdMap 用於設定“app:command”連結的命令映射。.// - SetHTML 用於將字串轉換為 HTML 文檔。.#include "StdAfx.h"#include "HtmlCtrl.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic 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 IHTMLDocument2DECLARE_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 ReleaseCWnd::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 stuffreturn 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 TCHARGetClassName(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 menuGetParent()->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 objectSPIHTMLDocument2 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 writeLPDISPATCH lpdRet;HRCHECK(doc->open(CComBSTR("text/html"),CComVariant(CComBSTR("_self")),CComVariant(CComBSTR("")),CComVariant((bool)1),&lpdRet));HRCHECK(doc->write(sar)); // write contents to docHRCHECK(doc->close());  // closelpdRet->Release();   // release IDispatch returnedreturn 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文檔

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.