我的RichEdit控件可以包含可点击的链接吗? [英] Can my RichEdit Control contain clickable links?
问题描述
我想向编辑控件或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_LINK
和CFE_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文件,并将
RichEdit20A
或RichEdit20W
替换为RichEdit50W
.W
代表控件的Unicode版本. -
调用
CRichEditCtrl::StreamIn()
插入包含超链接的RTF.在下文中,我提供了一个辅助函数StreamInRtf()
,该函数简化了将字符串流传输到控件中的任务:
- In the
InitInstance()
method of yourCWinApp
-derived class, callAfxInitRichEdit5()
if your version of Visual Studio supports it. Otherwise callLoadLibraryW(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
orRichEdit20W
byRichEdit50W
. TheW
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 functionStreamInRtf()
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屋!