Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi DrawCell vom Drawgrid belegt ganzes Programm (https://www.delphipraxis.net/152275-drawcell-vom-drawgrid-belegt-ganzes-programm.html)

BeBored 17. Jun 2010 07:39

Delphi-Version: 2007

DrawCell vom Drawgrid belegt ganzes Programm
 
Hallo,

ich sitze mal wieder an meinem Bahnprogramm und möchte eine wichtige Optimierung durchführen und hoffe ihr könnt mir helfen.
Ich zeichne folgt auf ein Drawgrid:
Delphi-Quellcode:
procedure TfrmMain.gridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  I: Integer;
begin
  for I := Low(GleisArray) to High(GleisArray) do
  begin
    if GleisArray[i].Art = 'Text' then
      Gleis.Text(GleisArray[i].x, GleisArray[i].y, GleisArray[i].Feldtext);
    if GleisArray[i].Art = 'Gerade' then
      Gleis.Gerade(GleisArray[i].x, GleisArray[i].y, GleisArray[i].Gesetzt);
    if GleisArray[i].Art = 'WeicheOL' then
      Gleis.WeicheOL(GleisArray[i].x, GleisArray[i].y, GleisArray[i].Gesetzt);
    if GleisArray[i].Art = 'WeicheOLG' then
      Gleis.WeicheOLG(GleisArray[i].x, GleisArray[i].y, GleisArray[i].Gesetzt);
    if GleisArray[i].Art = 'WeicheOR' then
      Gleis.WeicheOR(GleisArray[i].x, GleisArray[i].y, GleisArray[i].Gesetzt);
    if GleisArray[i].Art = 'WeicheORG' then
      Gleis.WeicheORG(GleisArray[i].x, GleisArray[i].y, GleisArray[i].Gesetzt);
    if GleisArray[i].Art = 'WeicheUL' then
      Gleis.WeicheUL(GleisArray[i].x, GleisArray[i].y, GleisArray[i].Gesetzt);
// und so weiter...
GleisArray ist ein Record
Delphi-Quellcode:
TGleisrecord = packed record
    x: Integer;
    y: Integer;
    Feldtext: string;
    Art: string;
    Gesetzt: Boolean;
  end;
und wird so gefüllt:
Delphi-Quellcode:
while not DataModule1.query2.Eof do
  begin
    {==============================================================================
    Das Array wird mit den einzelnen Feldern eingelesen.
    Das Array beginnt bei 1, da es nachher einfacher ist beim auslesen.
    ==============================================================================}
    GleisArray[i].x := DataModule1.query2.FieldByName('x').AsInteger;
    GleisArray[i].y := DataModule1.query2.FieldByName('y').AsInteger;
    GleisArray[i].Feldtext := DataModule1.query2.FieldByName('Feldtext').AsString;
    GleisArray[i].Art := DataModule1.query2.FieldByName('Art').AsString;
    GleisArray[i].Gesetzt := DataModule1.query2.FieldByName('Gesetzt').AsBoolean;
    Inc(i);
    {==============================================================================
    Weiter zum nächsten Datensatz.
    ==============================================================================}
    DataModule1.query2.Next;
Die Klasse Gleis beinhaltet die Bitmaps. Es ist alles als Bitmap vorhanden, ausser dem Text der wird "live" erzeugt.
Delphi-Quellcode:
// Die Gleise
procedure TGleisPic.DiagonalLinks(Spalte, Reihe: Integer; Gruen: Boolean);
var
  p: TRect;
begin
  p := Can.CellRect(Spalte, Reihe);
  if Gruen then
    BitBlt(Can.Canvas.Handle, p.Left, p.Top, p.Right - p.Left, p.Bottom - p.Top, Gleise.DiagonalLinks_G.Canvas.Handle, 0, 0, SRCCOPY)
  else
    BitBlt(Can.Canvas.Handle, p.Left, p.Top, p.Right - p.Left, p.Bottom - p.Top, Gleise.DiagonalLinks_S.Canvas.Handle, 0, 0, SRCCOPY);
end;

// und der Text
procedure TGleisPic.Text(Spalte, Reihe: Integer; Text: string);
var
  p: TRect;
begin
  SetBkMode(Can.Canvas.Handle, OPAQUE);
  Can.Canvas.Font.Color := clBlack;
  Can.Canvas.Font.Size := 7;
  Can.Canvas.Font.Style := [];
  Can.Canvas.Font.Name := 'Arial';
  p := Can.CellRect(Spalte, Reihe);
  Can.Canvas.TextOut(p.Left + 5, p.Top, Text);
end;
Das Bild wird auch fix gezeichnet, aber so schnell hintereinander das die gesammte Anwendung völlig belegt ist.
Ich hatte das ganze auch mit ProcessMessages versucht, aber dann ist das Programm sehr anfällig für Abstürze. :cry:

Hat jemand einen Vorschlag wie ich das ganze optimieren oder vielleicht ganz anders angehen könnte?

SirThornberry 17. Jun 2010 07:49

AW: DrawCell vom Drawgrid belegt ganzes Programm
 
Das wird zwar nicht der Performancekiller sein aber anstelle mehrere ifs unteinander zu schreiben, schau dir mal das schlüsselwort "else" an. Dadurch wird verhindert das die weiteren ifs noch ausgewertet werden selbst wenn zuvor ein passender Eintrag gefunden wurde.

idefix2 17. Jun 2010 08:44

AW: DrawCell vom Drawgrid belegt ganzes Programm
 
Die Gleisart als String zu speichern und abzufragen ist keine gute Idee. Mach dafür einen Aufzähltype, und verwende dann zum Abfragen ein Case statement.

Zitat:

Ich hatte das ganze auch mit ProcessMessages versucht, aber dann ist das Programm sehr anfällig für Abstürze.
Da gibt es wohl ein grundlegenderes Problem, Processmessages kann normalerweise ein Programm nicht anfällig für Abstürze machen, wenn nicht schon irgendwelche bösen Fehler da sind (nicht initialisierte Variable, Out of bounds Zugriff o.ä., die sich zufällig erst dann auswirken, wenn man den Befehl einbaut.

Hawkeye219 17. Jun 2010 08:54

AW: DrawCell vom Drawgrid belegt ganzes Programm
 
Hallo,

wenn ich den gezeigten Quelltext richtig interpretiere, wird bei jedem Aufruf von gridDrawCell das komplette Gleisbild gezeichnet. Die Aufgabe der Routine ist aber, nur den Inhalt der Zelle (ACol, ARow) darzustellen.

Gruß Hawkeye

Blup 17. Jun 2010 09:13

AW: DrawCell vom Drawgrid belegt ganzes Programm
 
Im OnDrawCell wird immer genau eine Zelle gezeichnet, nicht das komplette Grid.
Delphi-Quellcode:
procedure TfrmMain.gridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  I: Integer;
begin
  for I := Low(GleisArray) to High(GleisArray) do
  begin
    if (GleisArray[i].x = ACol) and (GleisArray[i].y = ARow) then
      Gleis.Zeichne(Grid.Canvas, Rect, GleisArray[i]);
  end;
end;

procedure TGleisPic.Zeichne(ACanvas: TCanvas; ARect: TRect; const AItem: TGleisrecord);
begin
  with AItem do
  begin
         if Art = 'Text'     then Text(ACanvas, ARect, Feldtext)
    else if Art = 'Gerade'   then Gerade(ACanvas, ARect, Gesetzt)
    else if Art = 'WeicheOL' then WeicheOL(ACanvas, ARect, Gesetzt)
    else if Art = 'WeicheOLG' then WeicheOLG(ACanvas, ARect, Gesetzt)
    else if Art = 'WeicheOR' then WeicheOR(ACanvas, ARect, Gesetzt)
    else if Art = 'WeicheORG' then WeicheORG(ACanvas, ARect, Gesetzt)
    else if Art = 'WeicheUL' then WeicheUL(ACanvas, ARect, Gesetzt)
// und so weiter...
  end;
end;

BeBored 17. Jun 2010 11:06

AW: DrawCell vom Drawgrid belegt ganzes Programm
 
Spitze!
Ich habe nun alle Vorschläge umgesetzt und es schnurrt wie ein Kätzchen :thumb:
Ich danke euch recht herzlich.

David Martens 21. Jun 2010 00:13

AW: DrawCell vom Drawgrid belegt ganzes Programm
 
Nur so ein Vorschlag, damit wird dein Programm nicht schneller aber, ich finde, es wird übersichtlicher:

Delphi-Quellcode:
case StrUtils.AnsiIndexStr(sourcestring, ['foo','bar']) of
  0:;
  1:;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:48 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz