AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Fragen zum Färben einer Stringgrid-Zeile

Ein Thema von stefankr · begonnen am 20. Apr 2015 · letzter Beitrag vom 22. Apr 2015
Antwort Antwort
stefankr

Registriert seit: 9. Mai 2010
24 Beiträge
 
#1

Fragen zum Färben einer Stringgrid-Zeile

  Alt 20. Apr 2015, 17:51
Hallo liebe Experten!

Ich möchte ein kleines Programm erstellen, bei dem Daten in einem Stringgrid angezeigt werden. Wenn ich auf eine Zeile des Stringgrids doppelklicke, öffnet sich an der Stelle ein PopUp-Menü mit verschiedenen Optionen, z.B. die Daten in der angeklickten Stringgrid-Zeile an einer anderen Stelle des Programms öffnen, um sie bearbeiten zu können.

Nach dem Doppelklick auf die Zeile soll diese eingefärbt werden, damit man sofort sieht, welche Zeile gerade in Verwendung ist. Das habe ich mit folgendem Code in etwa erreicht:

Delphi-Quellcode:
procedure TForm1.StringGrid1DblClick(Sender: TObject);
begin
  Form1.StringGrid1.OnDrawCell := StringGrid1DrawCell;
  GridColorCell := true;
  StringGrid1.Repaint;
  PopupMenu1.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
  Form1.StringGrid1.OnDrawCell := nil;
end;


procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var i: Integer;
begin
  if GridColorCell then
    begin
    Form1.StringGrid1.Canvas.Brush.Color:=clGreen;

    If aRow = Form1.StringGrid1.Row then
      with Form1.StringGrid1 do
      begin
        for i := (ColCount-5) to (ColCount) do
        begin
          Canvas.FillRect(Rect);
          Canvas.TextRect(Rect, Rect.Left+2, Rect.Top+5, Cells[ACol, ARow]);
        end;
      end;
    end;
end;
Wenn ich das ausführe, sieht es nach dem Doppelklick auf eine Zeile aus wie in der angehängten Bilddatei. Jetzt meine Fragen:

- Wenn ich dann einen Einzelklick auf irgendeine weiße Zelle ausführe, wird diese mit dem gepunkteten Rahmen angezeigt, und eine der grünen Zellen wird auch weiß, wie im zweiten angehängten Bild. Wie kann ich das verhindern? Ich möchte am liebsten, dass bei Einzeklicks nichts selektiert wird.
- Wie erreiche ich es, dass die weißen Zwischenräume zwischen den grünen Zellen verschwinden? Die angewählte Zeile soll durchgängig farbig sein.

Vielen Dank im Voraus für Eure Hilfe!
Miniaturansicht angehängter Grafiken
stringgrid.jpg   stringgrid2.jpg  
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.533 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Fragen zum Färben einer Stringgrid-Zeile

  Alt 20. Apr 2015, 21:04
Wenn man einmal auf den Canvas malt, dann ist das nur flüchtig (Ausnahme: Bitmaps). D.h. Du musst immer dann, wenn das Grid neu gezeichnet wird, die entsprechenden Zellen gemäß der gewünschten Logik zeichnen.

Daher solltest Du das OnDrawCell-Event belassen und Dir stattdessen merken, was die letzte doppelt geklickte Zeile war. Die malst Du dann grün, die anderen eben weiß.

Um auch den Selektionsrahmen wegzubekommen ist es das einfachste, die Eigenschaft "Defaultdrawing" des Grids auszuschalten.

So funktioniert es dann:
Delphi-Quellcode:
var
 GridColorCell: boolean = false;
 ClickedRow: Integer = -1;

 //StringGrid1.defaultdrawing im Objectinspector auf false setzen

procedure TForm10.StringGrid1DblClick(Sender: TObject);
begin
   ClickedRow := -1;
   StringGrid1.OnDrawCell := StringGrid1DrawCell;
   GridColorCell := true;
   StringGrid1.Repaint;
   PopupMenu1.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
   //Form10.StringGrid1.OnDrawCell := nil;
end;

procedure TForm10.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
  var i: Integer;
begin
   if GridColorCell then
     begin
     if ClickedRow = -1 then begin
       ClickedRow := Stringgrid1.row;
     end;

     If ClickedRow = ARow then begin
       StringGrid1.Canvas.Brush.Color:=clGreen;
       with StringGrid1 do
       begin
         for i := (ColCount-5) to (ColCount) do
         begin
           Canvas.FillRect(Rect);
           Canvas.TextRect(Rect, Rect.Left+2, Rect.Top+5, Cells[ACol, ClickedRow]);
         end;
       end;
     end else begin
       StringGrid1.Canvas.Brush.Color:=clWhite;
       stringGrid1.Canvas.FillRect(Rect);
       StringGrid1.Canvas.TextRect(Rect, Rect.Left+2, Rect.Top+5, Cells[ACol, ARow]);
     end;
   end;
