簡體   English   中英

我的RichEdit控件可以包含可點擊的鏈接嗎?

[英]Can my RichEdit Control contain clickable links?

我想向編輯控件或Rich Edit 2.0控件顯示一系列字符串。 之后,我希望顯示的某些文本帶有下划線並為藍色。 然后可以單擊這些帶下划線的文本以打開另一個對話框或某種形式的對話框。

有沒有辦法做到這一點?

Rich Edit 2.0僅支持自動RichEdit超鏈接,而Rich Edit 4.1和更高版本(msftedit.dll)支持友好名稱超鏈接

可以通過結合使用CFE_LINKCFE_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鍵以瀏覽各個鏈接,而后者則不支持。

實施友好名稱超鏈接(Rich Edit 4.1+)

免責聲明:以下代碼已在Win 10下經過創建者更新測試。 我還沒有時間在較舊的OS版本下進行測試。

  • 如果您的Visual Studio版本支持,則在CWinApp派生類的InitInstance()方法中,調用AfxInitRichEdit5() 否則,調用LoadLibraryW(L"msftedit.dll")
  • 確保richedit控件使用正確的窗口類。 資源編輯器默認情況下會創建RichEdit 2.0。 您需要使用文本編輯器手動編輯.rc文件並替換RichEdit20ARichEdit20W通過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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM