Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi StringGrid -> Zelle farblich (https://www.delphipraxis.net/102085-stringgrid-zelle-farblich.html)

HolgerCW 23. Okt 2007 11:42


StringGrid -> Zelle farblich
 
Hallo zusammen,

wie kann ich eine bestimmte Zelle farblich machen ?

Wenn ich das so mache:

Delphi-Quellcode:
var
Rect: TRect;

with StringGrid do
begin

Canvas.Brush.Color := clred;
Rect := StringGrid.CellRect(5,10);
Canvas.FillRect(Rect);
Canvas.TextOut(Rect.Left+2, Rect.Top+2, Cells[5, 10]);

end;
leuchtet die Zelle nur ganz kurz rot auf.

Gruss

Holger

nachti1505 23. Okt 2007 11:46

Re: StringGrid -> Zelle farblich
 
Du machst da aber schon im OnPaint-Ereignis des StringGrid?

HolgerCW 23. Okt 2007 11:50

Re: StringGrid -> Zelle farblich
 
Ein OnPaint - Ereignis hat mein StringGrid nicht, nur ein OnDrawCell, nur das möchte ich nicht benutzen, da es ja Zelle abgeht. Ich aber nur bestimmte Zellen ansprechen will.

Gruss

Holger

nachti1505 23. Okt 2007 11:53

Re: StringGrid -> Zelle farblich
 
Meinte auch OnDrawCell...

Wirst du aber verwenden müssen, da sonst das StringGrid jedesmal deine rot gefärbten Zellen übermalt.

Glaube, irgendwie man kann prüfen, ob Spalte = 5 und Zeile = 10 ist, dann wird selber gezeichnet, sonst wird der Standard Drawhandler aufgerufen...... evt. mit inherited?

stahli 23. Okt 2007 11:53

Re: StringGrid -> Zelle farblich
 
Beispiel mit OnDrawColumnCell:

Delphi-Quellcode:
procedure TFormAw.DBGridFaelligeVorgaengeDrawColumnCell(Sender: TObject;
  const Rect: TRect; DataCol: Integer; Column: TColumn;
  State: TGridDrawState);
var ErledigtFlag:Boolean;
begin
  if (Sender is TDBGrid) then with (Sender as TDBGrid) do begin
    ErledigtFlag:=False;
    if Assigned(Column.Field) then begin
      if (Column.Field.DataSet.FindField('Erledigt')<>nil) then begin
        ErledigtFlag:=(Column.Field.DataSet.FieldByName('Erledigt').AsBoolean);
      end;
    end;
    if (ErledigtFlag) then begin
      Canvas.Brush.Color:=clSilver;//$00B3B3FF;//clYellow;
      Canvas.Pen.Color:=clBlack;//clRed;
      DefaultDrawColumnCell(Rect,DataCol,Column,State);
    end
    else
    if ((Column.Title.Caption='Termin') or (Column.Title.Caption='AbgelaufenAm')) then begin
      if Assigned(Column.Field) then begin
        if (Column.Field is TDateField) then begin
          if ((Column.Field.AsDateTime>0) and (Column.Field.AsDateTime<Date)) then begin
//            if ((Fields.FindField('Status')<>nil) and (Column.FieldByName('Status...').AsString<>'...ok')) then begin
              Canvas.Brush.Color:=$00B3B3FF;//clYellow;
              Canvas.Pen.Color:=clRed;
              DefaultDrawColumnCell(Rect,DataCol,Column,State);
//            end;
          end;
        end;
      end;
    end;
  end;
end;
stahli

HolgerCW 23. Okt 2007 12:05

Re: StringGrid -> Zelle farblich
 
Kann ich auch am Ende den Rest nachzeichnen ?

Soll heissen:

Wenn er durchgelaufen ist, also z.B. an Spalte 5 und Zeile 10 angekommen ist, soll er an Spalte 2 und Zeile 3 was nachzeichnen ?

Mein Problem ist, wenn ich bei jeder Spalte/Zeile Abfrage ob er da Zeichnen soll dauert das zu lange.

Gruss

Holger

stahli 23. Okt 2007 12:25

Re: StringGrid -> Zelle farblich
 
wüsste ich nicht...
Außerdem flackert die Darstellung dann.

Du kannst aber z.B. eine globale Variable nutzen.
In der ersten Zelle definierst Du sie und danach fragst Du sie nur noch ab.

stahli

JonnyGuitar 23. Okt 2007 13:40

Re: StringGrid -> Zelle farblich
 
in der drawcell methode werden dir doch acol und arow mitgeliefert.
wieso fragst du in dieser nicht auf acol = 5 und arow = 10 ab?


mfg Jonny

stahli 23. Okt 2007 13:59

Re: StringGrid -> Zelle farblich
 
Hallo Holger,

Jonny hat natürlich recht!

Ich habe nicht aufgepasst und dachte, Du nutzt ein DBGrid - Sorry! :oops:

(Für DBGrid stimmt, aber was ich geschrieben habe :zwinker: )

Stahli

HolgerCW 23. Okt 2007 14:38

Re: StringGrid -> Zelle farblich
 
Hi,

ich habe nur einen kleinen Teil hier nachgefragt.

Im Endeffekt habe ich 12 Zeilen und 31 Spalten.

Ich müsste also bei ACol = 1 und ARow = 1 die Datenbank abfragen, dann ACol = 2 und ARow = 1 u.s.w.

Das würde zu lange dauern.

Lese jetzt die Datenbank vorher aus und schreibe die Daten in eine Globale Variable.

Meine Frage ist nun, wann zeichnet sich das StringGrid neu, bzw. wann wird das Ereignis OnDrawCell angesteuert ?

Gruss

Holger

stahli 23. Okt 2007 14:51

Re: StringGrid -> Zelle farblich
 
Hallo Holger,

dann doch mit Datenbank? Oder sind Deine Angaben nur UNTER ANDEREM abhängig von dem Datenbankinhalt?

Hast Du sonst schon mal über ein DBGrid nachgedacht? Dann hast Du eine direkte Verbindung zur Datenbank. Bei Änderung in der DB wird auch das DBGrid neu gezeichnet.

Das StringGrid zeichnet sich (oder nur die entsprechende Zelle?) neu, wenn Du einer Zelle einen Wert zuweist (denke ich zumindest).
On DrawCell wird für jede Zelle aufgerufen, die neu gezeichnet wird.

stahli

JonnyGuitar 23. Okt 2007 14:55

Re: StringGrid -> Zelle farblich
 
@HolgerCW
ich hatte dir doch schon in dem anderen thread vorgeschlagen dir die datenmenge für die darstellung einmal komplett zu holen und dann in objekte zu speichern und diese dem grid zu übergeben. zieh das mal in erwägung, so verkehrt ist der weg nicht ;)


