Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Gelöst: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen (https://www.delphipraxis.net/169564-geloest-algorithmus-zum-ermitteln-bestimmter-stringgrid-zellen.html)

Perlsau 29. Jul 2012 09:34


Gelöst: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Moin allerseits, heute hab ich ein eher kniffliges Problem, dessen Lösung mir partout nicht einfallen will:

Ich bastle mir gerade eine eigene Terminverwaltung mit einem StringGrid (TjvStringGrid). Via OnDrawCell manipuliere ich gewisse Zellen hinsichtlich Hintergrund- und Schriftfarbe. So sollen u.a. auch die Tage, die nicht zum aktuellen Monat gehören (ein paar in Row 1 und ein paar in der letzten Zeile) anders gefärbt werden als die zum Monat gehörenden Tage. Die Schriftfarbe dieser Zellen ist auf rot eingestellt, wie man am angehängten Screenshot sehen kann. Zu meiner Verwirrung werden die ersten Tage des nächsten Monats im Gegensatz zu den letzten Tagen des vorherigen Monats nicht rot dargestellt.

Hier einmal die OnDrawCell-Procedure:
Delphi-Quellcode:
procedure TFormTermin.StrGrid_MonatDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
VAR
   p  : Integer;
   Aus : String;

begin
     // Farbliche Markierung der Zellen mit einem Termineintrag
     Aus := StrGrid_Monat.Cells[ACol,ARow];                                                  // Zelle auslesen
     p := POS(CHR(10),Aus);                                                                  // nach Zeilenumbruch suchen
     IF p > 0 THEN                                                                           // wenn Zeilenumbruch gefunden dann
        BEGIN
             IF (ACol > 0) AND (ARow > 0) THEN                                               // wenn Spalte > 0 AND Zeile > 0 dann
             BEGIN
                  StrGrid_Monat.Canvas.Font.Color := Konst.Benutzer.TermStrGridEinColorFont; // Schriftfarbe setzen
                  StrGrid_Monat.Canvas.Brush.Color := Konst.Benutzer.TermStrGridEinColor;    // Hintergrundfarbe setzen
                  StrGrid_Monat.Canvas.FillRect(Rect);                                       // zeichnen
             END;
        END ELSE                                                                             // wenn kein Zeilenumbruch gefunden
        BEGIN
             IF (ACol > 0) AND (ARow > 0) THEN
             BEGIN
                  StrGrid_Monat.Canvas.Font.Color := Benutzer.TermStrGridColorFont;
                  StrGrid_Monat.Canvas.Brush.Color := Konst.Benutzer.TermStrGridColor;
                  StrGrid_Monat.Canvas.FillRect(Rect);
             END;
        END;

     // Aus enthält noch immer den Zellen-Inhalt
     IF Aus <> '' THEN                                                                       // wenn Aus nicht leer ist
     BEGIN
          IF TryStrToInt(Aus,p) THEN                                                         // wenn Aus eine Zahl enthält
             IF ((ARow = 1)                        AND (ACol > 0) AND (p > 7)) OR           // wenn Zeile 1 AND Spalte > 0 AND Tag > 7 oder
                ((ARow = StrGrid_Monat.ColCount -1) AND (ACol > 0) AND (p < 7)) THEN         // wenn letzte Zeile AND Spalte > 0 AND Tag < 7
                StrGrid_Monat.Canvas.Font.Color := Konst.Benutzer.TermStrGridOtherColor;
     END;

     IF ARow > 0 THEN
        StrGridAusrichtung(StrGrid_Monat, Rect, ACol, ARow, taLeftJustify, TRUE) ELSE
        StrGridAusrichtung(StrGrid_Monat, Rect, ACol, ARow, taCenter, False);

     IF ACol = 0 THEN StrGridAusrichtung(StrGrid_Monat, Rect, ACol, ARow, taRightJustify, FALSE);
Soweit ich das beurteilen kann, ist mein Algorithmus, der die ersten Tage des nächsten Monats ermitteln soll, stimmig. Aber er funktioniert nicht. Also stimmt was nicht. Nur was? Sicher wieder irgend so ein dummer Fehler, den ich vor läuter Bäumen nicht sehe ...

Helmi 29. Jul 2012 10:04

AW: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
Hallo,

ich kenne jetzt deine Konstanten (besser Records) nicht, aber müsste das hier nicht so heissen:

Delphi-Quellcode:
     IF p > 0 THEN// wenn Zeilenumbruch gefunden dann
         BEGIN
              IF (ACol > 0) AND (ARow > 0) THEN// wenn Spalte > 0 AND Zeile > 0 dann
              BEGIN
                   StrGrid_Monat.Canvas.Font.Color := Konst.Benutzer.TermStrGridEinColorFont; // Schriftfarbe setzen
                   StrGrid_Monat.Canvas.Brush.Color := Konst.Benutzer.TermStrGridEinColor; // Hintergrundfarbe setzen
                   StrGrid_Monat.Canvas.FillRect(Rect); // zeichnen
              END;
         END ELSE// wenn kein Zeilenumbruch gefunden
         BEGIN
              IF (ACol > 0) AND (ARow > 0) THEN
              BEGIN
                   StrGrid_Monat.Canvas.Font.Color := Konst.Benutzer.TermStrGridColorFont;          //<== Konst. hinzugefügt
                   StrGrid_Monat.Canvas.Brush.Color := Konst.Benutzer.TermStrGridColor;
                   StrGrid_Monat.Canvas.FillRect(Rect);
              END;
         END;

Perlsau 29. Jul 2012 10:08

AW: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
Zitat:

Zitat von Helmi (Beitrag 1176203)
Hallo,

ich kenne jetzt deine Konstanten (besser Records) nicht, aber müsste das hier nicht so heissen:

Delphi-Quellcode:
StrGrid_Monat.Canvas.Font.Color := Konst.Benutzer.TermStrGridColorFont;          //<== Konst. hinzugefügt

Ja, richtig, den hatte ich wohl übersehen. Ist aber erstmal nur ein "Schönheitsfehler", weil es im ganzen Programm sonst keinen Record gibt, der "Benutzer" heißt.

Das ist aber auch nicht mein Problem ...

Sir Rufo 29. Jul 2012 10:10

AW: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
Auf den ersten Blick sieht es so aus als ob es tatsächlich funktionieren müsste, somit könnte der Fehler bei der erfolglosen Umwandlung des Zellinhaltes in eine Zahl zu finden sein.

Abgesehen davon bin ich aber kein Freund davon von einer Dateninterpretation (Feldinhalt des Stringgrids) die Darstellung zu interpretieren. Besser wäre es hier einen Adapter zu schreiben der mit den Termindaten gefüllt wird (oder den Zugriff auf diese Objekte kennt) und der sich auch um die Befüllung des Stringgrids und das Event OnDrawCell kümmert. Dann kann man beim Zeichnen direkt auf die Terminobjekte und dessen Daten zurückgreifen und von den echten Daten die Darstellungsart ableiten.

Eine zukünftige Erweiterung wie z.B. spezielle Termine besonders einfärben ist dann ein Klacks.

Helmi 29. Jul 2012 10:17

AW: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
wo soll denn die Farbe ausgegeben werden?

Ist das dieser Block?
Delphi-Quellcode:
     // Aus enthält noch immer den Zellen-Inhalt
      IF Aus <> '' THEN// wenn Aus nicht leer ist
      BEGIN
           IF TryStrToInt(Aus,p) THEN// wenn Aus eine Zahl enthält
              IF ((ARow = 1) AND (ACol > 0) AND (p > 7)) OR// wenn Zeile 1 AND Spalte > 0 AND Tag > 7 oder
                 ((ARow = StrGrid_Monat.ColCount -1) AND (ACol > 0) AND (p < 7)) THEN// wenn letzte Zeile AND Spalte > 0 AND Tag < 7
                 StrGrid_Monat.Canvas.Font.Color := Konst.Benutzer.TermStrGridOtherColor;
      END;
Wenn ja, warum steht da
Delphi-Quellcode:
((ARow = StrGrid_Monat.ColCount -1)
müsste es nicht
Delphi-Quellcode:
((ARow = StrGrid_Monat.RowCount -1)
heissen?

Perlsau 29. Jul 2012 10:20

AW: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
Zitat:

Zitat von Sir Rufo (Beitrag 1176206)
Auf den ersten Blick sieht es so aus als ob es tatsächlich funktionieren müsste, somit könnte der Fehler bei der erfolglosen Umwandlung des Zellinhaltes in eine Zahl zu finden sein.

Glaube ich nicht. Wenn er die letzten Tage des vorigen Monats findet, dann sollte er auch die ersten Tage des letzten Monats finden. Bei den Tagen des aktuellen Monats steht ja das komplette Datum drin, da liefert TryStrToInt ein FALSE zurück. Und an der vorangestellten 0 bei den ersten Tagen des nächsten Monats kanns auch nicht liegen, die machen bei StrToInt keine Schwierigkeiten.

Zitat:

Zitat von Sir Rufo (Beitrag 1176206)
Abgesehen davon bin ich aber kein Freund davon von einer Dateninterpretation (Feldinhalt des Stringgrids) die Darstellung zu interpretieren. Besser wäre es hier einen Adapter zu schreiben der mit den Termindaten gefüllt wird (oder den Zugriff auf diese Objekte kennt) und der sich auch um die Befüllung des Stringgrids und das Event OnDrawCell kümmert. Dann kann man beim Zeichnen direkt auf die Terminobjekte und dessen Daten zurückgreifen und von den echten Daten die Darstellungsart ableiten. Eine zukünftige Erweiterung wie z.B. spezielle Termine besonders einfärben ist dann ein Klacks.

Keine Ahnung, was du dir unter einem Adapter vorstellst. Ich entwickle zum ersten Mal eine Terminverwaltung mit einem selbstgebastelten Kalender und habe noch etliche Schwierigkeiten damit, für alle anfallenden Problemstellungen Lösungen zu finden. Das ist sozusagen mein Prototyp. Wenn ich das Prinzip erstmal richtig kapiert habe, geht's an die Optimierung.

Beim Befüllen des Stringgrids wird erstmal das Stringgrid mit den reinen Monatsdaten gefüllt. Danach wird mittels SELECT die Datenmenge in der Datenbank nach Datum gefiltert (eben nur Termine mit dem Datum des aktuellen Monats).

Perlsau 29. Jul 2012 10:25

AW: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
Zitat:

Zitat von Helmi (Beitrag 1176207)
Delphi-Quellcode:
((ARow = StrGrid_Monat.ColCount -1)
müsste es nicht
Delphi-Quellcode:
((ARow = StrGrid_Monat.RowCount -1)
heissen?

Hi Helmi, du hast den Fehler entdeckt! 100 Punkte!!! :thumb:

Ich wußte doch, daß es etwas einfaches sein muß, das ich nur mal wieder nicht sehe :lol:

Jetzt funktioniert es so, wie ich es wollte.

Bjoerk 29. Jul 2012 11:35

AW: Gelöst: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
Ist sichergestellt, daß diese Methode erst dann aufgerufen wird, wenn das Grid schon auch Daten hat?

Mit Sys- bzw. DateUtils tust du dir leichter.

Ungetestet:

Delphi-Quellcode:
function ExtractDate(const S: string): string;
var
  L: integer;
begin
  L := Pos(sLineBreak, S);
  if L > 0 then
    Dec(L)
  else
    L:= Length(S);
  Result := Copy(S, 1, L);
end;

function CheckDate(const S: string): boolean;
var
  ADate: TDateTime;
  AYear, AMonth, ADay: Word;
begin
  Result := false;
  if SysUtils.TryStrToDate(ExtractDate(S), ADate) then
  begin
    SysUtils.DecodeDate(ADate, AYear, AMonth, ADay);
    Result := DateUtils.IsValidDate(AYear, AMonth, ADay);
  end;
end;

procedure TForm1.StrGrid_MonatDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  Ausrichtung: TAlignment;
  AusrichtungFlag: boolean;
begin
  if CheckDate(StrGrid_Monat.Cells[ACol, ARow]) then
  begin
    if Pos(sLineBreak, StrGrid_Monat.Cells[ACol, ARow]) > 0 then
    begin
      StrGrid_Monat.Canvas.Font.Color := Konst.Benutzer.TermStrGridEinColorFont;
      StrGrid_Monat.Canvas.Brush.Color := Konst.Benutzer.TermStrGridEinColor;
    end
    else
    begin
      StrGrid_Monat.Canvas.Font.Color := Konst.Benutzer.TermStrGridColorFont;
      StrGrid_Monat.Canvas.Brush.Color := Konst.Benutzer.TermStrGridColor;
    end;
  end
  else
  begin
    StrGrid_Monat.Canvas.Font.Color := Konst.Benutzer.TermStrGridOtherColor;
    StrGrid_Monat.Canvas.Brush.Color := Konst.Benutzer.TermStrGridColor;
  end;
  StrGrid_Monat.Canvas.FillRect(Rect);
  if ACol = 0 then
  begin
    Ausrichtung := taRightJustify;
    AusrichtungFlag := false;
  end
  else
    if ARow > 0 then
    begin
      Ausrichtung := taLeftJustify;
      AusrichtungFlag := true;
    end
    else
    begin
      Ausrichtung := taCenter;
      AusrichtungFlag := false;
    end;
  StrGridAusrichtung(StrGrid_Monat, Rect, ACol, ARow, Ausrichtung, AusrichtungFlag);
end;

Jumpy 29. Jul 2012 16:07

AW: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
Zitat:

Zitat von Perlsau (Beitrag 1176208)
Zitat:

Zitat von Sir Rufo (Beitrag 1176206)
Abgesehen davon bin ich aber kein Freund davon von einer Dateninterpretation (Feldinhalt des Stringgrids) die Darstellung zu interpretieren. Besser wäre es hier einen Adapter zu schreiben der mit den Termindaten gefüllt wird (oder den Zugriff auf diese Objekte kennt) und der sich auch um die Befüllung des Stringgrids und das Event OnDrawCell kümmert. Dann kann man beim Zeichnen direkt auf die Terminobjekte und dessen Daten zurückgreifen und von den echten Daten die Darstellungsart ableiten. Eine zukünftige Erweiterung wie z.B. spezielle Termine besonders einfärben ist dann ein Klacks.

Keine Ahnung, was du dir unter einem Adapter vorstellst. Ich entwickle zum ersten Mal eine Terminverwaltung mit einem selbstgebastelten Kalender und habe noch etliche Schwierigkeiten damit, für alle anfallenden Problemstellungen Lösungen zu finden. Das ist sozusagen mein Prototyp. Wenn ich das Prinzip erstmal richtig kapiert habe, geht's an die Optimierung.

Er meint glaub ich damit, dass du eine Struktur schaffen sollst, in der die Daten gespeichert werden. Das Grid soll nur zur Darstellung dienen. So sollst du dann quasi im OnDraw nicht schauen, was steht in der Grid-Zelle, sondern was steht in der Datenstruktur was für ein Wert in dieser Zelle steht, bzw. noch besser, was sagt mir die Datenstruktur, wie ich diese Zelle färben soll. Das geht dann denk ich in Richtung MVC.

Perlsau 29. Jul 2012 18:31

AW: Algorithmus zum Ermitteln bestimmter StringGrid-Zellen
 
Zitat:

Zitat von Jumpy (Beitrag 1176232)
Er meint glaub ich damit, dass du eine Struktur schaffen sollst, in der die Daten gespeichert werden. Das Grid soll nur zur Darstellung dienen. So sollst du dann quasi im OnDraw nicht schauen, was steht in der Grid-Zelle, sondern was steht in der Datenstruktur was für ein Wert in dieser Zelle steht, bzw. noch besser, was sagt mir die Datenstruktur, wie ich diese Zelle färben soll. Das geht dann denk ich in Richtung MVC.

Ich habe bereits eine Struktur zur Speicherung der Daten: eine Firebird-Datenbank. In dieser ist aber nicht vermerkt, an welchem Wochentag ein bestimmter Termin ist oder in welcher Spalte im StringGrid er steht. Ich möchte ja das Stringgrid je nach aktuellem Status so oder so aussehen lassen. Daher lese ich auch am Stringgrid aus, wie es sich derzeit befindet ... Natürlich könnte ich das auch aus den Daten in der DB ausrechnen. Da ich aber sowieso auf das OnDrawCell-Ereignis reagieren muß und dort auf bestimmte Spalten und Zeilen abfragen muß, ob und wie sie (hinsichtlich aktuellem Monat und Jahr bzw. hinsichtlich ihres Inhalts) manipuliert werden sollen. Ich will ja nicht nur Zellen manipulieren, in denen ein oder mehrere Termine stehen, sondern auch Zellen, in denen keine stehen. Wieso also sollte ich diese Manipulation einmal in einem extra "Adapter" machen und dann nochmal in OnDrawZell? Ich finde das so einfacher ...

Und was ist MVC?


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:11 Uhr.
Seite 1 von 2  1 2      

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