Solved

Delphi 7 :: TRichEdit Colored Lines :: Looses Format when Line Count too large

Posted on 2007-11-20
17
1,180 Views
Last Modified: 2013-11-23
Hi Experts,

1. Does the TRichEdit has any limit in Size / Line Count?

2. I have a procedure that colors a given line in a TRichEdit component. There is a little problem with the TRichEdit component, as soon as the line count is more than about 600-900 the RichEdit loads the saved information without any propery formatting and my colored lines are also gone. On application close I save TRichEdit.Lines.SaveToFile()  to file and when starting application I load again TRichEdit.Lines.LoadFromFile().
I think there is some kind of size limit because when line count is less 600 (est) it saves and loads and display contents correctly.

This is what the TRichEdit contents look like when it bombs out:

{\rtf1\ansi\deff0{\fonttbl{\f0\fnil MS Sans Serif;}}
{\colortbl ;\red0\green0\blue0;\red255\green0\blue0;}
\viewkind4\uc1\pard\cf1\lang1033\f0\fs16\{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033\{\\fonttbl\{\\f0\\fnil MS Sans Serif;\}\}
\par \{\\colortbl ;\\red0\\green0\\blue0;\\red128\\green0\\blue0;\\red0\\green128\\blue0;\\red255\\green0\\blue0;\}
\par \\viewkind4\\uc1\\pard\\cf1\\f0\\fs16 [2007/11/20 11:01:05 AM] New: D:\\\\B Destination\\\\44982.PREJIG
\par \\par [2007/11/20 11:01:05 AM] New: D:\\\\B Destination\\\\44987.PREJIG\\cf0
\par \\par \\cf1 [2007/11/20 11:01:05 AM] New: D:\\\\B Destination\\\\44980.PREJIG\\cf0
\par \\par \\cf2 [2007/11/20 11:01:09 AM] Production Order#: 7014564 has been replaced with latest.\\cf0
\par \\par \\cf1 [2007/11/20 11:01:09 AM] Production Order#: 7014564 Added.\\cf0
\par \\par \\cf2 [2007/11/20 11:01:09 AM] Production Order#: 7014565 has been replaced with latest.\\cf0
\par \\par \\cf1 [2007/11/20 11:01:09 AM] Production Order#: 7014565 Added.\\cf0
\par \\par \\cf2 [2007/11/20 11:01:09 AM] Production Order#: 7014566 has been replaced with latest.\\cf0
\par \\par \\cf1 [2007/11/20 11:01:09 AM] Production Order#: 7014566 Added.\\cf0


Thanks!
0
Comment
Question by:Marius0188
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
  • 4
17 Comments
 

Author Comment

by:Marius0188
ID: 20318666
When I set TRichEdit.PlainText := True
then it Loads properly but of course then my line coloring disappears.

Maybe this can help.... :)
0
 

Author Comment

by:Marius0188
ID: 20325875
Anyone that can help?
Or please if you know about a Free TRichEdit component that I can try out, let me know.

Thanks
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 20332987
depending on the os there is a memory-limit by default

not in mind correctly
- win9x -> 32kb
- winXP/NT/2000 -> 64kb

you can adjust this limit before loading editing with the API call

richedit1.perform(EM_EXLIMITTEXT,0,$0FFFFFFF);  //limit to 256MB

(you can play with the $0FFFFFFF paramater,
which is just the max amount of bytes a richedit can hold)

meikl ;-)
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 13

Expert Comment

by:rfwoolf
ID: 20332989
If you're stuck, you should look up the W3Org standard for RTF files, i.e. learn how to code them. That way you can analyse the source code of an RTF file
I once learnt it about 3 years ago - and only superficially to complete the task I was doing. I've forgetten all about it now.
Anyway, on the other hand you might be correct - that there's a problem over a certain number of lines. To me the problem is either the source code of the RTF is invalid around those colour-less lines, or, it's a problem with the component/windows.

Good luck!
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 20332992
appendix,

for using above the richedit-unit must be added to the unit clause

meikl ;-)
0
 
LVL 13

Expert Comment

by:rfwoolf
ID: 20332993
I posted my answer before seeing kretzschmar's. His answer sounds good. Give it a try.
0
 

Author Comment

by:Marius0188
ID: 20333045
HI Kretzschmar,

In regards to your post, #20332987
Do I need to only make a call to that method once for ex:
OnCreate of my main form

OR:

Should I make a call to that method BEFORE each time I add / edit a line to TRichEdit and also BEFORE loading and BEFORE saving to file?

