Recent

Author Topic: [Solved] Possible to set next characters background/foreground Windows RichEdit?  (Read 641 times)

ozznixon

  • Full Member
  • ***
  • Posts: 117
    • http://www.modernpascal.com/

Basically, I am trying to do things like, set bgcolor to Blue, and fgcolor to Yellow, then add the next character from the file to the screen. Thus, allowing me to render ANSI text files to GUI, then I will snapshop the Canvas to PNG. (Delphi7 Application)


Can someone help with how to preset the background/foreground color before I append the next character? Below is the result of my last attempt - but it changes the whole line to clMaroon.


```
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
   Format:CharFormat2;
   Index,SizeOfFormat:Longint;
   Ws:String;


begin
  RichEdit1.Clear;
  RichEdit1.SelAttributes.Color := clAqua;
//  RichEdit1.SelAttributes.Style := [fsBold];
  RichEdit1.SelText := '32bit GUI ';
  RichEdit1.SelAttributes.Color := clYellow;
  RichEdit1.SelText := 'A';
  RichEdit1.SelAttributes.Color := clRed;
  RichEdit1.SelText := 'N';
  RichEdit1.SelAttributes.Color := clWhite;
  RichEdit1.SelText := 'S';
  RichEdit1.SelAttributes.Color := clLime;
  RichEdit1.SelText := 'I ';
  RichEdit1.SelAttributes.Color := clAqua;
  RichEdit1.SelText := 'Terminal';
  RichEdit1.SelAttributes.Color := clRed;
  RichEdit1.SelAttributes.Style := [fsItalic];
  // try to turn on clMaroon background for this next string
  // however, ends up changing whole line to clMaroon. I actually
  // need to achieve this character by character...
  Ws:=#32'(c) 2023 by Ozz Nixon';
  Index:=Length(RichEdit1.Lines.Text);
  RichEdit1.SelStart  := Index;
  RichEdit1.SelLength := Length(Ws);
  RichEdit1.SelText := Ws;
  SizeOfFormat:=SizeOf(Format);
  FillChar(Format, SizeOfFormat, 0);
  Format.cbSize := SizeOfFormat;
  Format.dwMask := CFM_BACKCOLOR;
  Format.crBackColor := clMaroon;
  RichEdit1.Perform(EM_SETCHARFORMAT, $0004 {SCF_SELECTION}, Longint(@Format));
end;
```
« Last Edit: April 14, 2023, 05:14:10 am by ozznixon »
---
Want to kick the tires to a Free Pascal like script engine? http://www.ModernPascal.com/

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1197
    • Lebeau Software
Can someone help with how to preset the background/foreground color before I append the next character? Below is the result of my last attempt - but it changes the whole line to clMaroon.

You are on the right track.

However, you are setting the WPARAM parameter of EM_SETCHARFORMAT to $0004 (aka SCF_ALL) when you should be setting it to $0001 (aka SCF_SELECTION) instead.

Also, make sure you are setting up the correct selection before you change the background color.  For instance, make sure that Length(RichEdit1.Lines.Text) is not returning 0 unexpectedly.  Try using RichEdit1.GetTextLen() instead.

Also, since you are trying to place the SelStart at the end of the text, you should be setting the SelLength to 0 instead of Length(Ws), and that you set the background color before you assign the SelText rather than after, like you do with the other attributes.

Try this:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.SpeedButton1Click(Sender: TObject);
  2. var
  3.   Format: CharFormat2;
  4. begin
  5.   RichEdit1.Clear;
  6.  
  7.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  8.   RichEdit1.SelLength := 0;
  9.   RichEdit1.SelAttributes.Color := clAqua;
  10.   //RichEdit1.SelAttributes.Style := [fsBold];
  11.   RichEdit1.SelText := '32bit GUI';
  12.  
  13.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  14.   RichEdit1.SelLength := 0;
  15.   RichEdit1.SelAttributes.Color := clWindowText;
  16.   //RichEdit1.SelAttributes.Style := [];
  17.   RichEdit1.SelText := ' ';
  18.  
  19.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  20.   RichEdit1.SelLength := 0;
  21.   RichEdit1.SelAttributes.Color := clYellow;
  22.   RichEdit1.SelText := 'A';
  23.  
  24.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  25.   RichEdit1.SelLength := 0;
  26.   RichEdit1.SelAttributes.Color := clRed;
  27.   RichEdit1.SelText := 'N';
  28.  
  29.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  30.   RichEdit1.SelLength := 0;
  31.   RichEdit1.SelAttributes.Color := clWhite;
  32.   RichEdit1.SelText := 'S';
  33.  
  34.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  35.   RichEdit1.SelLength := 0;
  36.   RichEdit1.SelAttributes.Color := clLime;
  37.   RichEdit1.SelText := 'I';
  38.  
  39.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  40.   RichEdit1.SelLength := 0;
  41.   RichEdit1.SelAttributes.Color := clWindowText;
  42.   RichEdit1.SelText := ' ';
  43.  
  44.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  45.   RichEdit1.SelLength := 0;
  46.   RichEdit1.SelAttributes.Color := clAqua;
  47.   RichEdit1.SelText := 'Terminal';
  48.  
  49.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  50.   RichEdit1.SelLength := 0;
  51.   RichEdit1.SelAttributes.Color := clWindowText;
  52.   RichEdit1.SelText := ' ';
  53.  
  54.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  55.   RichEdit1.SelLength := 0;
  56.   RichEdit1.SelAttributes.Color := clRed;
  57.   RichEdit1.SelAttributes.Style := [fsItalic];
  58.   FillChar(Format, SizeOf(Format), 0);
  59.   Format.cbSize := SizeOf(Format);
  60.   Format.dwMask := CFM_BACKCOLOR;
  61.   Format.crBackColor := clMaroon;
  62.   RichEdit1.Perform(EM_SETCHARFORMAT, WPARAM(SCF_SELECTION), LPARAM(@Format));
  63.   RichEdit1.SelText := '(c) 2023 by Ozz Nixon';
  64.  
  65.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  66.   RichEdit1.SelLength := 0;
  67. end;

