I added a read-only rich edit 2.0 control to my dialog (code is using C windows API, the dialog is created by using function DialogBox)
At the dialog call back, at the WM_INITDIALOG, I add the following code to enable url detection and also enable the event ENM_LINK is sent to the parent dialog instead of the rich edit control itself:
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);
I had a little trouble to enable the url detection when dialog is initially launched (which seems a known issue or behavior since rich edit control would only enable url detection of modified text). However I worked around this issue by setting the dialog text again on every WM_PAINT event.
The code is generally working. I also implemented the following code to launch the URL at the browser when mouse is hovering over the 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;
}
It seems that I would get WM_NOTIFY event every time when I hovered the mouse over the url. However when I clicked on it, I always get same event as the mouse hover over.
Based on the structure of ENLINK, I should get more detailed NM event at the NMHDR structure, however the value plink->nmhdr.code is always 1803 which is not even NM_HOVER (its defined value is (NM_FIRST-13) and NM_FIRST is (0U- 0U), so NM_HOVER value is 4294967283 on my 64 bit machine). I know that I am missing something here. Could someone shed some lights here? How can I get the mouse click event for the rich edit control?
I think you should capture the EN_LINK notification. I implemented the following code. It enables a url link in a richedit control placed into the parent window, not into a dialog. You could adapt it for your dialog, as well.
Consider beginning with the code:
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
then, if you choose to launch url on LBUTTONUP, you have to check the value contained in enLinkInfo->msg
(remember to adapt it for your dialog, though)
if (enLinkInfo->msg == WM_LBUTTONUP) {
// select all the text from enLinkInfo->chrg.cpMin to enLinkInfo->chrg.cpMax
// lauch the url
}
Besides, you can intercept WM_MOUSEMOVE:
if(enLinkInfo->msg == WM_MOUSEMOVE) {
; // do nothing
}
Hope it helps.
As the answer by @A_nto2 shows, to intercept a mouse click do:
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) {
But the tricky part is to get the link that was clicked on.
One gets a "range" that was clicked on in the enLinkInfo->chrg
of the type CHARRANGE
.
An answer to Detect click on URL in RichEdit suggests using the EM_EXSETSEL
with the enLinkInfo->chrg
. And then using the EM_GETSELTEXT
to retrieve the text.
That works with auto-detected plain-text URLs (EM_AUTOURLDETECT
).
A problem is with friendly name hyperlinks (i.e. those that have an anchor text different than the URL itself):
{\rtf1{\field{\*\fldinst{ HYPERLINK "https://www.example.com"}}{\fldrslt{Example}}}}
(Note that these are supported in Rich Edit 4.1 and newer only)
For these, the CHARRANGE
points to the HYPERLINK "https://www.example.com"
part, which is hidden and cannot be selected using the EM_EXSETSEL
. Actually it can be selected on Windows 10. But it cannot be selected on Windows 7, Vista and XP. Sending the EM_EXSETSEL
to these systems results in selecting a zero-length block just after the hidden part.
So either you have to go back in the rich edit buffer and scan for the link; or use another method to retrieve the clicked text.
In my case, as I have small texts only in the rich edit, I've used the WM_GETTEXT
. It returns a plain-text version of the rich edit document, but with the friendly name hyperlinks preserved in this form:
HYPERLINK "https://www.example.com" Example
The CHARRANGE
points to the URL, strangely including the leading quote: ("https://www.example.com
).
But the indexes correspond to a text with a single-character (LF) line separators. While the WM_GETTEXT
returns the CRLF separators. So you have to convert the text to the LF before extracting the URL using the CHARRANGE
.
According to the documentation of EM_AUTOURLDETECT, you are supposed to get an EN_LINK notification, which should be reflected in the nmhdr.code
. According to Google,
#define EN_LINK 0x70B
which is 7 * 256 + 11 = 1750 + 42 + 11 = 1803.
Please note that your code misses a check for nmhdr.code == EN_LINK
.
I'm not sure if the control sends NM_HOVER
messages at all.
来源:https://stackoverflow.com/questions/11398248/how-to-implement-the-mouse-click-for-urls-at-rich-edit-control