delphiurldelphi-12-athenstrichedit

Automatically convert email adresses to working hyperlinks in TRichEdit?


TRichEdit has the properties: EnableURLs and ShowURLHint. EnableURLs automatically converts Internet URLs like e.g. http://www.example.com to hyperlinks.

With the code below, I tried to achieve the same functionality with email addresses. This works only visually:

screenshot of email hyperlink

Question: But how can I automatically achieve the name@somewhere.com hyperlink functionality (crHandPoint cursor and OnURLClick event handler) when clicking on the email address?

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    Label1: TLabel;
    procedure RichEdit1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  System.RegularExpressions;

procedure DetectAndLinkifyEmailsAndURLs(RichEdit: Vcl.ComCtrls.TRichEdit);
var
  Match: System.RegularExpressions.TMatch;
  EmailPattern, URLPattern: string;
  LineIndex, LineStart, StartPos, SelLength: Integer;
  LineText: string;
  PrevSelStart, PrevSelLength: Integer;
begin
  EmailPattern := '\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b';
  URLPattern := '\b(http|https)://[^\s]+';

  // Disable redraw to avoid flicker
  SendMessage(RichEdit.Handle, WM_SETREDRAW, WPARAM(False), 0);

  try
    // Save user selection
    PrevSelStart := RichEdit.SelStart;
    PrevSelLength := RichEdit.SelLength;

    // Reset all formatting to default for the entire text
    RichEdit.SelectAll;
    RichEdit.SelAttributes.Color := Vcl.Graphics.clWindowText;
    RichEdit.SelAttributes.Style := [];

    // Process line by line
    for LineIndex := 0 to RichEdit.Lines.Count - 1 do
    begin
      LineText := RichEdit.Lines[LineIndex];
      LineStart := RichEdit.Perform(EM_LINEINDEX, LineIndex, 0); // Get line start position

      // Format email addresses in the line
      Match := System.RegularExpressions.TRegEx.Match(LineText, EmailPattern, [System.RegularExpressions.roIgnoreCase]);
      while Match.Success do
      begin
        StartPos := LineStart + Match.Index - 1;
        SelLength := Match.Length;

        RichEdit.SelStart := StartPos;
        RichEdit.SelLength := SelLength;
        RichEdit.SelAttributes.Color := Vcl.Graphics.clBlue;
        RichEdit.SelAttributes.Style := [Vcl.Graphics.fsUnderline];

        Match := Match.NextMatch;
      end;

      // Format URLs in the line
      Match := System.RegularExpressions.TRegEx.Match(LineText, URLPattern, [System.RegularExpressions.roIgnoreCase]);
      while Match.Success do
      begin
        StartPos := LineStart + Match.Index - 1;
        SelLength := Match.Length;

        RichEdit.SelStart := StartPos;
        RichEdit.SelLength := SelLength;
        RichEdit.SelAttributes.Color := Vcl.Graphics.clBlue;
        RichEdit.SelAttributes.Style := [Vcl.Graphics.fsUnderline];

        Match := Match.NextMatch;
      end;
    end;

    // Restore user selection
    RichEdit.SelStart := PrevSelStart;
    RichEdit.SelLength := PrevSelLength;

    // Ensure the current selection uses default formatting
    if (PrevSelStart >= 0) and (PrevSelLength = 0) then
    begin
      RichEdit.SelAttributes.Color := Vcl.Graphics.clWindowText;
      RichEdit.SelAttributes.Style := [];
    end;
  finally
    // Re-enable redraw
    SendMessage(RichEdit.Handle, WM_SETREDRAW, WPARAM(True), 0);
    RichEdit.Invalidate; // Refresh to reflect changes
  end;
end;

procedure TForm1.RichEdit1Click(Sender: TObject);
begin
  DetectAndLinkifyEmailsAndURLs(RichEdit1);
end;

end.

Solution

  • The Auto URL Detection feature supports email addresses. You can simply prefix them with the mailto: url scheme.

    If you don't want to do that, then on Windows 8 and later, you can manually send an EM_AUTOURLDETECT message to the TRichEdit window, specifying the AURL_ENABLEEMAILADDR flag in the wParam parameter.

    Otherwise, you will have to enable the hyperlinks manually. Select the desired text and apply the CFE_LINK format style to it, which you can do via the TRichEdit.SelAttributes.Link property (if your Delphi version supports that) or the EM_SETCHARFORMAT message.