我的RichEdit控件可以包含可点击的链接吗? [英] Can my RichEdit Control contain clickable links?

查看:129
本文介绍了我的RichEdit控件可以包含可点击的链接吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想向编辑控件或Rich Edit 2.0控件显示一系列字符串.之后,我希望显示的某些文本带有下划线并为蓝色.然后可以单击这些带下划线的文本,以打开另一个对话框或某种形式的对话框.

I want to display a series of strings to an Edit Control or Rich Edit 2.0 Control. After that, I want some of the text displayed to be underlined and in blue. These underlined texts can then be clicked to open another dialog or some sort.

有没有办法做到这一点?

Is there a way to do this?

推荐答案

Rich Edit 2.0仅支持

Rich Edit 2.0 only supports Automatic RichEdit Hyperlinks while Rich Edit 4.1 and newer (msftedit.dll) supports Friendly Name Hyperlinks.

可以通过结合使用CFE_LINKCFE_HIDDEN EN_LINK 通知以对点击做出反应.此时,您必须进行一些解析才能从RTF文本中提取隐藏的URL.

You can emulate friendly name hyperlinks in Rich Edit 2.0 by using a combination of the CFE_LINK and CFE_HIDDEN character formatting flags. Mark the text with CFE_LINK and hide the URL by applying CFE_HIDDEN. Handle the EN_LINK notification to react on clicks. At this point you would have to do some parsing to extract the hidden URL from the rich text.

或者仅对文本使用CFE_LINK,并使用std::map将文本映射到URL.只要文本与URL的比例为1:1,就可以使用此功能.

Alternatively just use CFE_LINK for the text and use a std::map to map text to URLs. This will work as long as there is a 1:1 mapping of text to URL.

我刚刚指出,您只想在单击链接时打开另一个对话框",因此,在您的情况下,只需应用CFE_LINK就足够了.

I just noted that you just want "to open another dialog" when a link is clicked, so just applying CFE_LINK should be good enough in your case.

如果不需要显示带格式的文本,也不需要滚动,则建议使用

Edit 2: If you don't need to display formatted text and you also don't need scrolling, I suggest to use the SysLink control. Links displayed by the SysLink control have better accessibility than links in the RichEdit control. The former supports the TAB key to navigate through the individual links whereas the latter does not.

免责声明:以下代码已在Windows 10下经过创建者更新测试.我还没有时间在较旧的OS版本下进行测试.

Disclaimer: The following code has been tested under Win 10 with creators update. I haven't found time yet to test it under older OS versions.

  • 在您的CWinApp派生类的InitInstance()方法中,如果您的Visual Studio版本支持,请调用AfxInitRichEdit5().否则,请致电LoadLibraryW(L"msftedit.dll").
  • 确保richedit控件使用正确的窗口类.资源编辑器默认情况下会创建RichEdit 2.0.您需要使用文本编辑器手动编辑.rc文件,并将RichEdit20ARichEdit20W替换为RichEdit50W. W代表控件的Unicode版本.
  • 调用CRichEditCtrl::StreamIn()插入包含超链接的RTF.在下文中,我提供了一个辅助函数StreamInRtf(),该函数简化了将字符串流传输到控件中的任务:

  • In the InitInstance() method of your CWinApp-derived class, call AfxInitRichEdit5() if your version of Visual Studio supports it. Otherwise call LoadLibraryW(L"msftedit.dll").
  • Make sure the richedit control uses the right window class. The resource editor creates a RichEdit 2.0 by default. You need to manually edit the .rc file using a text editor and replace RichEdit20A or RichEdit20W by RichEdit50W. The W stands for the Unicode version of the control.
  • Call CRichEditCtrl::StreamIn() to insert the RTF containing the hyperlink(s). In the following I provide a helper function StreamInRtf() that simplifies the task of streaming a string into the control:

struct StreamInRtfCallbackData
{
    char const* pRtf;
    size_t size;
};