mfg Jonny

HolgerCW 25. Okt 2007 10:33

Re: StringGrid -> Zelle farblich
 
Habe das nun so gelöst:

1. Es werden alle Wochenenden gekennzeichnet.
2. Alle ungültigen Datums ausgegraut. Z.b.: 30.02.2007
3. Alle Urlaubs/Seminar/Sonstige - Tage mit unterschiedlichen Farben

So lese ich meine Arrays aus und bringe die Farben in mein StringGrid (STG_UP_Planer):
Delphi-Quellcode:
procedure UP_Monat_zeichnen(Sender: TObject; ACol,ARow: Integer; Rect: TRect; State: TGridDrawState);
var
 Datum: String;
 MyDate: TDateTime;
 I: Integer;
begin

 with STG_UP_Planer do
 begin

  if (ACol > 0) AND (ARow > 0) then
  begin

   Datum := inttostr(ACol) + '.' + inttostr(ARow) + '.2007';

   if trystrtodate(Datum,MyDate) = TRUE then
   begin

    //Wochenenden eintragen
    if (DayOfWeek(strtodate(Datum)) = 7) OR (DayOfWeek(strtodate(Datum)) = 1) then
    begin

     Canvas.Brush.Color := clMoneygreen;
     Canvas.FillRect(Rect);
     Canvas.TextOut(Rect.Left+2, Rect.Top+2, Cells[ACol, ARow]);

    end;

    //Urlaubstage eintragen
    for I := 0 to length(Tage) -1 do
    begin

     if (ACol = strtoint(Tage[I])) AND (ARow = strtoint(Monate[I])) then
     begin

      If Arten[I] = '1' then Canvas.Brush.Color := clRed;
      If Arten[I] = '2' then Canvas.Brush.Color := clBlue;
      If Arten[I] = '3' then Canvas.Brush.Color := clGreen;

      Canvas.FillRect(Rect);
      Canvas.TextOut(Rect.Left+200, Rect.Top+2, Cells[ACol, ARow]);

     end;

    end;

   end
   else
   begin

    //Ungültige Datums eintragen
    Canvas.Brush.Color := clSilver;
    Canvas.FillRect(Rect);
    Canvas.TextOut(Rect.Left+2, Rect.Top+2, Cells[ACol, ARow]);

   end;

  end;

 end;

