Recent

Author Topic: [SOLVED] TRichMemo and text colour  (Read 4606 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 8141
[SOLVED] TRichMemo and text colour
« on: May 20, 2024, 05:18:52 pm »
I know that this is a bit of an FAQ, but I'm trying to strip things down to the bare minimum without any frills.

I have a TRichMemo set read-only, and am adding logging-style text to the end of its Lines property. All added text will be an entire paragraph followed by a blank line, I will never be adding a partial line or attempting to append to an existing one.

In order to conserve resources and maximise performance, I am periodically deleting entire lines from the start of the Lines property.

The user can scroll the display, but not manipulate the content.

What is the most-straightforward way of saying, at the point in the code where lines are being added, "set the colour to clSomething" such that the colour stays with the text even though lines above it are being deleted?

MarkMLl
« Last Edit: June 07, 2024, 01:08:29 pm by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 8141
Re: TRichMemo and text colour
« Reply #1 on: May 23, 2024, 10:00:51 am »
On Linux this works without further correction for the number of lines etc.:

Code: Pascal  [Select][+][-]
  1. function CurtailedAppend(lines: TStrings; const line: ansistring; var caret: TPoint;
  2.                 blockText: boolean= false; limit: integer= CurtailLimit; slop: integer= -1): integer;
  3.  
  4. begin
  5.   result := 0;
  6.   lines.Append(line)
  7. end { CurtailedAppend } ;
  8.  
  9. ...
  10.  
  11. (* Output a single line.
  12. *)
  13. procedure TFrameInfield.PaneAppend(const line: ansistring; colour: TColor= clDefault);
  14.  
  15. const
  16.   hasBeenVisible: boolean= false;       (* Static variable                      *)
  17.  
  18. var
  19.   caret: TPoint;
  20.   lengthBeforeAppend, deletedByAppend: integer;
  21.  
  22. begin
  23.   lengthBeforeAppend := Length(RichMemoInfield.Lines.Text);
  24.   deletedByAppend := CurtailedAppend(RichMemoInfield.Lines, line, caret, true);
  25.   lengthBeforeAppend -= deletedByAppend;
  26.  
  27. (* CurtailedAppend() returns the number of characters deleted (is any) from the *)
  28. (* start of the TMemo or TRichMemo. This is used to adjust the start point of   *)
  29. (* the range to be coloured.                                                    *)
  30.  
  31.   if colour <> clDefault then
  32.  
  33. // https://wiki.freepascal.org/RichMemo?#Append_mixed_color_text_at_the_end_of_the_RichMemo
  34. // This will go wrong if any lines were deleted.
  35.  
  36. {
  37. SetRangeColor(Length(Lines.Text) - Length(Lines[Lines.Count - 1]) - Lines.Count - 1, Length(Lines[Lines.Count - 1]), clBlue);
  38. }
  39.  
  40.     RichMemoInfield.SetRangeColor(lengthBeforeAppend, Length(line), colour);
  41.  
  42. end { TFrameInfield.PaneAppend } ;
  43.  

I've stripped down CurtailedAppend() there to only append a single line, under normal circumstances it would ensure that the total number of lines was less than some maximum by deleting stuff from the start and would make sure that the most-recent text remained visible.

CurtailedAppend() is tested thoroughly with a TMemo. With a TRichMemo appending text with a defined colour works OK, but it deletion is allowed something goes wrong with the colouration a few lines above the insertion point.

I'll provide more detail once I've stripped stuff down to a bare-bones test app.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: TRichMemo and text colour
« Reply #2 on: May 23, 2024, 11:11:18 am »
I guess I did not really understand what you try to do, adding colored lines into a richmemo, readonly, remove from time to time some lines by not change colors for other lines.
Okay, all above can be simple done with those helpers:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.AddRichText(const ARichMemo: TRichMemo; const AText: string; const AFont: TFont; const ABackgroundColor: TColor);
  2. var
  3.   StartPos, EndPos: Integer;
  4.   FontParams: TFontParams;
  5. begin
  6.   StartPos := ARichMemo.SelStart;
  7.   EndPos := StartPos + Length(AText);
  8.  
  9.   FontParams.Color := AFont.Color;
  10.   FontParams.HasBkClr := True;
  11.   FontParams.BkColor := ABackgroundColor;
  12.   FontParams.Name := AFont.Name;
  13.   FontParams.Size := AFont.Size;
  14.   FontParams.Style := AFont.Style;
  15.   FontParams.VScriptPos := vpNormal;
  16.  
  17.   ARichMemo.Lines.BeginUpdate;
  18.   ARichMemo.SelText := AText;
  19.   ARichMemo.SelStart := StartPos;
  20.   ARichMemo.SelLength := EndPos - StartPos;
  21.   ARichMemo.SetTextAttributes(StartPos, EndPos - StartPos, FontParams);
  22.   ARichMemo.SelStart := EndPos;
  23.   ARichMemo.Lines.EndUpdate;
  24. end;
  25.  
  26. procedure TForm1.AddRichBreak(const ARichMemo: TRichMemo);
  27. begin
  28.   ARichMemo.Lines.BeginUpdate;
  29.   ARichMemo.SelText := LineEnding;
  30.   ARichMemo.SelStart := ARichMemo.SelStart + Length(ARichMemo.SelText);
  31.   ARichMemo.Lines.EndUpdate;
  32. end;
  33.  
  34. procedure TForm1.DelRichLine(const ARichMemo: TRichMemo; const ALineNumber: Integer);
  35. begin
  36.   if ALineNumber >= ARichMemo.Lines.Count then
  37.     Exit;
  38.   ARichMemo.Lines.BeginUpdate;
  39.   ARichMemo.Lines.Delete(ALineNumber);
  40.   ARichMemo.Lines.EndUpdate;
  41. end;

use "AddRichText()" to add text at wherever the caret is.
use "AddRichBreak()" to add a CRLF/linebreak wherever the caret is.
use "DelRichLine()" to delete a line, index 0 based for line #1.

Does that help?
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

cdbc

  • Hero Member
  • *****
  • Posts: 1787
    • http://www.cdbc.dk
Re: TRichMemo and text colour
« Reply #3 on: May 23, 2024, 11:43:00 am »
Hi
I think Mark is trying to maintain a colored 'viewport', (scrolling as I understand it)...
I, for one, am following his progress  :)
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

