Page 1 of 1

Hyperlinks in TRichEdit

Posted: Mon Dec 01, 2014 2:37 pm
by Marloes
I've got a strange problem. I've enabled the TRichEdit for hyperlinks

Code: Select all

	unsigned masktxt = SendMessage(redText->Handle, EM_GETEVENTMASK, 0, 0);
	SendMessage(redText->Handle, EM_SETEVENTMASK, 0, masktxt | ENM_LINK);
	SendMessage(redText->Handle, EM_AUTOURLDETECT, true, 0);
and

Code: Select all

void __fastcall TMainForm::WndProc(Messages::TMessage &Message) {
	if (Message.Msg == WM_NOTIFY) {
		if (((LPNMHDR) Message.LParam)->code == EN_LINK) {
			ENLINK *p = (ENLINK*) Message.LParam;
			if (p->msg == WM_LBUTTONDOWN) {
				ShowMessage("I'm here!");
				SendMessage(redText->Handle, EM_EXSETSEL, 0, (LPARAM) &(p->chrg));
				ShellExecute(Handle, "open", redText->SelText.c_str(), 0, 0, SW_SHOWNORMAL);
			}
		}
	}

	TForm::WndProc(Message);
}
The hyperlinks display correctly and when I put the mouse over the link the cursor changes to a hand point as it should. But when I click, nothing happens. As per the code above, the message "I'm here!" should display, but it does not. For some reason no message seem to be sent that the hyperlink is clicked. Does anybody have any idea what could be going on?

When I put the code in a separate test app with just a the TRichEdit component, everything works fine, so I am worried there is something prevent my app from working as intended but I cannot understand what that could be.

Re: Hyperlinks in TRichEdit

Posted: Tue Dec 02, 2014 3:50 am
by rlebeau
Is TMainForm the direct parent of the TRichEdit? I'm guessing no. Which would explain why it works in your test app. The WM_NOTIFY message is sent to the RichEdit's immediate parent window.

A more reliable way to handle this would be to subclass the TRichEdit itself and handle the CN_NOTIFY message. The VCL is designed to forward WM_NOTIFY (and WM_COMMAND) messages as CN_NOTIFY (and CN_COMMAND) to the original control that generated them, so controls can handle their own messages. For example:

Code: Select all

class TMainForm : public TForm
{
...
private:
    TWndMethod PrevRichEditWndProc;
    void __fastcall RichEditWndProc(Messages::TMessage &Message);
...
public:
    __fastcall TMainForm(TComponent *Owner);
...
};

Code: Select all

__fastcall TMainForm::TMainForm(TComponent *Owner)
    : TForm(Owner)
{
    PrevRichEditWndProc = redText->WindowProc;
    redText->WindowProc = &RichEditWndProc;
}

void __fastcall TMainForm::RichEditWndProc(Messages::TMessage &Message)
{
    if (Message.Msg == CN_NOTIFY)
    {
        if (reinterpret_cast<LPNMHDR>(Message.LParam)->code == EN_LINK)
        {
            ENLINK *p = reinterpret_cast<ENLINK*>(Message.LParam);
            if (p->msg == WM_LBUTTONDOWN)
            {
                ShowMessage("I'm here!");
                SendMessage(redText->Handle, EM_EXSETSEL, 0, reinterpret_cast<LPARAM>(&(p->chrg)));
                ShellExecute(Handle, NULL, redText->SelText.c_str(), 0, 0, SW_SHOWNORMAL);
                return;
           }
        }
    }
    PrevRichEditWndProc(Message);
}

Re: Hyperlinks in TRichEdit

Posted: Tue Dec 02, 2014 6:30 am
by Marloes
Yes, the TRichEdit was inside a TPageControl but your solution worked perfectly. Thank you so much

Re: Hyperlinks in TRichEdit

Posted: Sat Apr 25, 2020 4:59 am
by charlottejw23
Thanks for the code. It's helpful much.