zoukankan      html  css  js  c++  java
  • 在MFC对话框中显示html网页

    最近在写一个小软件,想在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 = 李***";
    m_html.SetHTML(m_Text );"
  • 相关阅读:
    ubuntu安装jdk的两种方法
    LeetCode 606. Construct String from Binary Tree (建立一个二叉树的string)
    LeetCode 617. Merge Two Binary Tree (合并两个二叉树)
    LeetCode 476. Number Complement (数的补数)
    LeetCode 575. Distribute Candies (发糖果)
    LeetCode 461. Hamming Distance (汉明距离)
    LeetCode 405. Convert a Number to Hexadecimal (把一个数转化为16进制)
    LeetCode 594. Longest Harmonious Subsequence (最长的协调子序列)
    LeetCode 371. Sum of Two Integers (两数之和)
    LeetCode 342. Power of Four (4的次方)
  • 原文地址:https://www.cnblogs.com/gywei/p/3387252.html
Copyright © 2011-2022 走看看