paweld

  • Hero Member
  • *****
  • Posts: 1278
Re: TRichMemo and text colour
« Reply #4 on: May 23, 2024, 01:01:14 pm »
@MarkMLI: Or maybe a listbox + HTML is enough for you? see @wp's example in this thread: https://forum.lazarus.freepascal.org/index.php/topic,55971.msg416110.html#msg416110
Best regards / Pozdrawiam
paweld

MarkMLl

  • Hero Member
  • *****
  • Posts: 8141
Re: TRichMemo and text colour
« Reply #5 on: May 24, 2024, 09:04:49 am »
Hi
I think Mark is trying to maintain a colored 'viewport', (scrolling as I understand it)...
I, for one, am following his progress  :)
Regards Benny

No, I'm trying to append coloured text that stays coloured from that point onwards (i.e. "henceforth") irrespective of scrolling etc. In effect, it's a "default for all new text" rather than the existing "default for everything".

From what I can see, there is no provision to do that. However my code that appends and then colours does appear to work- /unless/ there is subsequent deletion from the start of the text as shown in the partial screenshot of alternating-colour blocks with a colour change after deletion has started.

I'll append a demo program in a day or so when I've had time to chop things down a bit.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: TRichMemo and text colour
« Reply #6 on: May 24, 2024, 10:25:05 am »
No, I'm trying to append coloured text that stays coloured from that point onwards (i.e. "henceforth") irrespective of scrolling etc. In effect, it's a "default for all new text" rather than the existing "default for everything".
Sweet, I've understood your initial post :D
From what I can see, there is no provision to do that.
Sure there is, I've posted the methods that do exact what you want.  O:-)
Maybe exchange the "string" with a better suiting one, eg TStrings/TStringList etc ...
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

MarkMLl

  • Hero Member
  • *****
  • Posts: 8141
Re: TRichMemo and text colour
« Reply #7 on: May 24, 2024, 11:46:56 am »
Sure there is, I've posted the methods that do exact what you want.  O:-)
Maybe exchange the "string" with a better suiting one, eg TStrings/TStringList etc ...

Not in there /as/ /standard/ then. I'll check that out when I have time, thanks.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 8141
Re: TRichMemo and text colour
« Reply #8 on: June 01, 2024, 09:39:24 am »
Not in there /as/ /standard/ then. I'll check that out when I have time, thanks.

So what do I have to do to get that example to actually generate output? AddRichText() appears to be having no effect whatsoever.

