Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Fontfarbe in TStringgrid ändern ;-) (https://www.delphipraxis.net/192590-fontfarbe-tstringgrid-aendern-%3B.html)

Roadrunner.1 3. Mai 2017 09:25

Fontfarbe in TStringgrid ändern ;-)
 
Hi Zusammen,

ja, ja, ja, die Frage wurde schon 1000 mal gestellt und ich soll die Suche verwenden. Also nach einer Stunde bekomme ich MEIN Problem
nicht gelöst. Vielleicht liegt es aber auch Delphi XE5 und jemand hat eine Idee.

Also was will ich?
Bestimmte Einträge in einem Stringgrid in einer anderen Fontfarbe darstellen. Standartantwort wäre z.B.:

procedure TForm.SGDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
State: TGridDrawState);
begin
if (ACol=4) and (ARow>0) then begin
with SG.Canvas do begin
Font.Color:=clred;
FillRect(Rect);
Textout(Rect.Left+2,Rect.Top+2, SG.Cells[ACol,ARow]);
end;
end;
end;

Merkwürdig daran ist, das auch alle anderen Zellen gemalt werden. Wie's mir scheint wird hier ÜBERMAHLT nicht "statt dessen" gemalt, oder?

OK. Nun zu meinem Problem: Hat eine übermalte Zelle den Fokus (sieht dann anders aus, aber für meine Zwecke OK) und gehe ich dann mit TAB
aufs nächste Steuerelement, so wird der Eintrag nicht rot sondern schwarz dargestellt! Selbst ein Repaint, Invalid oder die Zuweisung eines neuen
Textes in der onExit des Stringgrids führt zu keiner Besserung. Folgendes führt zu einer Standartfarben (schwarz) Ausgabe:

procedure TForm.SGExit(Sender: TObject);
begin
with SG do begin
Cells[4,4]:='Test';
end;
end;

Das "Test" erscheint also in schwarz statt in rot wenn beim Fokuswechsel diese Zelle markiert war. War hingegen eine andere markiert wird
"Test" in rot dargestellt!

Meine letzte Idee war DrawCell in onExit aufzurufen, aber wo bekom' ich mein Rect Parameter her, und wieso ist das alles so aufwendig?
Des Weiteren hab' ich Breakpoints gesetzt, und DrawCell wird nach der Zuweisung in OnExit schon mit ACol=4 und ARow=4 aufgerufen, aber
dieser Eintrag nicht rot dargestellt.

Hat irgend einer eine Idee?

Jasocul 3. Mai 2017 09:58

AW: Fontfarbe in TStringgrid ändern ;-)
 
Auch wenn ich noch nicht ganz schlau aus deiner Beschreibung werden:
Schmeiß das verdammte "WITH" aus deinem Source. Es kann durchaus sein, dass damit dein Problem schon behoben ist.

Roadrunner.1 3. Mai 2017 10:34

AW: Fontfarbe in TStringgrid ändern ;-)
 
Hallo Peter,

danke fürs lesen. Aber am With liegt's mit hoher Wahrscheinlichkeit nicht, weil das ja nichts mit dem Fokus (Programmablauf) zu tun hat.

Hier vielleicht nochmal kurz was das Problem ist:

Ist eine Zelle in einem Stringgrid über onDrawCell "gemahlt" und hat den Fokus, und wird dann via Tastatur mittels der
Taste "Tab" aufs nächste Steuerelement gewechselt, wird die eigenen onDrawCell nicht nochmal aufgerufen (obwohl sich das
Aussehen ändert). Auch ein erneutes Zuweisen des Inhaltes, und damit das Aufrufen von onDrawCell in der onExit, führt nicht
zum gewünschten Ergebnis, weil wohl nach onExit da nochmal drüber gemahlt wird.

Den Effekt hab' ich auch wenn ich mit der Maus ein anderes Steuerelement wähle.

Was ich bräuchte wäre ein "Wenn Stringgrid Fokus verliert, onDrawCell der Fokusverlierenden Zelle aufrufen". Wie geschrieben
geht das in onExit des Stringgrids wohl leider nicht.

Roadrunner.1 3. Mai 2017 11:12

AW: Fontfarbe in TStringgrid ändern ;-)
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier mal ein komplettes Programm. Formular, Stringgrid, Button

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Grids;

type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
Button1: TButton;
procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
State: TGridDrawState);
begin
if (ACol=4) and (ARow>0) then begin
with StringGrid1.Canvas do begin
Font.Color:=clred;
FillRect(Rect);
Textout(Rect.Left+2,Rect.Top+2, StringGrid1.Cells[ACol,ARow]);
end;
end;
end;
end.
(Options von TStringgrid zusätzlich zum Default: goEditing, goAlwaysShowEditor)

Nach meinem Verständnis sollte folgendes Bild nicht möglich sein einzugeben (Die 12345 müsste rot sein) Siehe Anhang:
Hierzu einfach Spalte 4 gefüllt, Spalte 5 gefüllt dann einen anderen Wert von Spalte 5 ausgewählt und TAB gedrückt.

Sie steht auch weiter links und höher, vermutlich funkt der InplaceEditor dazwischen, aber wie und wann schalte ich den ab,
damit der nicht nach mir nochmal drüber malt? In onExit hatte ich jetzt schon versuchsweise das goEditing und goAlwaysShowEditor
abgeschaltet, aber hübsch ist anders (Blauer Hintergrund bleibt, fette Schriftart und falsche Ausrichtung).

Oder sollte ich versuchen dort die Schriftart zu Ändern? Geht das überhaupt?

Roadrunner.1 3. Mai 2017 14:39

AW: Fontfarbe in TStringgrid ändern ;-)
 