I would suggest then taking that a step further by wrapping the repeated code into a helper procedure, eg:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.SpeedButton1Click(Sender: TObject);
  2.  
  3.   procedure AppendText(const S: string; TextColor: TColor = clWindowText; Style: TFontStyles = []; BackColor: TColor = clWindow);
  4.   var
  5.     CharRange: TCharRange;
  6.     Format: CharFormat2;
  7.   begin
  8.     // RichEdit1.SelStart := RichEdit1.GetTextLen();
  9.     // RichEdit1.SelLength := 0;
  10.     CharRange.cpMin := RichEdit1.GetTextLen();
  11.     CharRange.cpMax := CharRange.cpMin + 0;
  12.     RichEdit1.Perform(EM_EXSETSEL, 0, LPARAM(@CharRange));
  13.     //RichEdit1.Perform(EM_SCROLLCARET, 0, 0);
  14.  
  15.     FillChar(Format, SizeOf(Format), 0);
  16.     Format.cbSize := SizeOf(Format);
  17.  
  18.     //RichEdit1.SelAttributes.Color := TextColor;
  19.     Format.dwMask := Format.dwMask or CFM_COLOR;
  20.     if (TextColor = clWindowText) {$IFNDEF FPC}or (TextColor = clDefault){$ENDIF} then begin
  21.       Format.dwEffects := CFE_AUTOCOLOR;
  22.     end
  23.     else begin
  24.       {$IFDEF FPC}if TextColor = clDefault then TextColor := RichEdit1.GetDefaultColor(dctfont);{$ENDIF}
  25.       Format.crTextColor := ColorToRGB(TextColor);
  26.     end;
  27.  
  28.     //RichEdit1.SelAttributes.Style := Style;
  29.     Format.dwMask := Format.dwMask or CFM_BOLD or CFM_ITALIC or CFM_UNDERLINE or CFM_STRIKEOUT;
  30.     if fsBold in Style then Format.dwEffects := Format.dwEffects or CFE_BOLD;
  31.     if fsItalic in Style then Format.dwEffects := Format.dwEffects or CFE_ITALIC;
  32.     if fsUnderline in Style then Format.dwEffects := Format.dwEffects or CFE_UNDERLINE;
  33.     if fsStrikeOut in Style then Format.dwEffects := Format.dwEffects or CFE_STRIKEOUT;
  34.  
  35.     Format.dwMask := Format.dwMask or CFM_BACKCOLOR;
  36.     if (BackColor = clWindow) {$IFNDEF FPC}or (BackColor = clDefault){$ENDIF} then begin
  37.       Format.dwEffects := Format.dwEffects or CFE_AUTOBACKCOLOR;
  38.     end
  39.     else begin
  40.       {$IFDEF FPC}if BackColor = clDefault then BackColor := RichEdit1.GetDefaultColor(dctbrush);{$ENDIF}
  41.       Format.crBackColor := ColorToRGB(BackColor);
  42.     end;
  43.  
  44.     RichEdit1.Perform(EM_SETCHARFORMAT, WPARAM(SCF_SELECTION), LPARAM(@Format));
  45.  
  46.     RichEdit1.SelText := S;
  47.   end;
  48.  
  49. begin
  50.   RichEdit1.Clear;
  51.  
  52.   AppendText('32bit GUI', clAqua {, [fsBold]});
  53.   AppendText(' ');
  54.   AppendText('A', clYellow);
  55.   AppendText('N', clRed);
  56.   AppendText('S', clWhite);
  57.   AppendText('I', clLime);
  58.   AppendText(' ');
  59.   AppendText('Terminal', clAqua);
  60.   AppendText(' ');
  61.   AppendText('(c) 2023 by Ozz Nixon', clRed, [fsItalic], clMaroon);
  62.  
  63.   RichEdit1.SelStart := RichEdit1.GetTextLen();
  64.   RichEdit1.SelLength := 0;
  65. end;
