Solved

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

Posted on 2007-11-20
17
1,170 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
appendix,

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

meikl ;-)
0
 
LVL 13

Expert Comment

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

Author Comment

by:Marius0188
Comment Utility
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
Comment Utility
>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
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:Marius0188
Comment Utility
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
Comment Utility
bad, was my only idea about a limit

maybe you could show your code-sample?

meikl ;-)
0
 
LVL 13

Expert Comment

by:rfwoolf
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
oops, of course line 80 must be richedit2 ;-)
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
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…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

744 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

19 Experts available now in Live!

Get 1:1 Help Now