OK, falls es noch interessiert, oder falls jemand eine bessere Lösung hat, hier wie ich es jetzt gelöst habe.

Im onExit versetz ich den Fokus um eine Zelle nach links.
Im onEnter setzt ich den Fokus auf 0,Row.
Im CanSelectCell wird dann der Fokus auf die Eingabespalte versetzt (macht die sowieso schon, damit der User nur die Zeile klicken braucht).

Damit onExit auf eine nicht erlaubte Spalte setzen kann, Variable die sich merkt ob gerade onExit läuft.
Um Spalte und Zeile gleichzeitig setzen zu können eine ReEnter Sperre für CanSelectCell.

Von Nachteil ist jetzt vor allem, das wenn der User den Fokus auf den Stringgrid ändert, dass dann
die bis dahin rote Zahl wieder schwarz wird... Wäre wohl zu lösen wenn der gesammte Text der Zelle als
markiert dargestellt werden würde, aber hier half bisher nicht mal ein SelectAll für den InplaceEditor.

scrat1979 3. Mai 2017 22:10

AW: Fontfarbe in TStringgrid ändern ;-)
 
Schau dir mal von Bergsoff Das NextGrid an. Ist einfach der Hammer und beherrscht das was du möchtest... Der Umstieg lohnt sich in jedem Fall und die Bedienung ist super simple!

Jasocul 4. Mai 2017 06:50

AW: Fontfarbe in TStringgrid ändern ;-)
 
Gestern hatte ich leider keine Zeit mehr, um mir das Problem nochmal genauer anzusehen.

Soweit ich mich erinnern kann, musst du dich immer um das Zeichnen jeder Zelle kümmern. Also nicht nur bei denen, die du anders darstellen willst.
Ich kann es hier im Moment nicht testen (gerade kein Delphi verfügbar), aber wenn du den Source in etwa so änderst, sollte es besser funktionieren:
Delphi-Quellcode:
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
 State: TGridDrawState);
var
  grdCanv : TCanvas; // Dadurch kürze Schreibweise ohne das "WITH"
  OldColor : TColor;
begin
  grdCanv := StringGrid1.Canvas;
  OldColor := grdCanv.Font.Color;
  if (ACol=4) and (ARow>0) then begin
    grdCanv.Font.Color:=clred;
  end;
  grdCanv.FillRect(Rect);
  grdCanv.Textout(Rect.Left+2,Rect.Top+2, StringGrid1.Cells[ACol,ARow]);
  // Statt Textout ist vielleicht TextRect die bessere Wahl
  grdCanv.Font.Color := OldColor;
end;
Auch wenn das "with" hier nicht das Problem ist, solltest du es vermeiden. Es verursacht immer wieder mal Probleme.

Uwe Raabe 4. Mai 2017 07:30

AW: Fontfarbe in TStringgrid ändern ;-)
 
Zitat:

Zitat von Jasocul (Beitrag 1370119)
Soweit ich mich erinnern kann, musst du dich immer um das Zeichnen jeder Zelle kümmern. Also nicht nur bei denen, die du anders darstellen willst.

Um das etwas zu präzisieren: Das wird über das Property
Delphi-Quellcode:
DefaultDrawing
gesteuert. Ist das true, malt das StringGrid vor dem Event schon mal den Text in die Zelle. Das ist der Übermalen-Effekt, den du schon bemerkt hast. Wenn DefaultDrawing auf False steht, musst du aber eben auch alle Zellen selbst malen. Dabei solltest du allerdings den Inhalt des State-Parameters berücksichtigen.

Weiterhin gibt es zu bedenken, daß ein aktiver Editor in einer Zelle selbst das Malen übernimmt. Da du goAlwaysShowEditor aktiv hast, bleibt der InplaceEditor sichtbar (und auch für die Textdarstellung zuständig) wenn du das Grid verlässt.

bcvs 4. Mai 2017 08:19

AW: Fontfarbe in TStringgrid ändern ;-)
 
Wie Uwe schon gesagt hat, malt der Inplace-Editor den Text neu, wenn das Grid den Focus verliert. Dabei kannst du die Textfarbe nicht beeinflussen. Das OnDrawCell des Grid ist hier nicht mehr zuständig.

Im OnExit den Text neu zu malen ist auch keine Option, denn das kommt zu früh. Der Inplace-Editor malt später nochmal drüber.

Man muss also eine Möglichkeit finden, den Text verzögert zu malen, nachdem der Inplace-Editor fertig ist.

Deshalb meine Lösung mit einem Timer:

Nimm einem Timer, setze Enabled auf false und Interval auf 10.

Im OnExit des Grid setzt du nur
Delphi-Quellcode:
Timer.enabled:=true;
Der Timer-Event sieht dann so aus:
Delphi-Quellcode:
procedure TForm1.TimerTimer(Sender: TObject);
var Rect: TRect;
begin
  if (StringGrid1.Col=4) and (StringGrid1.Row>0) then begin
    Rect:=StringGrid1.CellRect(StringGrid1.Col, StringGrid1.Row);
    StringGrid1.Canvas.Font.Color:=clred;
    StringGrid1.Canvas.FillRect(Rect);
    StringGrid1.Canvas.Textout(Rect.Left+2,Rect.Top+2, StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row]);
    Timer.Enabled:=false;
  end;
end;
Nicht besonders schön, funktioniert aber.

Uwe Raabe 4. Mai 2017 08:22

AW: Fontfarbe in TStringgrid ändern ;-)
 
Zitat:

Zitat von bcvs (Beitrag 1370124)
Man muss also eine Möglichkeit finden, den Text verzögert zu malen, nachdem der Inplace-Editor fertig ist.

... oder man nimmt das goAlwaysShowEditor weg.


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