« Last Edit: April 13, 2023, 07:09:29 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

ozznixon

  • Full Member
  • ***
  • Posts: 117
    • http://www.modernpascal.com/
Can someone help with how to preset the background/foreground color before I append the next character? Below is the result of my last attempt - but it changes the whole line to clMaroon.

You are on the right track.  Just make sure you are setting up the correct selection before you change the background color.  For instance, make sure that Length(RichEdit1.Lines.Text) is not returning 0 unexpectedly.  Try using RichEdit1.GetTextLen() instead.


Thank you Remy for your attempt. Neither work - copy your code right into my project, compile, run, and I get clMaroon as the background to the whole line. :-( - I will keep tinkering with your design to see if I can figure out why SelStart is always going to 0 (zero)...
---
Want to kick the tires to a Free Pascal like script engine? http://www.ModernPascal.com/

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1395
  • Fifty shades of code.
    • Delphi & FreePascal
There is one error in your code @Remy and because of that of course your code color all :P

change this
Code: Pascal  [Select][+][-]
  1. RichEdit1.Perform(EM_SETCHARFORMAT, $0004 {SCF_SELECTION}, Longint(@Format));
to that
Code: Pascal  [Select][+][-]
  1.   RichEdit1.Perform(EM_SETCHARFORMAT, WPARAM(SCF_SELECTION), LPARAM(@Format));

Quote
  SCF_SELECTION       = $0001;
  SCF_ALL             = $0004;

Now it prints like in attachment
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1395
  • Fifty shades of code.
    • Delphi & FreePascal
Code: Pascal  [Select][+][-]
  1.         TextColor := RichEdit1.GetDefaultColor(dctfont);
This method neither my Turbo Delphi 2006 nor my Delphi Alexandria does understand.
Can you explain it please?
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1197
    • Lebeau Software
There is one error in your code @Remy and because of that of course your code color all :P

Quote
  SCF_SELECTION       = $0001;
  SCF_ALL             = $0004;

Good catch. But that was an error in the original author's code.  I just didn't catch it, since I didn't look up the defined value of SCF_SELECTION.

I have updated my earlier code examples accordingly.
« Last Edit: April 13, 2023, 07:10:42 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1197
    • Lebeau Software
This method neither my Turbo Delphi 2006 nor my Delphi Alexandria does understand.

Correct, because TControl.GetDefaultColor() does not exist in Delphi, only in FreePascal.  This question was posted in a FreePascal forum, after all.  It should have posted in a Delphi forum instead.

Just ignore GetDefaultColor() in Delphi: eg:

Code: Pascal  [Select][+][-]
  1. ...
  2. //RichEdit1.SelAttributes.Color := TextColor;
  3. Format.dwMask := Format.dwMask or CFM_COLOR;
  4. if (TextColor = clWindowText) or (TextColor = clDefault) then begin
  5.   Format.dwEffects := CFE_AUTOCOLOR
  6. else
  7.   Format.crTextColor := ColorToRGB(TextColor);
  8.  
  9. ...
  10.  
  11. Format.dwMask := Format.dwMask or CFM_BACKCOLOR;
  12. if (BackColor = clWindow) or (BackColor = clDefault) then begin
  13.   Format.dwEffects := Format.dwEffects or CFE_AUTOBACKCOLOR
  14. else
  15.   Format.crBackColor := ColorToRGB(BackColor);

I have updated my earlier code examples accordingly.
« Last Edit: April 14, 2023, 06:43:23 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1395
  • Fifty shades of code.
    • Delphi & FreePascal
You did post this question in a FreePascal forum, after all.  You should have posted in a Delphi forum instead.
It was not me my friendly WinAPI Guru :-[
I just copied your post to find out why OP is telling that, since I know you are an absolute WinAPI expert.  O:-)
Delphi7 Application
And I do admit, his code I skipped to read since he not uses any code tags, so yes, his fault not yours.

But now I am extra curious because I did not find any working RichEdit for FreePascal, RichMemo and RichView are the only ones I found, is your RichEdit component somewhere available please?
Thank you for your time and code examples!
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1197
    • Lebeau Software
But now I am extra curious because I did not find any working RichEdit for FreePascal, RichMemo and RichView are the only ones I found

Correct, there is no native TRichEdit in FreePascal/Lazarus.  There are plenty of past discussions in this forum on that topic.

is your RichEdit component somewhere available please?

It is not my component.  TRichEdit is a native component in Delphi's VCL.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

 

TinyPortal © 2005-2018