1. Computing
Send to a Friend via Email
Adding URL hyperlink functionality to RichEdit
Here's how to add URL hyperlink functionality to a TRichEdit component - whenever the text in a RichEdit matches the format of a URL, the control will display it as a hyperlink.
 Win prizes by sharing code!
Do you have some Delphi code you want to share? Are you interested in winning a prize for your work?
Delphi Programming Quickies Contest
 More of this Feature
• Download CODE

• TRichEditURL - hyperlink aware RichEdit
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• Using ShellExecute
• How to hot-track any control
• Sending messages
 Elsewhere on the Web
• RichEdit on MSDN

Interested? Here's even more: when you click the URL, your Web browser will be launched and the link will be loaded into the browser; or if the URL is a "mailto:" link, your default email client will be launched, thus enabling you to send e-mail messages "from" RichEdit.

About the TRichEdit control
The TRichEdit control included in the VCL (located under "Win32" tab of the component palette) is a wrapper for a Windows rich text edit control. Rich text edit controls let the user enter (edit, format, print, and save) text that includes font and paragraph formatting.

Unfortunately, Delphi's implementation of the RichEdit control leaves out a lot of the functionality found in more recent versions of this control (from Microsoft).

In this article you'll learn how to implement URL highlighting in a TRichEdit control ... and much more.

Detecting URLs in RichEdit
To follow along, I suggest you to create a new Delphi application and drop two TRichEdit control on an empty form. Leave the default component names (RichEdit1 and RichEdit2 on Form1).

In general, this is what needs to be done to "URL enable" a TRichEdit control:

  1. Send a specific message (EM_GETEVENTMASK) to a RichEdit control, to get the event mask for a rich edit control. The event mask specifies which notification messages the control sends to its parent window.
  2. Send the specific EM_SETEVENTMASK message to RichEdit including the ENM_LINK flag. Once ENM_LINK is included in the mask, the EN_LINK message is sent when a link (URL) is clicked with the mouse.
  3. Send the EM_AUTOURLDETECT message to a RichEdit. An EM_AUTOURLDETECT message enables (or disables) automatic detection of URLs by a rich edit control.

EN_LINK, EM_AUTOURLDETECT ?
Let's just take a quick look at what those "specific" messages and flags do to a RichEdit control.
As stated above, when ENM_LINK is included in the event mask for a rich edit control, the controls send the EN_LINK to its parent when a link is clicked with the mouse.

For a RichEdit to actually display the link (underline, change font color, etc.) we need to send it the EM_AUTOURLDETECT message. The most interesting result of this action is that when URL detection is enabled, the control scans any modified text to determine whether the text matches the format of a URL. The control detects, among others, URLs that begin with the following prefixes: "http:", "file:", "mailto:", "ftp", ...

This gives us the possibility to actually launch the Web browser and navigate to the URL ("http:" prefix); or to send an e-mail from a RichEdit if the URL contains the "mailto:" prefix.

Highlighting URLs in TRichEdit
The code below shows how this can be done in Delphi; I've placed the required code in the InitRichEditURLDetection procedure - this procedure is called from the OnCreate event handing procedure for a Form. In the FormCreate procedure I also set some example text in both RichEdit controls. Note that only the first (RichEdit1) rich edit control is "URL-detect" enabled.

procedure TForm1.InitRichEditURLDetection(RE: TRichEdit);
var
  mask: Word;
begin
  mask := SendMessage(RE.Handle, EM_GETEVENTMASK, 0, 0);
  SendMessage(RE.Handle, EM_SETEVENTMASK, 0, mask or ENM_LINK);
  SendMessage(RE.Handle, EM_AUTOURLDETECT, Integer(True), 0);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  s: string;
begin
  InitRichEditURLDetection(RichEdit1);

  s:='Great Delphi tutorials and articles at ' +
     'http://www.delphi.about.com.' + #13#10 +
     'About Delphi Programming site!' + #13#10 +
     'Send an email to your Guide: mailto:delphi@aboutguide.com';
  RichEdit1.Text := s;

  s:= 'http://www.delphi.about.com. ' +
      ' This Rich Edit does not recognize URLs!';
  RichEdit2.Text := s
end;

If you run the application, this is how your RichEdits could (should) look like:

URL in TRichEdit

Note: the second RichEdit control does not recognize the text containing the URL - because we called the InitRichEditURLDetection only for the "first" one (just to make things more complicated).

Click & Launch
Hm, great, but nothing happens when you click the link?! Yes, we have to code some more to actually respond to EN_LINK message sent from RichEdit to its parent (Form1).

To catch the EN_LINK message we override the WndProc method for our Form - since this is the first method that receives messages for a form.
Once the message is caught we use the RichEdit specific record structure TENLink (defined in RichEdit.pas unit) to get our hands on the entire link - then we simply use the ShellExecute procedure to launch the default application for the URL.

Here's how:

procedure TForm1.WndProc(var Msg: TMessage);
var
  p: TENLink;
  sURL: string;
  CE : TRichEdit;
begin
 if (Msg.Msg = WM_NOTIFY) then
 begin
  if (PNMHDR(Msg.lParam).code = EN_LINK) then
  begin
   p := TENLink(Pointer(TWMNotify(Msg).NMHdr)^);
   if (p.Msg = WM_LBUTTONDOWN) then
   begin
    try
     CE := TRichEdit(Form1.ActiveControl);
     SendMessage(CE.Handle, EM_EXSETSEL, 0, Longint(@(p.chrg)));
     sURL := CE.SelText;
     ShellExecute(Handle, 'open', PChar(sURL), 0, 0, SW_SHOWNORMAL);
    except
    end;
   end;
  end;
 end;

 inherited;
end; (* TForm1.WndProc *)

Let's "read" our WndProc method's code:

  1. Look for any WM_NOTIFY messages
  2. See if the notification has the EN_LINK code, if so the lParam of the message will be a pointer to a TENLink record.
  3. Examine the Msg value of the TENLink record to see if it is equal to WM_LBUTTONDOWN (left mouse button clicked)
  4. Send an EM_EXSETSEL message to the active RichEdit. The EM_EXSETSEL message selects a range of characters in a rich edit control. The number of character we are interested in (the range of characters that make up the link), is held in the chrg member of the TENLink record.
  5. Use the SelText method to get the string containing the URL.
  6. Call the ShellExecute method to open up the default application for the URL (web browser, email client, ...)

Warning!
If the RichEdit is placed on a Panel component (for example) the code will not work?! The problem is that the message is being sent to the Panel, not the Form. Specifically, the message is sent to the RichEdit's parent. Since we are trying to catch the message from within the form (and not the RichEdit's Parent: the Panel), the message is never seen.
Here's the solution: TRichEditURL - hyperlink aware RichEdit.

That's it. If you have any questions please post to the Delphi Programming Forum. Of course, don't forget to download the sample source code.

~ Zarko Gajic

©2014 About.com. All rights reserved.