Page 1 of 1

Hyperlinks in TRichEdit

PostPosted: 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

PostPosted: 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

PostPosted: 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