Please advise.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 20333074
>Do I need to only make a call to that method once
yes, its only once needed
and (not sure, if it needed) before each load (.loadfromfile) (in case you load multiple files with the same instance)

meikl ;-)
0
 

Author Comment

by:Marius0188
ID: 20333156
I have implement that line of code but the problem still exists.
Any other suggestions?

Thanks for helping so far.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 20333233
bad, was my only idea about a limit

maybe you could show your code-sample?

meikl ;-)
0
 
LVL 13

Expert Comment

by:rfwoolf
ID: 20333250
Try dumping the lines to an rtf file and opening it up in Word or Wordpad. See if it manages to colour the lines or not.
This will help in your diagnosis
0
 

Author Comment

by:Marius0188
ID: 20333426
Here is the procedure that writes the message to my log file and also to the TRichEdit
-------------------------------------------------------------------------------------------------------
procedure TfrmMain.WriteToLog(const ALogType :TLogType; AMessage: WideString);
var
  FTextFile :TextFile;
  TempMessage :String;
begin
  AssignFile(FTextFile, fServerLogFile);
  Try
    If FileExists(fServerLogFile) then Append(FTextFile)
    Else Rewrite(FTextFile);

    If not IsFilled(AMessage) then TempMessage := AMessage
    Else TempMessage := '[' + DateTimeToStr(Now) + '] ' + AMessage;


    Writeln(FTextFile, TempMessage);

    redtLogFile.Lines.Add(TempMessage);
    Case ALogType of
      logNormal: ColorRicheditLine(redtLogFile, redtLogFile.Lines.Count - 1, clBlack);
      logAttention: ColorRicheditLine(redtLogFile, redtLogFile.Lines.Count - 1, clGreen);
      logAlert: ColorRicheditLine(redtLogFile, redtLogFile.Lines.Count - 1, clMaroon);
      logError: ColorRicheditLine(redtLogFile, redtLogFile.Lines.Count - 1, clRed);
    end;
   
  Finally
    CloseFile(FTextFile);
    redtLogFile.Lines.SaveToFile(fServerLogFileRichEdit);
  end;
end;

-------------------------------------------------------------------------------------------------------



-------------------------------------------------------------------------------------------------------
Procedure ColorRicheditLine(const ARichEdit :TRichEdit; ARow :Integer; AColor :TColor);
begin
  With ARichEdit do
  begin
    SelStart := SendMessage(Handle, EM_LINEINDEX, ARow, 0);
    SelLength := Length(Lines[ARow]);
    SelAttributes.Color := AColor;
    SelLength := 0;
  end;
end;

-------------------------------------------------------------------------------------------------------
0
 

Author Comment

by:Marius0188
ID: 20348520
When opening the rtf file in wordpad is also have the wrong format.

Do you know about a free TRichEdit alternative component?
0
 
LVL 13

Expert Comment

by:rfwoolf
ID: 20348893
Marius, surely if it displays wrong in Wordpad, then the sourcecode of the RTF is wrong?  Therefore a different richtext reader component is probably not the solution.
You need to perhaps study the RTF standards from W3O and study the RTF file, take out parts you don't need, scroll through until you find the problem. If you don't find the problem, at least you've eliminated some possibilities.
0
 

Author Comment

by:Marius0188
ID: 20350136
Mmmh, I hear what you say.
But why is it working fine up to a certain line count?
Anything less than 600-800 lines is displaying correctly.

Does that not rather shows it is something with the component because the code I use to highlight a line is consistent?
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 500 total points
ID: 20363868
Hi again,

i cant reproduce your problem (using TurboExplorer).
Have implemented an alternative Method, tests with a file with 5000 lines (206kb).
Also stoped the time:
Your Implementation: 170265 MilliSeconds
Alternative Implementation: 17203 MilliSeconds

My TestCase:


unit re_colorLines_u;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls;
 
type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit; //FileHolder
    Panel1: TPanel;
    Button1: TButton;
    Button2: TButton;
    OpenDialog1: TOpenDialog;
    Button3: TButton;
    Splitter1: TSplitter;
    RichEdit2: TRichEdit;  //Target
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    fServerLogFile : string;
    fServerLogFileRichEdit : String;
    procedure WriteToLog(const ALogType :integer; AMessage: WideString);
    procedure WriteToLogNewVersion(const ALogType :Integer; AMessage: WideString);
  public
    { Public-Deklarationen }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
