Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi nochmals StringGridDrawcell (https://www.delphipraxis.net/139303-nochmals-stringgriddrawcell.html)

fl63 26. Aug 2009 13:36


nochmals StringGridDrawcell
 
Hallo DPler,

ich möchte eine Spalte eines Stringgrids, in Abhängigkeit des Inhaltes färben(rot,grün).

Mein Quelltext läßt sich auch fehlerfrei kompilieren, nur seh ich keinen Erfolg.

Das Stringgrid welches ich verwende ist Jedi Stringgrid. Die DrawCell Methode habe ich aus diesem Forum. Anbei mein Text.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
//Lade Datei
JvSG1.LoadFromCSV('messwert.txt',#9);
//Färbe Spalte 2
Rechnen(Sender);
//Spring zur letzten Zeile
//JvSG1.Row := JvSG1.RowCount-1;

end;

Procedure TForm1.Rechnen(Sender: TObject);
var i:Integer;
   k,l:extended;

begin
  For i := 2 to JvSG1.RowCount-1 do
    k := StrToFloat(JvSG1.Cells[2,i]); l := StrToFloat(JvSG1.Cells[2,i-1]);
    If k > l then
    begin
    JvSG1.Canvas.Brush.Color := clred;
    DrawCell(Sender,2,i,Rect(0,0,0,0),[gdselected]) ;
    end;
end;

procedure TForm1.DrawCell(Sender: TObject; Col, Row: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  (sender as TStringgrid).canvas.Brush.color:=(sender as TStringgrid).color;
  (sender as TStringgrid).canvas.Font.color:=clWindowText;
  if (col<(sender as TStringgrid).fixedCols) or (row<(sender as TStringgrid).fixedRows) then
    (sender as TStringgrid).canvas.Brush.color:=(sender as TStringgrid).FixedColor //farbe der Header
  else if gdSelected in state then
  begin
    (sender as TStringgrid).canvas.Brush.color:=clHighlight; //farbe von markierung
    (sender as TStringgrid).canvas.Font.color:=clWindow;
  end else if integer(JVSG1.objects[col,row])=2 then
    (sender as TStringgrid).canvas.Brush.color:=clgreen;
  (sender as TStringgrid).canvas.FillRect(rect);
  (sender as TStringgrid).canvas.TextOut(rect.left+2,rect.top+2,(sender as TStringgrid).Cells[col,row]);
end;
Ich hoffe auf Hilfe.

MacGuyver 26. Aug 2009 13:52

Re: nochmals StringGridDrawcell
 
Moin fl63,

ich kann jetzt so nicht sagen warum, habe nur einen kleinen Tip für die Übersichtlichkeit:

Delphi-Quellcode:
var
  lGrid : TStringgrid;
  lCV : TCanvas;

begin
  lGrid := sender as TStringgrid;
  lCV := lGrid.canvas;
Ab dann kannst du mit lGrid und lCV arbeiten anstelle immer (sender as TStringgrid) und (sender as TStringgrid).canvas zu benutzen.

Musst du bei dem Stringgrid irgendwie "OwnerDraw" aktivieren?

Stefan

fl63 26. Aug 2009 14:07

Re: nochmals StringGridDrawcell
 
Hallo Mac Guyver
Die DrawCell Methode habe ich wie schon geschrieben aus diesem Forum nur kopiert. In diesem Beitrag wurde ein Ereignis über eine Click Routine ausgelöst. So ähnlich wie bei mir.

Ownerdraw :gruebel: :gruebel: ???

Hobby-Programmierer 26. Aug 2009 14:50

Re: nochmals StringGridDrawcell
 
Tach ...
fangen wir mal von vorne an.
- Hast Du die Zeichnenfunktion auch mit dem enstpr. Ereigniss des Stringrids verbunden? (OnDrawCell)
- DefaultDrawing auf False umgestellt?

LG Mario

fl63 26. Aug 2009 14:52

Re: nochmals StringGridDrawcell
 
Ja zu beidem.

Hobby-Programmierer 26. Aug 2009 15:29

Re: nochmals StringGridDrawcell
 
Zeig mal bitte den kompletten Code. Irgendwie fehlt mir da einiges!

P.S.: Nimm mal Draw aus Deiner Rechenroutine raus, darum kümmert sich das SG selbstständig.

Keldorn 26. Aug 2009 15:36

Re: nochmals StringGridDrawcell
 
Hallo

da sind mehrere Sachen drin, die nicht gehen können, wobei ich das Jedi Grid nicht kenne.

u.a.:

Ich versteh dein "Rechnen" nicht, da keine Zuweisung erfolgt.
Das drawcell direkt aufzurufen ist unnötig, das macht das Grid alleine, sobald sich ein Wert ändert. So kann es auch nicht gehen, da du dort
1. als Sender einen Button übergibst, und mit sender as tstringgrid bist du nicht im Grid, sondern im Button
2. als rect übergibst du 0,0,0,0 -> was glaubst Du, wo dein Textout(rect.left,rect.top,...) den Text hinschreiben wird ;-)

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
...
Rechnen(Sender); //Sender=Button1
...
end;

Procedure TForm1.Rechnen(Sender: TObject);
begin
...
    DrawCell(Sender,2,i,Rect(0,0,0,0),[gdselected]) ; //übergebener Sender ist der Button1
...
end;
Zitat:

if integer(JVSG1.objects[col,row])=2 then
in deinem Code steht nirgends, wo Du das object hinterlegts, sicher, das du hier nicht inttostr(cells[acol,arow] stehen haben willst?

Gruß Frank

fl63 26. Aug 2009 15:41

Re: nochmals StringGridDrawcell
 
Ich habe DrawCell aus der Rechenroutine gestrichen und es passiert nichts.

Im übrigen ist das der komplette Code

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, JvExGrids, JvStringGrid;

type
  TForm1 = class(TForm)
    JvSG1: TJvStringGrid;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    Procedure Rechnen(Sender: TObject);
    procedure DrawCell(Sender: TObject; Col, Row: Integer; Rect: TRect; State: TGridDrawState);


  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
begin
//Lade Datei
JvSG1.LoadFromCSV('messwerte.txt',#9);
//Färbe Spalte 2
Rechnen(Sender);
//Spring zur letzten Zeile
//JvSG1.Row := JvSG1.RowCount-1;

end;

Procedure TForm1.Rechnen(Sender: TObject);
var i:Integer;
   k,l:extended;

begin
  For i := 2 to JvSG1.RowCount-1 do
    k := StrToFloat(JvSG1.Cells[2,i]); l := StrToFloat(JvSG1.Cells[2,i-1]);
    If k > l then
    begin
    JvSG1.Canvas.Brush.Color := clred;
//    DrawCell(Sender,2,i,Rect(0,0,0,0),[gdselected]) ;
    end;
end;

procedure TForm1.DrawCell(Sender: TObject; Col, Row: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  (sender as TStringgrid).canvas.Brush.color:=(sender as TStringgrid).color;
  (sender as TStringgrid).canvas.Font.color:=clWindowText;
  if (col<(sender as TStringgrid).fixedCols) or (row<(sender as TStringgrid).fixedRows) then
    (sender as TStringgrid).canvas.Brush.color:=(sender as TStringgrid).FixedColor //farbe der Header
  else if gdSelected in state then
  begin
    (sender as TStringgrid).canvas.Brush.color:=clHighlight; //farbe von markierung
    (sender as TStringgrid).canvas.Font.color:=clWindow;
  end else if integer(JVSG1.objects[col,row])=2 then
    (sender as TStringgrid).canvas.Brush.color:=clgreen;
  (sender as TStringgrid).canvas.FillRect(rect);
  (sender as TStringgrid).canvas.TextOut(rect.left+2,rect.top+2,(sender as TStringgrid).Cells[col,row]);
end;


end.

Hobby-Programmierer 26. Aug 2009 15:53

Re: nochmals StringGridDrawcell
 
Du hast immer noch nicht dem angehängtem Object einen Wert zugewiesen!!
Delphi-Quellcode:
if integer(JVSG1.objects[col,row])=2 then
läuft ins leere. Bist Du sicher das dies der richtige Weg für dich ist? Prüfe stattdessen doch einfach den Wert der Zelle direkt
Delphi-Quellcode:
if Trim(Cells[col, row]) = '2' then

fl63 26. Aug 2009 16:10

Re: nochmals StringGridDrawcell
 
Zitat:

Zitat von Hobby-Programmierer
Du hast immer noch nicht dem angehängtem Object einen Wert zugewiesen!!
Delphi-Quellcode:
if integer(JVSG1.objects[col,row])=2 then
läuft ins leere. Bist Du sicher das dies der richtige Weg für dich ist? Prüfe stattdessen doch einfach den Wert der Zelle direkt
Delphi-Quellcode:
if Trim(Cells[col, row]) = '2' then

Ich bin jetzt langsam davon überzeugt die gesamte DrawCell Routine ist für dieses Problem nicht geeignet. Wie schon geschrieben habe ich diese Routine aus diesem Forum. Sie selber zu schreiben, weiß ich gar nicht wie, da ich Anfänger bin.

Hobby-Programmierer 26. Aug 2009 16:51

Re: nochmals StringGridDrawcell
 
Ich kenne das JediGrid zwar auch net, aber folgendes sollte auch damit funktionieren. Sonst teste mal einfach mit nem Standard Grid
Delphi-Quellcode:
procedure TForm1.SG1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
const tFormat = DT_SINGLELINE or DT_CENTER or DT_VCENTER;
var  tText: String;
begin
  with (Sender as TStringGrid) do begin
    tText:= Trim(Cells[ACol, ARow]); // Text der Zelle
    if (gdFixed in State) then begin // feste Zelle?
      Canvas.Brush.Color:= clBtnFace; // HintergrundFarbe

      end else if (gdSelected in State) then begin // markierte Zelle
      Canvas.Brush.Color:= clHighlight;
      Canvas.Font.Color:= clBlack;

     end else begin // normale Zelle
      Canvas.Brush.Color:= clWindow;
      if tText = '2' then Canvas.Brush.Color:= clgreen;
  //    ...
  //    ...
    end; // <> (gdFixed in State)
    Canvas.FillRect(Rect); // Hintergrund zeichnen
    DrawText(Canvas.Handle, PChar(tText), Length(tText), Rect, tFormat); // Textausgabe
  end; // with
end;
evtl. musst Du noch ACol, ARow in Col, Row umbenennen. DefaultDrwaing auf True

LG Mario

fl63 27. Aug 2009 14:38

Re: nochmals StringGridDrawcell
 
Hallo Hobby-Programmierer,
Ich habe deine Methode ausprobiert und komme auch mit Delphi Standard SG zum Selben Ergebnis

4spaltige Wiederholung der Zelle 1,1 und keine Farbe

Ich werde es weiter Probieren Vielen Dank.

Keldorn 27. Aug 2009 17:55

Re: nochmals StringGridDrawcell
 
Zitat:

Zitat von fl63
4spaltige Wiederholung der Zelle 1,1 und keine Farbe

dann liegt das problem wahrscheinlich an acol und arow:
Zitat:

procedure TForm1.SG1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
const tFormat = DT_SINGLELINE or DT_CENTER or DT_VCENTER;
var tText: String;
begin
with (Sender as TStringGrid) do begin
tText:= Trim(Cells[ACol, ARow]); // Text der Zelle

...
das A vor Acol und Arow ist sehr wichtig (du mußt es auch noch im interfaceTeil ändern)

Ansonsten verwendest du mit with (sender asstringgrid) do ... cells[col,row] nicht die beiden Übergebenen col und row sondern sg1.col und sg1.row = die aktuell selektierte Zelle. Damit steht dann auch immer das gleiche in allen Zellen drin.

Gruß Frank

Hobby-Programmierer 27. Aug 2009 19:31

Re: nochmals StringGridDrawcell
 
Liste der Anhänge anzeigen (Anzahl: 1)
siehe Anhang

[edit] Das evtl. umbenennen von ACol, ARow bezog sich auf das JediGrid.

fl63 28. Aug 2009 14:31

Re: nochmals StringGridDrawcell
 
Hallo Keldorn, Hallo Hobby-Programmierer,

Endlich Farbe im Grid :drunken:

Aber

ich verdeutliche mal mein Problem

Cell[2,0] = FixedRow
Cell[2,1] = 1 Ausgangswert
Cell[2,2] = 2 Vergleich mit Cell 2,1 ==> Zelle 2,2 Farbe Grün
Cell[2,3] = 3 Vergleich mit Cell 2,2 ==> Zelle 2,3 Farbe Grün
Cell[2,4] = 2 Vergleich mit Cell 2,3 ==> Zelle 2,4 Farbe Rot !!!
Cell[2,5] = 3 Vergleich mit Cell 2,4 ==> Zelle 2,5 Farbe Grün !!


In der Rechnen Prozedur habe ich das versucht anzudeuten
Der Code ist nicht vollständig und fehlerhaft die Logik dahinter meiner Ansicht nach dennoch richtig.

1. wandle String in extended um (weil Kommazahlen vorhanden)
2. Vergleiche extended Zahlen
3. weise Farbe zu und färbe Grid

Ich hoffe auf eure weitere Hilfe.

Gruß Frank

Lannes 28. Aug 2009 15:21

Re: nochmals StringGridDrawcell
 
Hallo,

das Ereignis OnDrawCell wird automatisch ausgelöst, wenn eine Zelle neu gezeichnet werden muss, wobei das Ereignis für jede Zelle einzeln ausgelöst wird. Schreibst Du Code für die Behandlung des OnDrawCell-Ereignisses musst Du das immer beachten.
Die Parameter ACol und ARow liefern Dir die aktuell zu zeichnende Adresse, im Parameter Rect sind die Koordinaten der Zelle enthalten. Möchtest Du nun auf Grund von Zellinhalten einfärben ist die Bedingung relativ zur aktuell zu zeichnende Zelle zu stellen.

Wenn ich Dein Beispiel richtig interpretiere soll eine Zelle rot eingefärbt werden, wenn der Inhalt größer als der in der darüberliegenden Zelle ist.

ARow = 0 -> erste Zeile ist fixed.
ARow = 1 -> zweite(erste Wertzeile) Zeile muss nicht beachtet werden.
ARow >= 2 -> dritte Zeile und weitere vergleichen mit Zelle oberhalb

Daraus ergib sich folgender grober Ansatz:
Delphi-Quellcode:
if ARow >= 2 then
  if StrToFloat(Grid.Cells[ACol,ARow]) > StrToFloat(Grid.Cells[ACol,ARow -1]) then
    begin
    //Farbe setzen
    //Zelle zeichnen
    //Text ausgeben
    end;

Blup 28. Aug 2009 15:22

Re: nochmals StringGridDrawcell
 
Machs dir einfach und übersichtlich, erstelle für jede Aufgabe eine eigene Funktion.
Delphi-Quellcode:
function CalcCellColor(AGrid: TStringGrid; ACol, AROw: Integer): TColor;
var
  d1, d2: Double;
begin
  Result := AGrid.Color;
  if ARow > 1 then
  begin
    try
      d1 := StrToFloat(AGrid.Cells[ACol, AROw - 1]);
      d2 := StrToFloat(AGrid.Cells[ACol, AROw]);
      if     d1 < d2 then Result := clGreen
      else if d1 > d2 then Result := clRed;
    except
    end;
  end;
end;

// normale Zelle
Canvas.Brush.Color:= CalcCellColor(Sender as TStringGrid, ACol, ARow);

hoika 28. Aug 2009 15:32

Re: nochmals StringGridDrawcell
 
Hallo,

Lannes hat Recht.
Du hast das DrawCell nicht verstanden.

Unter Windows rufst nicht du ein DrawCell auf,
sondern Windows, du reagierst nur drauf !

Fang mal mit einem einfachen Bsp. an.

Erzeuge durch Doppelklick auf das Ereignis OnDrawCell
eine Methode GridXDrawCell (macht Delphi).
Dort rufst du dein SGDrawCell (?) auf.


Heiko

Hobby-Programmierer 28. Aug 2009 19:00

Re: nochmals StringGridDrawcell
 
vielleicht so
Delphi-Quellcode:
if ARow > 1 then begin
  if StrToFloatDef(Cells[ACol, ARow], 0.0) > StrToFloatDef(Cells[ACol, ARow - 1], 0.0) then
    Canvas.Brush.Color:= clgreen
   else
    Canvas.Brush.Color:= clred;
end;

fl63 29. Aug 2009 12:33

Re: nochmals StringGridDrawcell
 
Hallo Helfer,

@ Lannes und hoika

Ich würde es ja auch gerne selber schreiben, wenn ich davon genug wüßte. vielleicht könnt ihr mir ein umfangreiches Tutorial empfehlen in dem Stringgrid gut beschrieben wird.

Ich hab den Tip von Blub eingebaut und bekomme jetzt ab der Zelle(2,3) die erste FarbZeile geliefert. Warum die ganze Zeile farbig wird... Ich muß mich wohl mit abfinden.

Warum Zeile 1 ohne Farbe ist ist klar. Bei Zeile 2 sieht das schon anders aus??

Ansonsten bedanke ich mich für die schnelle Hilfe.

Frank

hoika 29. Aug 2009 12:54

Re: nochmals StringGridDrawcell
 
Hallo,

was ist daran so schwer ? ;)
OK, aller Anfang ist schwer.

Zeig noch mal deine aktuelle DrawCell-Methode.

Vielleicht noch ein Hinweis.

Du musst die Farbe auch dann setzen,
wenn sie wie die des Grids /weiss ?) sein soll.
Das DrawCell "merkt" sich die letzten gesetzten Farben.


Heiko

Lannes 29. Aug 2009 13:13

Re: nochmals StringGridDrawcell
 
Hallo,

Zitat:

Zitat von fl63
Warum die ganze Zeile farbig wird... Ich muß mich wohl mit abfinden.

Die Bedingung in dem Code hat nur Bezug zur Zeile, also wird in allen Spalten eingefärbt.

Die Bedingung erweitern:
Delphi-Quellcode:
if (ACol = 2) and (ARow > 1) then
  //nur jetzt vergleichen und einfärben
Tutorial von www. hardcoders.de.cx, etwas älter, aber zum Einstieg geeignet.
Da www. hardcoders.de.cx wohl nicht mehr betrieben wird, hier ein Ersatzlink
http://www.ansatheus.de/_at_dokserve...stringgrid.pdf

fl63 29. Aug 2009 15:59

Re: nochmals StringGridDrawcell
 
nochmals Hallo,

Ich hab die Spalte komplett jetzt eingefärbt.
Warum er erst ab Zeile 3 färbte hatte offensichtlich etwas mit Row Count im Objektinspektor zu tun.

Danke an alle
Frank


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:49 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