如何在富编辑控件上实现鼠标单击URL

我在对话框中添加了一个只读的富编辑2.0控件(代码使用的是C windows API,该对话框是使用函数DialogBox创建的)

在对话框回调中,在WM_INITDIALOG,我添加以下代码以启用URL检测,并启用事件ENM_LINK被发送到父对话框而不是富编辑控件本身:

LRESULT mask = SendMessage(hWndText, EM_GETEVENTMASK, 0, 0); //hWndText is rich edit control SendMessage(hWndText, EM_SETEVENTMASK, 0, mask | ENM_LINK); ::SendMessage(hWndText, EM_AUTOURLDETECT, TRUE, NULL); 

在最初启动对话框时启用url检测时遇到了一些麻烦(这似乎是一个已知问题或行为,因为丰富的编辑控件只能启用对已修改文本的url检测)。 但是,我通过在每个WM_PAINT事件上再次设置对话框文本来解决此问题。

代码通常有效。 我还实现了以下代码,当鼠标hover在url上时,在浏览器中启动URL:

 case WM_NOTIFY: plink = (ENLINK *) lParam; switch(LOWORD(wParam)) { case IDC_DISPLAY_TEXT_2: //this is ID for my rich edit control szURL =m_strDisplay.Mid(plink->chrg.cpMin, plink->chrg.cpMax - plink->chrg.cpMin); LaunchURL(szURL); //function to launch the url with default browser break; default: break; } 

每当我将鼠标hover在url上时,我似乎都会收到WM_NOTIFY事件。 但是当我点击它时,鼠标hover在鼠标hover上时,我总是得到相同的事件。

基于ENLINK的结构,我应该在NMHDR结构中获得更详细的NM事件,但是值plink-> nmhdr.code始终是1803,甚至不是NM_HOVER(其定义的值是(NM_FIRST-13)而NM_FIRST是( 0U-0U),因此我的64位机器上的NM_HOVER值为4294967283)。 我知道我在这里遗漏了一些东西。 有人可以在这里点灯吗? 如何获得富编辑控件的鼠标单击事件?

我认为您应该捕获EN_LINK通知。 我实现了以下代码。 它允许将richedit控件中的url链接放入父窗口,而不是对话框。 您也可以根据对话进行调整。

考虑从代码开始:

 case WM_NOTIFY: { switch (((LPNMHDR)lParam)->code) { //NMHDR structure contains information about a notification message. case EN_LINK: { ENLINK *enLinkInfo = (ENLINK *)lParam; // pointer to a ENLINK structure 

那么,如果你选择在LBUTTONUP上启动url,你必须检查enLinkInfo->msg包含的值(记得为你的对话框调整它)

  if (enLinkInfo->msg == WM_LBUTTONUP) { // select all the text from enLinkInfo->chrg.cpMin to enLinkInfo->chrg.cpMax // lauch the url } 

此外,你可以拦截WM_MOUSEMOVE:

 if(enLinkInfo->msg == WM_MOUSEMOVE) { ; // do nothing } 

希望能帮助到你。

正如@ A_nto2的答案所示,要拦截鼠标点击,请执行以下操作:

 case WM_NOTIFY: { //NMHDR structure contains information about a notification message. switch (((LPNMHDR)lParam)->code) { case EN_LINK: { ENLINK *enLinkInfo = (ENLINK *)lParam; // pointer to a ENLINK structure if (enLinkInfo->msg == WM_LBUTTONUP) { 

但棘手的部分是获取被点击的链接。

获得一个在“ enLinkInfo->chrg ”类型的enLinkInfo->chrg中单击的“范围”。

在RichEdit中检测点击URL的答案建议使用EM_EXSETSELenLinkInfo->chrg 。 然后使用EM_GETSELTEXT检索文本。

这适用于自动检测到的纯文本URL( EM_AUTOURLDETECT )。

问题在于友好名称超链接(即具有与URL本身不同的锚文本的超链接):

 {\rtf1{\field{\*\fldinst{ HYPERLINK "https://www.example.com"}}{\fldrslt{Example}}}} 

(请注意,Rich Edit 4.1和更新版本仅支持这些function)

对于这些, CHARRANGE指向HYPERLINK "https://www.example.com"部分,该部分是隐藏的,无法使用EM_EXSETSEL进行选择。 实际上它可以在Windows 10上选择。但它无法在Windows 7,Vista和XP上选择。 将EM_EXSETSEL发送到这些系统会导致在隐藏部分之后选择零长度块。

所以要么你必须回到富编辑缓冲区并扫描链接; 或使用其他方法检索点击的文本。

就我而言,因为我只在富编辑中有小文本,所以我使用了WM_GETTEXT 。 它返回富文本编辑文档的纯文本版本,但在此表单中保留了友好名称超链接:

 HYPERLINK "https://www.example.com" Example 

CHARRANGE指向URL,奇怪的是包括引号:( "https://www.example.com )。

但索引对应于具有单字符(LF)行分隔符的文本。 而WM_GETTEXT返回CRLF分隔符。 因此,在使用CHARRANGE提取URL之前,必须将文本转换为LF。

根据EM_AUTOURLDETECT的文档,您应该收到EN_LINK通知,该通知应反映在nmhdr.code 。 根据谷歌的说法,

 #define EN_LINK 0x70B 

这是7 * 256 + 11 = 1750 + 42 + 11 = 1803。

请注意,您的代码错过了对nmhdr.code == EN_LINK的检查。

我不确定控件是否发送NM_HOVER消息。