Test program attached.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 8141
Re: TRichMemo and text colour
« Reply #9 on: June 01, 2024, 09:07:05 pm »
I've tracked down my problem: when I was deleting a line at the start of the memo I was adding  Length(Lines[0])  to the number of characters I was reporting deleted, when I should have been adding  Length(Lines[0]) + 1  to allow for an internal EOL marker. The fact that an entire line was appearing with the wrong colour was an unfortunate coincidence.

I've now got a single function which handles length management of either a TMemo or TRichMemo, with the final line kept in view which is what would be expected for debugging etc. output:

Code: Pascal  [Select][+][-]
  1. const
  2.   CurtailLimit= 256;                    (* Default limit and slop               *)
  3.   CurtailSlop= 32;                      (* This is a fraction since +ve         *)
  4.  
  5. var
  6.   CurtailedMemoFteTimeout: integer= 90; (* Seconds                              *)
  7.  
  8.  
  9. (* This is typically used to keep the total number of lines in a TMemo etc.
  10.   below some limit, so that the resources it consumes do not start to impose a
  11.   bottleneck; this should also be called regularly (say every minute) without a
  12.   lines parameter to update an internal counter. The return value is the number
  13.   of characters deleted, including line-ends.
  14.  
  15.   If the blockText parameter is false then deletion is of individual lines at
  16.   the start of the memo, otherwise it continues until it reaches a blank line
  17.   assumed to indicate the end of a block or paragraph which is also deleted. If
  18.   hasBeenVisible is false no attempt is made to save and restore the caret
  19.   position, avoiding the penalty of handling an internal exception if text is
  20.   being sent to a form known to be hidden.
  21.  
  22.   If the slop parameter is +ve then it indicates the fraction by which the size
  23.   is allowed to "hunt" around the limit; +1 is a special case indicating that
  24.   there should be no deletion. If the slop parameter is -ve then it is a number
  25.   of lines rather than a fraction; -1 is a special case indicating a default.
  26. *)
  27. function CurtailedAppend(const memo: TCustomMemo; const line: ansistring= #$7f;
  28.                 blockText: boolean= false; hasBeenVisible: boolean= true;
  29.                 limit: longword= CurtailLimit; slop: integer= -1): integer;
  30.  
  31. {$define USE_TAG_FOR_TIMEOUT }
  32.  
  33. const
  34.   ZeroPt: TPoint= (X: 0; Y: 0);
  35.  
  36. var
  37.   caret: TPoint;
  38.   trimmedLines, halfSlop: integer;
  39.   forceToEnd: boolean= false;
  40.  
  41. {$ifdef USE_TAG_FOR_TIMEOUT }
  42.  
  43.   procedure setTimer(t: longword);
  44.  
  45.   begin
  46.     if t = 0 then
  47.       memo.Tag := 0                     (* Zero/nil is valid                    *)
  48.     else
  49.       memo.Tag := ptruint(t << 1) or 1  (* Otherwise must not look like pointer *)
  50.   end { setTimer } ;
  51.  
  52.  
  53.   function getTimer(): longword;
  54.  
  55.   begin
  56.     result := longword(memo.Tag >> 1)
  57.   end { getTimer } ;
  58.  
  59. {$else                      }
  60.  
  61. (* Do not declare a static variable for the force-to-end timer if this will be  *)
  62. (* called in the context of more than one memo.                                 *)
  63.  
  64. //  timer: qword= 0;                      (* Static variable                      *)
  65.  
  66.  
  67.   procedure setTimer(t: longword);
  68.  
  69.   begin
  70.   {$if declared(timer) }
  71.     timer := t
  72.   {$endif              }
  73.   end { setTimer } ;
  74.  
  75.  
  76.   function getTimer(): longword;
  77.  
  78.   begin
  79.   {$if declared(timer) }
  80.     result := timer
  81.   {$else               }
  82.     result := 0
  83.   {$endif              }
  84.   end { getTimer } ;
  85.  
  86. {$endif                     }
  87.  
  88. begin
  89.   result := 0;
  90.   memo.Lines.BeginUpdate;
  91.   try
  92.  
  93. (* Save caret position on entry, with special provision for a hidden pane to    *)
  94. (* avoid a "GetCaretPos called without handle" error.                           *)
  95.  
  96.     if hasBeenVisible then
  97.       try
  98.         caret := memo.CaretPos
  99.       except
  100.         caret := zeroPt
  101.       end
  102.     else
  103.       caret := zeroPt;
  104.  
  105. (* Initialise the slop and/or limit where not explicitly specified. Slop values *)
  106. (* of -1 and +1 are chosen to indicate the default and no-deletion cases since  *)
  107. (* (-1 div 2) lines is zero and (limit / +1) would result in no retained output *)
  108. (* which makes these parameter values redundant.                                *)
  109.  
  110.     case Sign(slop) of
  111.       -1: if slop = -1 then
  112.             halfSlop := (limit div CurtailSlop) div 2
  113.           else
  114.             halfSlop := -slop div 2;    (* Slop was number of lines             *)
  115.        0: halfSlop := 0;
  116.        1: halfSlop := (limit div slop) div 2 (* Slop was denominator            *)
  117.      end;
  118.  
  119. (* If the cursor (as distinct from scrollbar) has been placed at some position  *)
  120. (* other that the end of the displayed text then there will not be an automatic *)
  121. (* jump to the end as soon as more output arrives. However this is subject to a *)
  122. (* timeout so that if the operator is not actively investigating older messages *)
  123. (* the memo reverts to a state where it is the newer ones that are displayed.   *)
  124.  
  125.     trimmedLines := memo.Lines.Count;   (* Visible for debugging                *)
  126.     forceToEnd := not (caret.Y < trimmedLines - 1);
  127.     if (not forceToEnd) and (getTimer() = 0) then
  128.       setTimer(UnixNow);
  129.     trimmedLines := 0;
  130.     try
  131.  
  132. (* If the line contains (only) a <Del> character then this is a dummy operation *)
  133. (* (typically invoked by a timer) with the intention of reverting to the end if *)
  134. (* the timeout has expired. In practice, don't delete any lines from the start  *)
  135. (* if the user has scrolled up and is trying to read stuff.                     *)
  136.  
  137.       if line <> #$7f then begin
  138.         if getTimer() = 0 then begin
  139.           if (slop <> 1) and (memo.Lines.Count > limit + halfSlop) then begin
  140.             while memo.Lines.Count > limit - halfSlop do begin
  141.               result += memo.Lines[0].Length + 1;
  142.               memo.Lines.Delete(0);
  143.               trimmedLines += 1;
  144.               if caret.Y > 0 then
  145.                 caret.Y -= 1
  146.             end;
  147.  
  148. (* If that's left us on a non-blank line then advance to the next blank line,   *)
  149. (* then one more to get rid of that as well.                                    *)
  150.  
  151.             if blockText then begin
  152.               while (memo.Lines.Count > 0) and (memo.Lines[0] <> '') do begin
  153.                 result += memo.Lines[0].Length + 1;
  154.                 memo.Lines.Delete(0);
  155.                 trimmedLines += 1;
  156.                 if caret.Y > 0 then
  157.                   caret.Y -= 1
  158.               end;
  159.               if (memo.Lines.Count > 0) and (memo.Lines[0] = '') then begin
  160.                 result += memo.Lines[0].Length + 1;
  161.                 memo.Lines.Delete(0);
  162.                 trimmedLines += 1;
  163.                 if caret.Y > 0 then
  164.                   caret.Y -= 1
  165.               end
  166.             end
  167.           end
  168.         end;
  169.  
  170. (* Scrolling etc. behaviour above and in finally block below largely cribbed    *)
  171. (* from WatchP0x via PSTalk.                                                    *)
  172.  
  173.         memo.Lines.Append(line)
  174.       end
  175.     finally
  176.       if forceToEnd or (UnixNow() - getTimer() > CurtailedMemoFteTimeout) then begin
  177.         if memo.Lines.Count > 0 then begin
  178.           caret.Y := memo.Lines.Count - 1;
  179.           caret.X := 0
  180.         end;
  181.         setTimer(0)
  182.       end
  183.     end;
  184.  
  185. (* Restore caret position on exit, with special provision for a hidden pane to  *)
  186. (* avoid the overhead of a "GetCaretPos called without handle" exception.       *)
  187.  
  188.     if hasBeenVisible then
  189.       try
  190.         memo.CaretPos := caret
  191.       except
  192.       end
  193.   finally
  194.     memo.Lines.EndUpdate
  195.   end
  196. end { CurtailedAppend } ;
  197.  

For a TMemo it can be called like this:

Code: Pascal  [Select][+][-]
  1. (* Output a single line.
  2. *)
  3. procedure TFrameOutfield.PaneAppend(const line: ansistring);
  4.  
  5. begin
  6.   CurtailedAppend(MemoOutfield, line, true)
  7. end { TFrameOutfield.PaneAppend } ;
  8.  

while the code for a TRichMemo is only slightly more complex:

Code: Pascal  [Select][+][-]
  1. (* Output a single line.
  2. *)
  3. procedure TFrameInfield.PaneAppend(const line: ansistring; colour: TColor= clDefault);
  4.  
  5. var
  6.   existingTextLength: integer;
  7.  
  8. begin
  9.   existingTextLength := Length(RichMemoInfield.Lines.Text);
  10.   existingTextLength -= CurtailedAppend(RichMemoInfield, line, true);
  11.  
  12. (* CurtailedAppend() returns the number of characters deleted (if any) from the *)
  13. (* start of the TMemo or TRichMemo. This is used to adjust the start point of   *)
  14. (* the range to be coloured.                                                    *)
  15.  
  16.   if colour <> clDefault then
  17.     RichMemoInfield.SetRangeColor(existingTextLength, Length(line), colour)
  18. end { TFrameInfield.PaneAppend } ;
  19.  

Performance is sufficiently good that I've not investigated appending a block as a single operation. It should be easy enough with CurtailedAppend() called only for the final line, with suitable consideration of the length parameter (the example above doesn't colour the EOL, which might slow line addition down but OTOH might speed deletion up).

Hoping that is useful to somebody.

MarkMLl
« Last Edit: August 20, 2024, 09:33:08 am by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

cdbc

  • Hero Member
  • *****
  • Posts: 1787
    • http://www.cdbc.dk
Re: TRichMemo and text colour
« Reply #10 on: June 02, 2024, 02:48:24 am »
Hi
Nice, good on you Mark.
Quote
Hoping that is useful to somebody.
It is, Thanks  :)
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

