![]() |
Buttons in Stringgrid
Hi Leute
Ich habe ziemlich lange gegoogelt, leider nichts passendes gefunden. Auch hier in Forum konnte ich keine Antwort auf meine Frage finden. Vielleicht packe ich es falsch an. Nun zum Problem Ich versuche eine Tabelle zu erstellen, soweit so gut, (Stringgrid) Das letzte Row sollte aber als Button dargestellt werden und beim click sollte die Zeile gelöscht werden. Hier ist mein TestProjekt Es wird nur ein Stringgrid benötigt
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,Buttons, Grids; type TForm1 = class(TForm) StringGrid1: TStringGrid; procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); procedure FormCreate(Sender: TObject); procedure MyClick(Sender: TObject); procedure MyClick2(Sender: TObject) ; private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; Btn: array [1 .. 100] of TSpeedButton; I : Integer; implementation {$R *.dfm} procedure StringgridDeleteRow(const Grid : TStringGrid; RowNumber : Integer); var i : Integer; begin for i := RowNumber to Grid.RowCount - 2 do Grid.Rows[i].Assign(Grid.Rows[i+ 1]); Grid.Rows[Grid.RowCount-1].Clear; Grid.RowCount := Grid.RowCount - 1; end; procedure TForm1.FormCreate(Sender: TObject); begin for I := 1 to StringGrid1.RowCount -1 do begin Btn[I] := TSpeedButton.create(self); Btn[I].parent := Stringgrid1; Btn[I].Caption := 'Löschen ' + inttostr(i); //if i = 1 then Btn[I].OnClick := MyClick; //StringgridDeleteRow(StringGrid1, 2); //if i = 2 then // StringgridDeleteRow(StringGrid1, 3); // Btn[I].OnClick := MyClick2; end; Stringgrid1.ColWidths[0] := 30; Stringgrid1.ColWidths[1] := 100; Stringgrid1.ColWidths[2] := 150; Stringgrid1.ColWidths[3] := 250; Stringgrid1.ColWidths[4] := 100; StringGrid1.Cells[0,0] := 'Nr:'; StringGrid1.Cells[1,0] := 'Serie'; StringGrid1.Cells[2,0] := 'Folge'; StringGrid1.Cells[3,0] := 'Adresse'; StringGrid1.Cells[4,0] := 'Löschen'; end; procedure TForm1.MyClick(Sender: TObject) ; begin showmessage('Button'); end; procedure TForm1.MyClick2(Sender: TObject) ; begin showmessage('Button 2'); end; procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); begin {Das gehört zum Button erstellen ***************************} with TStringGrid(Sender) do if (Acol >= Fixedcols) and (ARow >= Fixedrows) then begin if (ACol = 4) then begin Btn[ARow].BoundsRect := Rect; Btn[ARow].visible := true; end; end; {************************************************************} end; end. Ich habe versucht ein Parameter an die MyClick Procedur zu schicken. Das geht wohl nicht. Google hat's bestätigt. Dann habe ich versucht global ein Integer zu deklarieren und an Btn[I] abzukoppeln. Das geht auch nicht. Nur wenn ich für jeden Button ein OnClick Ereignis erstelle funktioniert es. Das Problem ist aber ich wei0 nicht wie viel Zeilen es werden, bzw. die Zeilen werden ständig gelöscht und neu erstellt. In meinem Testcode habe ich es eingefügt wie ich es meine. Anreize wie man es lösen könnte wären gerne gesehen. Ich bin nur ein Anfänger also bitte habt Verständnis für mich. Gerne schaue ich mir andere Methode, wie man es lösen könnte. Wichtig ist nur. Es werden Zeilen hinzugefügt und sollten per Button in der letzten Spalte wider gelöscht werden können. Jede Hilfe ist gerne willkommen. |
AW: Buttons in Stringgrid
Ich würde den Button einfach nur hinmalen (OnDrawCell und in den nötigen Mausereignissen) und die Klickereignisse des StringGrid entsprechend auswerten.
PS: Die Buttons haben ein .Tag, wo man sich eine Nummer drin speichern kann, oder man vergleicht die Instanz des geklickten Buttons (Sender im OnClick) mit den Instanzen im Array. Wobei man die Buttons auch direkt an das Daten-Property der jeweiligen Row hängen könnte. Wozu ist das I global, wo es doch nur lokal im OnCreate verwendet wird? Und wieso liegt btn nicht im Privateabschnitt der Form? (Globale sind böse) |
AW: Buttons in Stringgrid
Prinzipiell verstehe ich was du damit meinst
Zitat:
Was das I global angeht, klar reicht es das I local zu deklarieren. Das entstand weil ich aus Verzweiflung alles mögliche probiert habe. Dazu gehört globale Deklaration von I und paar andere Parameter, die ich aber aufgegeben habe. Könntest du mir deine Erklärung etwas genauer erklären ? Am liebsten mit einem kleinen Beispiel. Muss nicht auf meine Vorlage bezogen werden , Hauptsache ich schnalle wie es geht. Wie gesagt, ich bin noch ein Anfänger. |
AW: Buttons in Stringgrid
hilft da nicht StringGrid1.onFixedCellClick ? Da sind bereits Schalter, da brauchst du nur drauf Antworten.
procedure FixedCellClick(Sender: TObject; ACol, ARow: Integer); Es wird dir Zeile und Spalte übergeben |
AW: Buttons in Stringgrid
Wenn du nach wie vor auf eigene Schalter bestehst, dann hilft dir vielleicht folgender Code weiter:
Delphi-Quellcode:
das habe ich aus dem sogenannten Kochbuch von Doberenz und Kowalski.
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, StdCtrls; type TForm1 = class(TForm) StringGrid1: TStringGrid; ComboBox1: TComboBox; Label1: TLabel; procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); procedure ComboBox1Change(Sender: TObject); procedure StringGrid1TopLeftChanged(Sender: TObject); procedure FormCreate(Sender: TObject); procedure setRect(rec: TRect); // per Hand eintragen! private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} // Beim Laden des Formulars werden die notwendigen Initialisierungen des StringGrid durchgeführt: procedure TForm1.FormCreate(Sender: TObject); begin with StringGrid1 do begin // Spalten: ColCount := 8; ColWidths[0] := 80; // erste Spalte 80 Pixel breit Cells[0,0] := 'Zeitraum'; Cells[1,0] := 'Sonntag'; Cells[2,0] := 'Montag'; Cells[3,0] := 'Dienstag'; Cells[4,0] := 'Mittwoch'; Cells[5,0] := 'Donnerstag'; Cells[6,0] := 'Freitag'; Cells[7,0] := 'Sonnabend'; // Zeilen: RowCount := 4; Cells[0,1] := ' 6:00 - 14:00'; Cells[0,2] := '14:00 - 22:00'; Cells[0,3] := '22:00 - 6:00'; DefaultRowHeight := Combobox1.Height; Options := Options + [goTabs]; end end; // Positionierung der Combobox (muss als Methode von Form1 deklariert werden): procedure TForm1.setRect(rec: TRect); var r: TRect; begin with ComboBox1 do begin CopyRect(r, rec); // rec => r (Eck-Koordinaten an Hilfsrechteck übergeben) // Umrechnung der Eck-Koordinaten des Hilfsrechtecks: r.BottomRight := Parent.ScreenToClient(StringGrid1.ClientToScreen(r.BottomRight)); r.TopLeft := Parent.ScreenToClient(StringGrid1.ClientToScreen(r.TopLeft)); // Positionierung der Combobox (Left, Top, Width und Height werden zugewiesen): SetBounds(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top); BringToFront // Combobox in Vordergrund bringen end end; // Im OnDrawCell-Event wird Combobox exakt über die Zelle positioniert: procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); begin if (ACol >= StringGrid1.FixedCols) and (ARow >= StringGrid1.FixedRows) and (gdFocused in State) then setRect(Rect); end; // Comboboxinhalt wird in Zelle übertragen: procedure TForm1.ComboBox1Change(Sender: TObject); begin Beep; with StringGrid1 do Cells[Col, Row] := ComboBox1.Text end; //Der folgende Eventhandler versteckt die Combobox, wenn sie aus dem StringGrid "herausgescrollt" wird: procedure TForm1.StringGrid1TopLeftChanged(Sender: TObject); begin with StringGrid1 do setRect(CellRect(Col,Row)); end; end. Klappt aber, ich habe es mit eine TColorBox programmiert, sollte auch mit TButton funktionieren |
AW: Buttons in Stringgrid
Danke an Alle
@himitsu dein Ansatz hat mich auf die Lösung verwiesen. Hier das Relevante
Delphi-Quellcode:
Es funktioniert einwandfrei.
procedure TForm1.FormCreate(Sender: TObject);
var I : Integer; begin for I := 1 to StringGrid1.RowCount -1 do begin Btn[I] := TSpeedButton.create(self); Btn[I].Caption := 'Löschen'; Btn[I].Name := 'Löschen' + inttostr(i); Btn[I].parent := Stringgrid1; Btn[I].visible := false; Btn[I].Tag := 100 + I; Btn[I].OnClick := MyClick; FreeOnRelease; end; procedure TForm1.MyClick(Sender: TObject) ; var I:Integer; begin for I := 1 to StringGrid1.RowCount do begin if Sender = FindComponent('Löschen' + IntToStr(I)) then begin showmessage('Lösche Zeile ' + IntToStr(I) ); end; end; end; @Peter-Pascal Ich bin auf dein Tip nicht eingegangen weil ich schon sehr tief an meiner Lösung gegraben habe. Danke trotzdem. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:38 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