uses richedit;
 
 
//Load a file
procedure TForm1.Button1Click(Sender: TObject);
begin
  if opendialog1.Execute then
  begin
    //CleanUp
    richedit1.lines.Clear;
    richedit2.lines.Clear;
    //Init
    richedit1.perform(EM_EXLIMITTEXT,0,$0FFFFFFF);  //limit to 256MB
    richedit2.perform(EM_EXLIMITTEXT,0,$0FFFFFFF);  //limit to 256MB
    richedit1.Lines.LoadFromFile(opendialog1.FileName);
    fServerLogFile := opendialog1.FileName+'.fsl';
    fServerLogFileRichEdit  := opendialog1.FileName+'.fsl.rtf';
  end;
end;
 
//Caller ColorTheFileOriginalMethod
procedure TForm1.Button2Click(Sender: TObject);
var
  i : integer;
  start, ende : Longint;
begin
  start := getTickCount;
  for I := 0 to richedit1.lines.Count - 1 do
    WriteToLog(i mod 4, richedit1.lines[i]);
  ende := getTickCount;
  showmessage('TimeNeeded (MilliSeconds): '+IntTostr(ende-start));
end;
 
//Caller ColorTheFileNewMethod
procedure TForm1.Button3Click(Sender: TObject);
var
  i : integer;
  start, ende : Longint;
begin
  start := getTickCount;
  for I := 0 to richedit1.lines.Count - 1 do
    WriteToLogNewVersion(i mod 4, richedit1.lines[i]);
//save only once
  richedit1.Lines.SaveToFile(fServerLogFileRichEdit);
  ende := getTickCount;
  showmessage('TimeNeeded (MilliSeconds): '+IntTostr(ende-start));
end;
 
//Old Method
Procedure ColorRicheditLine(const ARichEdit :TRichEdit; ARow :Integer; AColor :TColor);
begin
  With ARichEdit do
  begin
    SelStart := SendMessage(Handle, EM_LINEINDEX, ARow, 0);
    SelLength := Length(Lines[ARow]);
    SelAttributes.Color := AColor;
    SelLength := 0;
  end;
end;
 
procedure TForm1.WriteToLog(const ALogType :Integer; AMessage: WideString);
var
  FTextFile :TextFile;
  TempMessage :String;
begin
  AssignFile(FTextFile, fServerLogFile);
  Try
    If FileExists(fServerLogFile) then Append(FTextFile)
    Else Rewrite(FTextFile);
 
    If not (AMessage = '') then TempMessage := AMessage
    Else TempMessage := '[' + DateTimeToStr(Now) + '] ' + AMessage;
 
 
    Writeln(FTextFile, TempMessage);
 
    richedit2.Lines.Add(TempMessage);
    Case ALogType of
      0: ColorRicheditLine(richedit2, richedit2.Lines.Count - 1, clBlack);
      1: ColorRicheditLine(richedit2, richedit2.Lines.Count - 1, clGreen);
      2: ColorRicheditLine(richedit2, richedit2.Lines.Count - 1, clMaroon);
      3: ColorRicheditLine(richedit2, richedit2.Lines.Count - 1, clRed);
    end;
 
  Finally
    CloseFile(FTextFile);
    richedit2.Lines.SaveToFile(fServerLogFileRichEdit);
  end;
end;
 
//New Method
procedure TForm1.WriteToLogNewVersion(const ALogType :Integer; AMessage: WideString);
var
  FTextFile :TextFile;
  TempMessage :String;
  Color : TColor;
begin
  AssignFile(FTextFile, fServerLogFile);
  Try
    If FileExists(fServerLogFile) then Append(FTextFile)
    Else Rewrite(FTextFile);
 
    If not (AMessage = '') then TempMessage := AMessage
    Else TempMessage := '[' + DateTimeToStr(Now) + '] ' + AMessage;
 
 
    Writeln(FTextFile, TempMessage);
 
    //richedit2.Lines.Add(TempMessage);
    Case ALogType of
      0: Color := clBlack;
      1: Color := clGreen;
      2: Color := clMaroon;
      3: Color := clRed;
    end;
 
    Richedit2.selstart := length(Richedit2.text);
    Richedit2.selAttributes.Color := Color;
    Richedit2.seltext := TempMessage+#10;
 
  Finally
    CloseFile(FTextFile);
    //guess must not done each line
    //richedit2.Lines.SaveToFile(fServerLogFileRichEdit);
  end;
end;
 
end.

Open in new window

0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 20363883
oops, of course line 80 must be richedit2 ;-)
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Finding and deleting duplicate (picture) files can be a time consuming task. My wife and I, our three kids and their families all share one dilemma: Managing our pictures. Between desktops, laptops, phones, tablets, and cameras; over the last decade…

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question