end;
Vorher lese ich alle VON und BIS Datums aus mit der Art des Urlaubs, die dann mit der oberen Procedure eingetragen werden.

Delphi-Quellcode:
procedure Urlaubstage_eintagen();
var
 T: Integer;
 M: Integer;
 I: Integer;
 Laenge: Integer;
 Monat1: Integer;
 Monat2: Integer;
 Tag1: Integer;
 Tag2: Integer;
 Art: String;
begin

 I := 0;
 T := 0;
 M := 0;
 Laenge := 0;

 Tage := nil;
 Monate := nil;
 Arten := nil;
 
 //Länge der Arrays bestimmen
 DM_Query_UP.QueryPlaner.First;
 while DM_Query_UP.QueryPlaner.Eof <> true do
 begin

  Monat1 := Monthof(strtodate(DM_Query_UP.QueryPlaner['VON']));
  Monat2 := Monthof(strtodate(DM_Query_UP.QueryPlaner['BIS']));
  Tag1 := Dayof(strtodate(DM_Query_UP.QueryPlaner['VON']));
  Tag2 := Dayof(strtodate(DM_Query_UP.QueryPlaner['BIS']));

  for T := Tag1 to Tag2 do
  begin

   for M := Monat1 to Monat2 do
   begin

    Laenge := Laenge + 1;

   end;

  end;

  DM_Query_UP.QueryPlaner.Next;

 end;

 SetLength(Tage,Laenge);
 SetLength(Monate,Laenge);
 SetLength(Arten,Laenge);

 I := 0;
 T := 0;
 M := 0;

 //Urlaubstage auslesen
 DM_Query_UP.QueryPlaner.First;
 while DM_Query_UP.QueryPlaner.Eof <> true do
 begin

  Monat1 := Monthof(strtodate(DM_Query_UP.QueryPlaner['VON']));
  Monat2 := Monthof(strtodate(DM_Query_UP.QueryPlaner['BIS']));
  Tag1 := Dayof(strtodate(DM_Query_UP.QueryPlaner['VON']));
  Tag2 := Dayof(strtodate(DM_Query_UP.QueryPlaner['BIS']));
  Art := DM_Query_UP.QueryPlaner['ART'];

  for T := Tag1 to Tag2 do
  begin

   for M := Monat1 to Monat2 do
   begin

    Tage[I] := inttostr(T);
    Monate[I] := inttostr(M);
    Arten[I] := Art;

    I := I + 1;

   end;

  end;

  DM_Query_UP.QueryPlaner.Next;

 end;

end;
Weiss nicht ob das eine optimale Lösung ist, aber es funktioniert ohne merkliche Ladezeiten. (< 1 Sekunde)

Gruss

Holger


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:47 Uhr.

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