Search code examples
firemonkeytmemo

Changing the background color behind a selected substring in a Firemonkey TMemo component


I wish to programmatically set focus on a particular substring in a (Delphi 10.3.1) Firemonkey TMemo component, by painting a yellow background behind the substring. The code below paints a yellow rectangle in the right position, but the rectangle appears to be superimposed over the text, thereby hiding it. Is there some TMemo property that can be used to avoid this? If not, what is the recommended fix?

procedure TTextGUIMemo.SetFocusOnHit(HitIndex: integer);
var
  LineIndex: integer;
  GlobalHitInterval: TIntegerArray2;
begin
  FFileCptHitsExpd.FileCptHits.GetHitSubstringGlobal(HitIndex, {=>}LineIndex,
                GlobalHitInterval);
  FMemo.SetFocus;
  FMemo.SelStart:= GlobalHitInterval[0];
  FMemo.SelLength:= GlobalHitInterval[1];
  FMemo.SelectionFill.Color := TAlphaColorRec.Yellow; 
  FMemo.FontColor:= TAlphaColorRec.Black;
  FMemo.Repaint;
end;

Thank you in advance for any suggestions.


Solution

  • Looking at (XE7) FMX.Memo.pas procedure TMemo.DoContentPaint() one might think the order of drawing is wrong. On the other hand it might be intentional, maybe I just don't get it why.

    First the text is drawn, then the selection and finally spell highlighting. The standard selection color is $7F3399FF. Note the alpha channel (7F). This makes it half transparent and therefore the text shows through, even though the selection color is drawn over the text.

    enter image description here

    The solution for your issue is therefore to define the color to be partly transparent, f.ex.:

    FMemo.SelectionFill.Color := $7FFFFF00; // or perhaps even more transparent $4FFFFF00
    

    The effect of this is however, that the text is not black anymore (just as it isn't with the original selection color).

    enter image description here

    Testing with a copy of the FMX.Memo.pas file I rearranged the procedure TMemo.DoContentPaint() so that the code block marked with // selection comes before the // text block. In this case completely opaque color can be used for selection.

    FMemo.SelectionFill.Color := $FFFFFF00; // alpha = $FF
    

    enter image description here

    But never modify any file in the original Delphi installation directory(ies). Make a copy of the file in your project directory and modify that copy. The downside is that with new updated versions you might need to remember to copy and modify again.