• 在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 );"
  • 相关阅读:
    java设计模式之代理模式 ,以及和java 回调机制的区别
    oracle 安装,启动 ,plsql 连接
    jsp 访问文件夹中的图片,tomcat配置虚拟目录
    最实用解决tomcat startup.bat 一闪而过
    oracle 创建表
    java debug源码完整版
    node.js事件轮询(1)
    markdown命令语法
    mac常用的命令
    node + nginx + mongo搭建负载均衡
  • 原文地址:https://www.cnblogs.com/gywei/p/3387252.html
Copyright © 2020-2023  润新知