HTML Link in RichEdit

1

It would be possible to have a hyperlink in a word or phrase in a RichEdit , and when you hover over that link the cursor stays as crHandPoint and when you click, with a specific website.
For example:
Clicking here will open the StackOverFlow .

    
asked by anonymous 04.04.2018 / 19:10

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 so that it always updates its screen when there are changes, responsible for this is EM_GETEVENTMASK e EM_SETEVENTMASK . Then% w /% will detect all URLs that exist (here with a little improvement you can even type in the component and it will recognize it as a new url).

We created a list of links to intercept at the time of Click or mouse movement:

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

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

That's what I meant before, here we already have a pre-defined link, a modification is needed for it to detect new links.

Following is the procedure 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;

Font

    
04.04.2018 / 20:01