Hi all,
I have a little problem with my application under Win32 (Laz 0.9.30 + FPC 2.4.2).
I have a dynamic array of packed record. The structure is this:
TRecord = packed record
Description:ansistring;
DT:tdatetime;
Component:string;
end;
TDataRec= array of TRecord;
var
datarec: TDataRec;
This array can be very big (about 1.000.000 of record). And I need to show its content in a TStringGrid.
My first attempt was to populate each cell with a loop:
StringGrid1.rowcount:=length(datarec)+1; //for header...
for c:=0 to high(datarec) do
begin
StringGrid1.cells[0,c+1]:=datarec[c].description;
...
end;
But this approch has 2 problems:
1. it takes about 6-7 seconds to complete
2. the application eats about 600MB in ram
So, considering a user can display only few records at a time, I tried to populate the grid only for records that are visible on the screen. To achive this I used OnDrawCell event.
Something like this:
procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
aRect: TRect; aState: TGridDrawState);
var
MyTextStyle:TTextStyle;
begin
MyTextStyle := StringGrid1.Canvas.TextStyle;
MyTextStyle.SingleLine := false;
StringGrid1.Canvas.TextStyle := MyTextStyle;
if arow>0 then //stringgrid1 has length(datarec)+1 as rowcount, and row 0 is header
case acol of
0: stringgrid1.Canvas.TextRect(aRect,aRect.Left+6,aRect.Top,formatdatetime('yyyy-mm-dd hh:nn:ss.zzz',DataRec[arow-1].DT));
1: stringgrid1.Canvas.TextRect(aRect,aRect.Left+6,aRect.Top,DataRec[arow-1].Component);
2: stringgrid1.Canvas.TextRect(aRect,aRect.Left+6,aRect.Top,DataRec[arow-1].Description,mytextstyle);
end;
end;
In this way: the load time is few milliseconds and the ram used by stringgrid is about 20MB because I do not write on each cell but "draw" a cell with text. (Perhaps it is possble to optimize it with a lower number of rows, about 100, and using a TScrollbar to move to a different position).
But my problem is that after the grid is populated, the application eats 100% cpu and become irresponsive. The same happens if I write directly to cells with StringGrid1.cells[acol,arow]:=...
and also if I use OnPrepareCanvas event.
So I have 2 questions:
1. What is wrong in my code? Why I cannot "draw" text in OnDrawCell event?
2. Is this approach correct? Does anybody know a different method to load a large amount of data in a stringgrig, without actually populate every cell?
Thanks in advance.