[英]Can my RichEdit Control contain clickable links?
我想向編輯控件或Rich Edit 2.0控件顯示一系列字符串。 之后,我希望顯示的某些文本帶有下划線並為藍色。 然后可以單擊這些帶下划線的文本以打開另一個對話框或某種形式的對話框。
有沒有辦法做到這一點?
Rich Edit 2.0僅支持自動RichEdit超鏈接,而Rich Edit 4.1和更高版本(msftedit.dll)支持友好名稱超鏈接 。
您可以通過結合使用CFE_LINK
和CFE_HIDDEN
字符格式設置標志 來模擬Rich Edit 2.0中的友好名稱超鏈接。 使用CFE_LINK
標記文本,並通過應用CFE_HIDDEN
隱藏URL。 處理EN_LINK
通知以對點擊做出反應。 在這一點上,您必須進行一些分析才能從RTF文本中提取隱藏的URL。
或者,只需使用CFE_LINK
作為文本,然后使用std::map
將文本映射到URL。 只要文本與URL的1:1映射就可以使用。
編輯:我剛剛指出,單擊鏈接時,您只想“打開另一個對話框”,因此在您的情況下,只需應用CFE_LINK
就足夠了。
編輯2:如果您不需要顯示格式化的文本並且也不需要滾動,則建議使用SysLink控件 。 與RichEdit控件中的鏈接相比,SysLink控件顯示的鏈接具有更好的可訪問性。 前者支持TAB鍵以瀏覽各個鏈接,而后者則不支持。
免責聲明:以下代碼已在Win 10下經過創建者更新測試。 我還沒有時間在較舊的OS版本下進行測試。
CWinApp
派生類的InitInstance()
方法中,調用AfxInitRichEdit5()
。 否則,調用LoadLibraryW(L"msftedit.dll")
。 RichEdit20A
或RichEdit20W
通過RichEdit50W
。 W
代表控件的Unicode版本。 調用CRichEditCtrl::StreamIn()
以插入包含超鏈接的RTF。 在下面的內容中,我提供了一個輔助函數StreamInRtf()
,它簡化了將字符串流傳輸到控件中的任務:
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更具可讀性):
StreamInRtf( m_richedit, R"({\\rtf1 {\\field{\\*\\fldinst {HYPERLINK "https://www.stackoverflow.com" }}{\\fldrslt {stackoverflow}}}\\par Some other text\\par })" );
要處理點擊,您需要為EN_LINK
控件啟用EN_LINK
通知,例如:
m_richedit.SetEventMask( m_richedit.GetEventMask() | ENM_LINK );
將EN_LINK
的處理程序添加到您的消息映射中:
BEGIN_MESSAGE_MAP(CMyDialog, CDialog) ON_NOTIFY( EN_LINK, IDC_RICHEDIT1, OnLink ) END_MESSAGE_MAP()
定義事件處理程序方法以處理鼠標單擊和返回鍵:
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
消息來啟用此功能:
DWORD style = SES_HYPERLINKTOOLTIPS | SES_NOFOCUSLINKNOTIFY; m_richedit.SendMessage( EM_SETEDITSTYLE, style, style );
如果您缺少定義,則它們是:
#ifndef SES_HYPERLINKTOOLTIPS #define SES_HYPERLINKTOOLTIPS 8 #endif #ifndef SES_NOFOCUSLINKNOTIFY #define SES_NOFOCUSLINKNOTIFY 32 #endif
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.