Solved

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

Posted on 2007-11-20
17
1,171 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
  • 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
 
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.
Hi friends,  in this video  I'll show you how new windows 10 user can learn the using of windows 10. Thank you.

911 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now