MarkMLl

  • Hero Member
  • *****
  • Posts: 8141
Re: TRichMemo and text colour
« Reply #11 on: June 05, 2024, 09:19:18 am »
I've edited that example function I provided with a couple more internal error checks, and to use the memo's .Tag property for a seconds timeout so that if the user has scrolled (and set the cursor) to look at an older message it will revert to displaying newly-appended messages after 2:30. That originally used a static variable (initialised constant), but that's obviously NBG if multiple memos are being used.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

cdbc

  • Hero Member
  • *****
  • Posts: 1787
    • http://www.cdbc.dk
Re: TRichMemo and text colour
« Reply #12 on: June 05, 2024, 10:07:49 am »
Hi
Nifty little solution, Me Likey  ;)
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

MarkMLl

  • Hero Member
  • *****
  • Posts: 8141
Re: TRichMemo and text colour
« Reply #13 on: June 07, 2024, 01:07:53 pm »
Hi
Nifty little solution, Me Likey  ;)
Regards Benny

It appears that system colours like clGrayText can't be used in this context, although that might depend on the widget set.

I've added a term to force the tag's LSB to 1 which will reduce the risk it could be confused with a reference to an object.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

CM630

  • Hero Member
  • *****
  • Posts: 1224
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: [SOLVED] TRichMemo and text colour
« Reply #14 on: December 13, 2024, 08:18:36 am »
I tried to modify AddRichText.
I have an issue with ABackgroundColour = clDefault - I cannot get the actual colour of the RichMemo.
The ARichMemo.Colour returns clDefault.
I tried with Brush, etc, I still do not get the actual background colour of the RichMemo. Any ideas?

Code: Pascal  [Select][+][-]
  1. procedure AddRichText(ARichMemo: TRichMemo; const AText: string; const AForegroundColour: TColor = clDefault; const ABackgroundColour: TColor = clDefault);
  2. var
  3.   StartPos, EndPos: Integer;
  4.   FontParams: TFontParams;
  5. begin
  6.   StartPos := ARichMemo.SelStart;
  7.   EndPos := StartPos + Length(AText);
  8.  
  9.  
  10.   FontParams.Color := AForegroundColour;
  11.   FontParams.HasBkClr := True;
  12.   if ABackgroundColour = clDefault
  13.     then FontParams.BkColor := clWhite //I do not know how to handle this
  14.     else FontParams.BkColor := ABackgroundColour;
  15.   FontParams.Name := Graphics.GetFontData(ARichMemo.Font.Handle).Name;
  16.   FontParams.Size := Round((- Graphics.GetFontData(ARichMemo.Font.Handle).Height * 72 / ARichMemo.Font.PixelsPerInch));
  17.   FontParams.Style := Graphics.GetFontData(ARichMemo.Font.Handle).Style;
  18.   FontParams.VScriptPos := vpNormal;
  19.   ...
  20. end;
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

 

TinyPortal © 2005-2018