end;
Übrigens solltest Du vermeiden, in dem Event direkt die Variable Stringgrid1 zu verwenden, da der Code sonst nicht mehr verwendbar ist, wenn Du z.B. auch andere Stringgrids in der Form so malen wolltest.

Besser wäre daher:

Delphi-Quellcode:
var
  sg: TStringGrind;
begin
  sg := TStringGrid (Sender);

  with sg do begin
    ....
  end;

Geändert von Harry Stahl (20. Apr 2015 um 22:33 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#3

AW: Fragen zum Färben einer Stringgrid-Zeile

  Alt 20. Apr 2015, 21:38
Falsch. Das ist eine genauso schwachsinnige Idee, wie auf Form1.Canvas zu zeichnen und sich zu wundern, wenn die Zeichnungen immer mal wieder verschwinden.

In Draw-Cell färbt man immer nur die Zelle, welche geare in den Parametern übergeben wird.
Sobald durch irgendwas dein Grid/Form nach dieser Aktion neu gezeichnet werden soll, ist alles wieder weg.
Man arbeitet also nicht mit temporären Daten.

Außerdem greifast duu innerhalb von TForm1 auf die Variable Form1 zu ... allein dafür sollte man dir auf die Finger hauen.

Es wird Du kannst in OnDrawCell auf ARow und ACol mit ClickedRow und ClickedCol vergleichen und natürlich muß die Eventmethode die ganze Zeit angehängt bleiben.
Nach dem Setzen/Ändern von ClickedRow/ClickedCol wird ein neuzeichnen des Grids ausgelöst (Grid.Invalidate).
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.533 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Fragen zum Färben einer Stringgrid-Zeile

  Alt 20. Apr 2015, 22:23
Hey Himitsu,

sei doch bitte nicht so streng mit dem Fragesteller. Offensichtlich ist das Neuland für ihn und dann muss man ja nicht gleich auf die Finger hauen.

Davon abgesehen: Du hast ja recht, dass das System nur darum bittet, dass in dem DrawCell-Event nur die eine Zelle gemalt wird. Aber verboten ist es nicht, dennoch bei der Gelegenheit in der ZEILE oder sonst wo im Grid noch was anderes zu malen, wenn es denn der Erfüllung des Programmzwecks dient (z.B. bei einer Tabellenkalkulation eine Positionsmarke im Header, zur Anzeige der aktiven Spalte im Grid).

Geändert von Harry Stahl (20. Apr 2015 um 22:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#5

AW: Fragen zum Färben einer Stringgrid-Zeile

  Alt 20. Apr 2015, 23:04
Nja, er hatte Glück, daß es zufällig fast funktiniert.

Genauso darf man gerne verkehrtrum auf der falschen Spur über die Autobahn rauschen.
Selbst wenn man dabei mit 120 km/h rückwärts fährt, bleibt es dennoch falsch und man darf sowas einfach nicht machen.

Also besser jetzt gleich ausmärtzen und es richtig machen, bevor es sich noch einbürgert.

In 20 Jahren schreibt er vielleicht mal die Firmware für die Herzlungenmaschine, an der ich später hänge und dann möchte ich nicht, daß sich darin grob fahrlässiger Code befindet.
Genauso hätte man es viel früher rigeros durchsetzen sollen, daß Programme nicht in ihr Programmverzeichnis schreiben.




Das mit den Fingern gilt nur für böse globale Variablen, if B = true then , leere Try-Except-Blöcke und Dergleichen.
Der Rest ist zwar dennoch falsch, aber das kann ja mal passieren und lässt sich reparieren.

DrawCell zeichnet nunmal nur die eine Zelle, für die der Aufruf gilt
und bei späteren Aufrufen sollte genau das selbe Verhalten erhalten bleiben, um bei eventuellen Repaints die Anzeige wiederherstellen zu können.

Delphi-Quellcode:
procedure TForm3.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
  if {(ClickedRow <> -1) and } (ClickedRow = ARow) then
    StringGrid1.Canvas.Brush.Color := clGreen
  else
    StringGrid1.Canvas.Brush.Color := clWhite;
  StringGrid1.Canvas.FillRect(Rect);
  StringGrid1.Canvas.TextRect(Rect, Rect.Left+2, Rect.Top+5, StringGrid1.Cells[ACol, ARow]);
end;


// Wenn die Zeile markiert werden soll, dann
ClickedRow := StringGrid1.Row;
StringGrid1.Invalidate; // oder StringGrid1.Repaint;

// und später, wenn die Bearbeitung fertig ist, wieder auf -1 setzen.

PS: Viele Komponenten besitzen Eigenschaften wie RowSelect und/oder HideSelection, um ein vergleichbares und vorallem einheitliches Standardverhalten hinzubekommen.



Bei vielen "ordentlichen" Grid-Komponenten kann man auch Folgendes machen, wo einfach nur die Hintergrundfarbe für das nachfolgende DefaultDrawing gesetzt wird.
Leider sind die delphieigenen Grids echt bescheiden. (in Delphi wirkt sich das nur auf den FocusRect aus)
So muß man hier auch noch den State manuell behandeln, weil hier nur "entweder" alles selber oder automatisch (Defaultverhalten) funktioniert.
Delphi-Quellcode:
// mit DefaultDrawing=True
procedure TForm3.StringGrid1CustomDrawCell(Sender: TObject; ACanvas: TCanvas: ACol, ARow: Integer; ARect: TRect; AValue: string; AState: TGridDrawState);
begin
  if {(ClickedRow <> -1) and } (ClickedRow = ARow) then
    ACanvas.Brush.Color := clGreen;
end;
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (20. Apr 2015 um 23:16 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.533 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Fragen zum Färben einer Stringgrid-Zeile

  Alt 20. Apr 2015, 23:34
Himitsu,

ja, das stimmt schon, man sollte sicher mehr grundsätzliches erklären (deswegen habe ich ja zumindest auch ein paar allgemeine Erklärungen zum malen auf den Canvas gegeben und auch den Hinweis, nicht direkt die Stringgrid-Variable im Event zu nutzen auch den Bezug zur Formvariable entfernt).

Daher hier in diesem Sinne vielleicht noch ein Tipp: In den (von mir so geschätzen und geliebten) Doberenz Büchern wird (letzte Fassung zu Delphi 7) ab Seite 337 (Kapitel 7.1 "Das Canvas-Object") alles wissenswerte zum Zeichnen auf dem Canvas erklärt. Im Kapitel "How To: Oberfläche", wird ab Seite 1040 noch einiges zum OnDrawCell-Event erläutert, etwa wie man Text mehrzeilig in einer Zelle ausgibt oder rechtsbündig zeichnet.

Bei Amazon kann man die Doberenz Bücher sogar noch kaufen.
  Mit Zitat antworten Zitat
stefankr

Registriert seit: 9. Mai 2010
24 Beiträge
 
#7

AW: Fragen zum Färben einer Stringgrid-Zeile

  Alt 21. Apr 2015, 09:41
Hallo Harry und Himitsu,

vielen Dank für Eure hilfreichen Antworten. Das Auf-die-Finger-hauen habe ich schon verkraftet, ich als Anfänger lerne eben durch "Trial and Aua"!

Ich arbeite als freiberuflicher Übersetzer und nicht als Entwickler, programmiere erst seit ein paar Monaten nebenbei. Ich habe mir ein Programm geschrieben, mit dem ich meine Kunden und Aufträge erfassen und Rechnungen drucken kann. Es funktioniert echt gut, obwohl einige sicher bei bestimmten Stellen im Code die Hände überm Kopf zusammenschlagen würden... Dieses Programm erweitere ich Schritt für Schritt, und das mit der markierten Zeile soll eben dazugehören.

Harry, das von dir genannte Buch habe ich übrigens, und es hat mir schon einige Male geholfen. Aber ich bin jemand, der wenig im Voraus liest, sondern lieber mit einem konkreten Projekt anfängt und daran lernt und bei Bedarf etwas nachschlägt. Das mit dem Canvas werde ich demnächst mal nachlesen. Leider bin ich heute und morgen außer Haus, kann also von den genannten Vorschlägen noch nichts umsetzen. Aber ich freue mich schon darauf, bald weitermachen zu können. Danke nochmal für all die Tipps, die ich von euch bekomme!
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.533 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Fragen zum Färben einer Stringgrid-Zeile

  Alt 22. Apr 2015, 00:22
@Stefankr

Du hast in Deinem letzten posting etwas erwähnt, wozu ich Dir eine private Nachricht mit einer Frage gesendet habe. Schau da bitte bei Gelegenheit mal rein.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:53 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