How to include the last word of hyperlink text in TRichEdit in the blue, underline format of the rest?

176 views Asked by At

I'm using a TRichEdit to edit text. I then use TJvRichEditToHtml to convert the text to HTML which then gets sent as the body of an email via Mailgun. I'd like to include hyperlinks in the text that gets emailed.

Following this SO post, and several other similar ones, I included the code below to insert a formatted hyperlink in the TRichEdit at the insertion point. As expected, that hides the URL and shows the link text as blue, underlined text just as I wanted. i.e. if I insert the url https://stackoverflow.com, with the text this is a link, the HTML will contain HYPERLINK "https://stackoverflow.com/"this is a link and the Rich text box shows this is a link all in blue and underlined.

Just before sending the body to Mailgun I then substitute HYPERLINK &quot; with <a href=" and &quot; with " to get the html <a href="https://stackoverflow.com/">this is a link

To identify the end of the link text, so that I can substitute </a> and close the html hyperlink properly, I added code to append a hidden text token ENDHYPERLINK after the hypertext link in the TRich edit which I then substitute for </a>. ie the html before substitution look like HYPERLINK &quot;https://stackoverflow.com/&quot;this is a link ENDHYPERLINKand after substitution looks like <a href="https://stackoverflow.com/">this is a link</a>

However, when I add this extra text after the hyperlink, although it is correctly invisible in the TRichEdit, the blue underlining of the link text in the TRichEdit shrinks back so that the last word of the hyperlink text is no longer formatted in blue underline (no matter how long the hyperlink text is or how long the last word is) i.e I get this is a and the space char in blue and underlined but not the word link

Can someone help me to append my ending token but still get all of the original hyperlink text shown formatted?

Code used to insert the hyperlink - before adding my ending token - this displays OK.

procedure TForm1.InsertHyperLink(const HyperlinkText, HyperlinkURL: string);

var
  HyperlinkPrefix, FullHyperlink: string;
  Fmt: CHARFORMAT2;
  StartPos: Integer;

  begin
  if HyperlinkURL <> '' then
    begin
    HyperlinkPrefix := Format('HYPERLINK "%s"', [HyperlinkURL]);
    FullHyperlink := HyperlinkPrefix + HyperlinkText;
    end
  else
    begin
    FullHyperlink := HyperlinkText;
    end;

  StartPos := RichEdit1.SelStart;
  RichEdit1.SelText := FullHyperlink;
  RichEdit1.SelStart := StartPos;
  RichEdit1.SelLength := Length(FullHyperlink) ;
  FillChar(Fmt, SizeOf(Fmt), 0);
  Fmt.cbSize := SizeOf(Fmt);
  Fmt.dwMask := CFM_LINK;
  Fmt.dwEffects := CFE_LINK;

  SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));

  if HyperlinkURL <> '' then
    begin
    RichEdit1.SelStart := StartPos ;
    RichEdit1.SelLength := Length(HyperlinkPrefix);
    FillChar(Fmt, SizeOf(Fmt), 0);
    Fmt.cbSize := SizeOf(Fmt);
    Fmt.dwMask := CFM_HIDDEN;
    Fmt.dwEffects := CFE_HIDDEN;
    SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));
    end;

  RichEdit1.SelStart := StartPos + Length(FullHyperlink) ;
  RichEdit1.SelLength := 0;

end;

Code used to insert the hyperlink but also append a closing token - this loses formatting of the last word in the link text.

procedure TForm1.InsertHyperLink(const HyperlinkText, HyperlinkURL: string);

const
  TOKEN_LINK_END = ' ENDHYPERLINK';

var
  HyperlinkPrefix, FullHyperlink: string;
  Fmt: CHARFORMAT2;
  StartPos: Integer;

  begin
  if HyperlinkURL <> '' then
    begin
    HyperlinkPrefix := Format('HYPERLINK "%s"', [HyperlinkURL]);
    FullHyperlink := HyperlinkPrefix + HyperlinkText;
    end
  else
    begin
    FullHyperlink := HyperlinkText;
    end;

  StartPos := RichEdit1.SelStart;
  RichEdit1.SelText := FullHyperlink;
  RichEdit1.SelStart := StartPos;
  RichEdit1.SelLength := Length(FullHyperlink) ;
  FillChar(Fmt, SizeOf(Fmt), 0);
  Fmt.cbSize := SizeOf(Fmt);
  Fmt.dwMask := CFM_LINK;
  Fmt.dwEffects := CFE_LINK;

  SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));

  if HyperlinkURL <> '' then
    begin
    RichEdit1.SelStart := StartPos ;
    RichEdit1.SelLength := Length(HyperlinkPrefix);
    FillChar(Fmt, SizeOf(Fmt), 0);
    Fmt.cbSize := SizeOf(Fmt);
    Fmt.dwMask := CFM_HIDDEN;
    Fmt.dwEffects := CFE_HIDDEN;
    SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));
    end;

  RichEdit1.SelStart := StartPos + Length(FullHyperlink) ;
  RichEdit1.SelLength := 0;

  ///////////////////////////////////////////////////////////////////////////////
  //  //now add closing token as hidden text
  ///////////////////////////////////////////////////////////////////////////////
  StartPos := RichEdit1.SelStart ;
  RichEdit1.SelText := TOKEN_LINK_END;
  RichEdit1.SelStart := StartPos;
  RichEdit1.SelLength := Length(TOKEN_LINK_END);

  FillChar(Fmt, SizeOf(Fmt), 0);
  Fmt.cbSize := SizeOf(Fmt);
  Fmt.dwMask := CFM_HIDDEN;
  Fmt.dwEffects := CFE_HIDDEN;

  SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));
end;

Note This question is not about being able to click the links in the TRichEdit and get sent to the web site, so is not a duplicate of many others (Although I have written the code to do this by overriding WndProc, which works OK even though my last word is not shown formatted correctly)

0

There are 0 answers