HTML link in Richedit

Asked

Viewed 263 times

1

It would be possible to have a hyperlink in a word or phrase in a RichEdit, while hovering over this link the cursor looks like crHandPoint and by clicking, evidently open the browser with a specific website.
For example:
When you click here will open the Stackoverflow.

1 answer

3


It is possible yes, difficult to understand but easy to implement/modify.

I found a solution and I can detail some parts.

First we must create a proc to exchange messages with TRichEdit:

var
  vEvento: Word;
begin
  FWndProc := RichEdit.Parent.WindowProc;
  RichEdit.Parent.WindowProc := REditParentWndProc;

  vEvento := SendMessage(RichEdit.Handle, EM_GETEVENTMASK, 0, 0);
  SendMessage(RichEdit.Handle, EM_SETEVENTMASK, 0, vEvento or ENM_LINK);
  SendMessage(RichEdit.Handle, EM_AUTOURLDETECT, Integer(True), 0);

Here we would be informing the component to always update its screen when there are changes, responsible for this is the EM_GETEVENTMASK e EM_SETEVENTMASK. Then the EM_AUTOURLDETECT detect any URL that exists (here with a small improvement you can even type in the component and recognize it as a new url).

We create a List of Links to intercept at the moment of Click or mouse movement:

  vListaLinks := TStringList.Create;
  vListaLinks.Add('https://answall.com=https://answall.com');

  RichEdit.Text := vListaLinks.Names[0];

That’s what I meant before, here we already have a predefined Link, necessary a modification to detect new links.

It follows every day that will be responsible for the exchange of messages:

SeuForm = class(TForm)
...
private
  { Private declarations }
  FWndProc    : TWndMethod;
  vListaLinks : TStringList;
  procedure REditParentWndProc(var Message: TMessage);
end;

procedure REditParentWndProc(var Message: TMessage);
var
 i          : Integer;
 vLink      : TENLink;
 vUrl,
 vLinkFinal : String;
begin
  FWndProc(Message);

  if (Message.Msg = WM_NOTIFY) then
  begin
    if (PNMHDR(Message.LParam).code = EN_LINK) then
    begin
      vLink := TENLink(Pointer(TWMNotify(Message).NMHdr)^);

      if (vLink.msg = WM_LBUTTONDOWN) then
      begin
         SendMessage(RichEdit.Handle, EM_EXSETSEL, 0, LongInt(@(vLink.chrg)));
         vUrl := RichEdit.SelText;

         if (vListaLinks.Count > 0) then
         begin
           for i:= 0 to Pred(vListaLinks.Count) do
           begin
             if vListaLinks.Names[i] = vUrl then begin
                vLinkFinal := vListaLinks.ValueFromIndex[i];
                Break;
             end
             else
             begin
               vLinkFinal := vUrl;
             end;
           end;
         end;

         ShellExecute(Handle, 'open', PChar(vLinkFinal), 0, 0, SW_SHOWNORMAL);
         RichEdit.SelStart := 0;
      end
    end
  end;
end;

Source

Browser other questions tagged

You are not signed in. Login or sign up in order to post.