【问题标题】:How can I create href links on CHtmlEditCtrl?如何在 CHtmlEditCtrl 上创建 href 链接?
【发布时间】:2019-02-02 15:54:01
【问题描述】:

我使用 Visual Studio 2017 c++ MFC 和 CHtmlEditCtrl 的 Web 链接创建一个对话框。

但是,href 链接不起作用...

我期待以下行为。

  1. 点击链接
  2. 浏览器(例如 chrome)启动
  3. 在浏览器上显示网页

如何修复我的代码?

BOOL CTestDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // ...

    CHtmlEditCtrl* htmledit = new CHtmlEditCtrl();
    CEdit* edit = (CEdit*)GetDlgItem(IDC_EDIT_HTML);
    CRect rc;
    edit->GetWindowRect(&rc);
    this->ScreenToClient(&rc);
    htmledit->Create(0, (WS_CHILD | WS_VISIBLE), rc, this, IDC_EDIT_HTML, 0);

    CComPtr<IHTMLDocument2> document;
    htmledit->GetDocument(&document);
    WaitForComplete(document);
    htmledit->SetDocumentHTML(_T("<a href=\"https://www.google.co.jp/\" target=\"_blank\">Google</a><br><a href=\"https://stackoverflow.com/\" target=\"_blank\">stackoverflow</a>"));
    WaitForComplete(document);

    return TRUE;
}

void CTestDlg::WaitForComplete(IHTMLDocument2* document)
{
    BSTR ready;
    document->get_readyState(&ready);
    while (wcscmp(ready, L"complete"))
    {
        AfxPumpMessage();
        document->get_readyState(&ready);
    };
}

我参考了以下网站。

【问题讨论】:

    标签: html c++ mfc


    【解决方案1】:

    CHtmlEditCtrl 覆盖 NavigateComplete2 并调用 SetDesignMode(TRUE)。如果你想要一个查看器,而不是编辑器,那么覆盖如下:

    class CMyHtmlEditCtrl : public CHtmlEditCtrl
    {
        virtual void _OnNavigateComplete2(LPDISPATCH, VARIANT FAR*) 
        { 
            //SetDesignMode(TRUE);
        }
    public:
        DECLARE_EVENTSINK_MAP()
    };
    
    BEGIN_EVENTSINK_MAP(CMyHtmlEditCtrl, CHtmlEditCtrl)
        ON_EVENT_REFLECT(CMyHtmlEditCtrl, 252 /* NavigateComplete2 */, _OnNavigateComplete2, VTS_DISPATCH VTS_PVARIANT)
    END_EVENTSINK_MAP()
    

    使用这个类而不是CHtmlEditCtrl。您将不再需要WaitForComplete,因为SetDesignMode 不会阻止OnInitDialog 中的调用。


    要启动默认浏览器,您还必须覆盖 _OnBeforeNavigate

    此外,将# 添加到链接:href="#http://www.google.com" 以便浏览器控件不知道如何处理该链接,而是让您处理它。然后将#http://www.google.com 转换为http://www.google.com 并打开链接。

    声明为CMyHtmlEditCtrl browser; 为类成员以避免泄漏。

    例子:

    class CMyHtmlEditCtrl : public CHtmlEditCtrl
    {
    public:
        virtual void _OnNavigateComplete2(LPDISPATCH, VARIANT FAR*)
        {
            //SetDesignMode(TRUE);
        }
    
        void _OnBeforeNavigate2(LPDISPATCH,
            VARIANT* URL, VARIANT*, VARIANT*, VARIANT*, VARIANT*, VARIANT_BOOL*)
        {
            CString str(V_BSTR(URL));
            int pos = str.Find(L'#');
            if(pos >= 0)
            {
                str = str.Mid(pos + 1);
                ShellExecute(NULL, L"open", str, NULL, NULL, SW_SHOWNORMAL);
            }
        }
    
        DECLARE_EVENTSINK_MAP()
    };
    
    BEGIN_EVENTSINK_MAP(CMyHtmlEditCtrl, CHtmlEditCtrl)
        ON_EVENT_REFLECT(CMyHtmlEditCtrl, 250, _OnBeforeNavigate2, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
        ON_EVENT_REFLECT(CMyHtmlEditCtrl, 252, _OnNavigateComplete2, VTS_DISPATCH VTS_PVARIANT)
    END_EVENTSINK_MAP()
    
    ...
    //declare class member for CMyDialog:
    CMyHtmlEditCtrl browser;
    ...
    
    CMyHtmlEditCtrl browser;
    BOOL CMyDialog::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
    
        CWnd* edit = GetDlgItem(IDC_EDIT1);
        CRect rc;
        edit->GetWindowRect(&rc);
        ScreenToClient(&rc);
        browser.Create(0, WS_CHILD | WS_VISIBLE, rc, this, 301, 0);
    
        CString html = LR"(<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 
    Transitional//EN">
    <html>
    <head>
    <style type="text/css">
    body
    {
        border:1px solid gray;
    }
    </style>
    </head>
    <body>
    <a href="#http://www.stackoverflow.com">http://www.stackoverflow.com</a>
    </body>
    </html>
    )";
    
        browser.SetDocumentHTML(html);
        return TRUE;
    }
    

    【讨论】:

    • IE 已启动。如何启动默认浏览器?如果你知道,请告诉我。我已经使用 Windows 的设置为默认浏览器设置了 chrome。
    • 我添加了一个例子。您也可以考虑改用CDHtmlDialogCDHtmlDialog 将接管整个对话框,它不是子控件,但更容易。
    • 谢谢!该示例完美运行。我学到了一些新东西!
    • 其实你可以把SetDesignMode注释掉,然后你就不需要WaitForComplete了。查看更新。
    • 我检查了新示例。谢谢你的好意。
    猜你喜欢
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 2018-09-06
    • 1970-01-01
    • 2019-07-19
    • 2016-11-10
    • 1970-01-01
    • 2015-03-02
    相关资源
    最近更新 更多