DWORD CALLBACK StreamInRtfCallback( DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb )
{
    StreamInRtfCallbackData* pData = reinterpret_cast<StreamInRtfCallbackData*>( dwCookie );

    // Copy the number of bytes requested by the control or the number of remaining characters
    // of the source buffer, whichever is smaller.
    size_t sizeToCopy = std::min<size_t>( cb, pData->size );
    memcpy( pbBuff, pData->pRtf, sizeToCopy );

    *pcb = sizeToCopy;

    pData->pRtf += sizeToCopy;
    pData->size -= sizeToCopy;

    return 0;
}

DWORD StreamInRtf( CRichEditCtrl& richEdit, char const* pRtf, size_t size = -1, bool selection = false )
{
    StreamInRtfCallbackData data;
    data.pRtf = pRtf;
    data.size = ( size == -1 ? strlen( pRtf ) : size );

    EDITSTREAM es;
    es.dwCookie    = reinterpret_cast<DWORD_PTR>( &data );
    es.dwError     = 0;
    es.pfnCallback = StreamInRtfCallback;

    int flags = SF_RTF | ( selection ? SFF_SELECTION : 0 );

    richEdit.StreamIn( flags, es );

    return es.dwError;
}

用法示例(在此处使用原始字符串文字以使RTF更具可读性):

Example usage (using a raw string literal here to make the RTF more readable):

StreamInRtf( m_richedit, 
R"({\rtf1
{\field{\*\fldinst {HYPERLINK "https://www.stackoverflow.com" }}{\fldrslt {stackoverflow}}}\par
Some other text\par
})" );

  • 要处理单击,您需要为richedit控件启用EN_LINK通知,例如. g.:

  • To handle clicks you need to enable EN_LINK notifications for the richedit control, e. g.:

    m_richedit.SetEventMask( m_richedit.GetEventMask() | ENM_LINK );
    

    EN_LINK的处理程序添加到您的消息映射中:

    Add a handler for EN_LINK to your message map:

    BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
        ON_NOTIFY( EN_LINK, IDC_RICHEDIT1, OnLink )
    END_MESSAGE_MAP()
    

    定义事件处理程序方法以处理鼠标单击和返回键:

    Define the event handler method to handle mouse clicks and the return key:

    void CMyDialog::OnLink( NMHDR* pnm, LRESULT* pResult )
    {
        ENLINK* pnml = reinterpret_cast<ENLINK*>( pnm );
    
        if(   pnml->msg == WM_LBUTTONDOWN || 
            ( pnml->msg == WM_KEYDOWN && pnml->wParam == VK_RETURN ) )
        {
            CString url;
            m_richedit.GetTextRange( pnml->chrg.cpMin, pnml->chrg.cpMax, url );
            AfxMessageBox( L"URL: \"" + url + L"\"" );
    
            *pResult = 1; // message handled
        }
    
        *pResult = 0;  // enable default processing
    }
    

  • 从Windows 8开始,该控件可以显示一个工具提示,该提示在鼠标光标下方显示链接的URL.可以通过向控件发送EM_SETEDITSTYLE消息来启用此功能:

  • Beginning with Windows 8, the control can show a tooltip that displays the URL of the link under the mouse cursor. This feature can be enabled by sending the EM_SETEDITSTYLE message to the control:

    DWORD style = SES_HYPERLINKTOOLTIPS | SES_NOFOCUSLINKNOTIFY;
    m_richedit.SendMessage( EM_SETEDITSTYLE, style, style );
    

    如果您缺少定义,则为:

    In case you are missing the defines, here they are:

    #ifndef SES_HYPERLINKTOOLTIPS
        #define SES_HYPERLINKTOOLTIPS   8
    #endif
    #ifndef SES_NOFOCUSLINKNOTIFY
        #define SES_NOFOCUSLINKNOTIFY   32
    #endif 
    

  • 这篇关于我的RichEdit控件可以包含可点击的链接吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