![]() |
Delphi hängt bei klick auf Frame
Hallo ihr Lieben,
Ich habe ein Testprogramm geschrieben, in dem ich Frames per Laufzeit in ein Formular lade. Ich habe jeden Frame so ausgestattet dass ich den angeklickten Frame 1. überall anklicken kann und das onClick Ereignis auf jeder Komponente ausgelöst wird(, ich weise also jeder Komponente bei OnClick eine von mir geschriebene Prozedur zu), und ihn 2. über die Vergabe eines einheitlichen Tags aller Komponenten, der Identisch mit dem Index des Frame-Arrays ist identifizieren kann. Im Testprogramm funktioniert das alles einwandfrei. Hier der Code zum Erstellen der Frames und der Vergabe des Tags, sowie des OnClick Ereignises: (Frame ist in beiden Programmen eine globale Variable: array of TFrame)
Delphi-Quellcode:
Und hier die FrameClick-Prozedur, in der der Frame als angeklickt markiert wird:
procedure TDialog_MainUnit.CreateFrames();
var i, j: Integer; begin try for i := 0 to 2 do begin SetLength(Frame, length(Frame) + 1); //Frame bauen: Frame[i] := TFrame_ButtonTest.Create(Self); if Assigned(TFrame_ButtonTest(Frame[i])) then begin with Frame[i] do begin Name := 'Frame' + IntToStr(i); Parent := PnlFramesBack; Align := alLeft; Tag := i; end; TFrame_ButtonTest(Frame[i]).LblName.Caption := Frame[i].Name; for j := 0 to TFrame_ButtonTest(Frame[i]).ComponentCount - 1 do begin TFrame_ButtonTest(Frame[i]).Components[j].Tag := i; TButton(TFrame_ButtonTest(Frame[i]).Components[j]).OnClick := FrameClick; TButton(TFrame_ButtonTest(Frame[i]).Components[j]).Cursor := crHandPoint; end; TFrame_ButtonTest(Frame[i]).Show; end; end; except on e: Exception do begin ShowMessage('Fehler in CreateFrames(): ' + e.Message); end; end; end;
Delphi-Quellcode:
Wie gesagt, funktioniert das alles ohne Probleme. Also wollte ich den Code meines Testprogrammes auf mein Hauptprogramm anwenden, was dann so für das Erstellen der Frames so aussieht:
procedure TDialog_MainUnit.FrameClick(Sender: TObject);
var tmpIdx, i: Integer; begin try tmpIdx := TComponent(Sender).Tag; LblFramesAktiv.Caption := 'Aktiver Frame: '; for i := Low(Frame) to High(Frame) do begin TFrame_ButtonTest(Frame[i]).IsSelected := False; TFrame_ButtonTest(Frame[i]).PnlTop.BevelOuter := bvNone; TFrame_ButtonTest(Frame[i]).PnlTop.BevelWidth := 1; end; TFrame_ButtonTest(Frame[tmpIdx]).IsSelected := True; TFrame_ButtonTest(Frame[tmpIdx]).PnlTop.BevelOuter := bvRaised; TFrame_ButtonTest(Frame[tmpIdx]).PnlTop.BevelWidth := 3; LblFramesAktiv.Caption := 'Aktiver Frame: ' + TFrame_ButtonTest(Frame[tmpIdx]).Name; except on e: Exception do begin ShowMessage('Fehler in FrameClick(): ' + e.Message); end; end; end;
Delphi-Quellcode:
Diese Funktion ist also Quasi identisch mit der aus meinem Testprogramm, bis auf dass ich die Frames im richtigen Programm vorm Createn erst lösche und ich mit einer while schleife durch meine TmpQuery gehe und dabei i inkrementiere, anstatt wie im Testprogramm i direkt mit einer for-Schleife hochzuzählen. Aber das sollte ja keinen unterschied machen... Oder?
function TDialog_Hauptprogramm.CreateFrames(): Boolean;
var i, j: Integer; function DeleteFrames(): Boolean; var i: Integer; begin Result := False; try for i := Low(Frame) to High(Frame) do begin if Assigned(Frame) then FreeAndNil(Frame[i]); end; Result := True; except on e: Exception do begin Result := False; ShowMessage('Fehler in DeleteFrames(): ' + e.Message); end; end; end; begin Result := False; try //Erst alle Frames löschen if DeleteFrames() then begin TmpQuery.Close; TmpQuery.SQL.Clear; TmpQuery.SQL.Add('SELECT * FROM meine_tabelle'); TmpQuery.SQL.Add('WHERE ID_meine_tablle2 = ' + IntToStr(SpinEdit.Value)); TmpQuery.Open; try TmpQuery.First; i := 0; while not TmpQuery.Eof do begin SetLength(Frame, length(Frame) + 1); //Frame bauen: TMein_Frame(Frame[i]) := TMein_Frame.Create(self); if Assigned(TMein_Frame(Frame[i])) then begin with Frame[i] do begin Name := 'Mein_Frame'+IntToStr(i); Parent := PnlFramesBack; Tag := i; Align := alLeft; end; //Frame ausstatten: TMein_Frame(Frame[i]).IsSelected := False; TMein_Frame(Frame[i]).PnlBack.BevelOuter := bvNone; TMein_Frame(Frame[i]).PnlBack.BevelWidth := 1; //allen Frame-Komponenten den selben tag vergeben und anklickbar machen: for j := 0 to TMein_Frame(Frame[i]).ComponentCount - 1 do begin TMein_Frame(Frame[i]).Components[j].Tag := i; TButton(TMein_Frame(Frame[i]).Components[j]).OnClick := OnFrameClick; TButton(TMein_Frame(Frame[i]).Components[j]).Cursor := crHandPoint; end; Frame[i].Show; end; TmpQuery.Next; Inc(i); end; finally TmpQuery.Close; end; ScrollBoxFrames.Refresh; end else begin Result := False; Exit; end; Result := True; except on e: Exception do begin ShowMessage('Fehler in CreateFrames(): ' + e.Message); end; end; end; Das Createn der Frames funktioniert auch im Hauptprogramm einwandfrei. Aber jetzt kommt der Knackpunkt; Hier meine OnFrameClick Prozedur vom Hauptprogramm:
Delphi-Quellcode:
Diese Prozedur ist sogar noch ähnlicher zu der FrameClick Prozedur vom Testprogramm.
procedure TDialog_Hauptprogramm.OnFrameClick(Sender: TObject);
var tmpIdx, i: Integer; begin try tmpIdx := TComponent(Sender).Tag; //alle Frames demarkieren: for i := Low(Frame) to High(Frame) do begin TMein_Frame(Frame[i]).IsSelected := False; TMein_Frame(Frame[i]).PnlBack.BevelOuter := bvNone; TMein_Frame(Frame[i]).PnlBack.BevelWidth := 1; end; //Den angeklickten Frame markieren: TMein_Frame(Frame[tmpidx]).IsSelected := True; TMein_Frame(Frame[tmpidx]).PnlBack.BevelOuter := bvRaised; TMein_Frame(Frame[tmpidx]).PnlBack.BevelWidth := 3; //mache anders Zeug... except on e: Exception do begin ShowMessage('Fehler in OnFrameClick(): ' + e.Message); end; end; end; Ich habe nun aber 2 Probleme in dieser Prozedur: 1. Das durchlaufen des Arrays, also folgende Code-passage erzeugt eine Zugriffsverletzung
Delphi-Quellcode:
Wenn ich diesen Teil auskommentiere, Habe ich diesen Fehler schon mal nicht. Allerdings brauche ich diesen Code nunmal und im Testprogramm hat es ja einwandfrei funktioniert.
for i := Low(Frame) to High(Frame) do
begin TMein_Frame(Frame[i]).IsSelected := False; TMein_Frame(Frame[i]).PnlBack.BevelOuter := bvNone; TMein_Frame(Frame[i]).PnlBack.BevelWidth := 1; end; Nun zu Problem 2: Als Progammierer denkt man sich nach dem Zugriffsverletzngsfehler natürlich: "Na gut, dann debugge ich die Prozedur halt mal und setze nen Haltepunkt an den Anfang." Wenn man das nun tut und auf den Frame klickt, hängt sich das ganze Programm auf und ich bekomme nichtmal eine Fehlermeldung. Ich kann dann weder Delphi, noch das Programm schließen und muss Delphi per Taskmanager abschießen. Was ist da los??? Im Testprogramm hatte ich das alles nicht. Woran könnte es liegen? Danke nochmal im Voraus für eure Hilfe! MFG MorrisF |
AW: Delphi hängt bei klick auf Frame
TMein_Frame(Frame[i]) := TMein_Frame.Create(self);
sieht mir falsch aus, oder? Generell könnte man auch so arbeiten, dass man eine lokale TMein_Frame variable benutzt, diese füllt und setzt und am ende Frame[i] zuweist. Dann kann man sich das gehampel und gecaste sparen. Und man könnte dann auch das i weglassen und Frame[High(Frame)] nehmen. |
AW: Delphi hängt bei klick auf Frame
Habe jetzt
Delphi-Quellcode:
durch
TMein_Frame(Frame[i]) := TMein_Frame.Create(self);
Delphi-Quellcode:
ausgetauscht. Hat allerdings keinen unterschied gemacht
Frame[i] := TMein_Frame.Create(self);
Morris |
AW: Delphi hängt bei klick auf Frame
Zitat:
Ich bräuchte TMein_Frame außerdem als globlae Variable, da ich den Frame an mehreren Stellen im Programm brauche. Hätte jemand mal ein kleines Beispiel, wie ich das mit einer globalen Variable vom Typ TMein_Frame machen könnte? |
AW: Delphi hängt bei klick auf Frame
Ich glaube ja eher, dass es irgenwas mit der von mir zugewiesenen Prozedur OnFrameClick zu tun hat, weil da bekomm ich ja den Fehler bzw wenn ich da nen Haltepunkt setze, hängt sich Delphi auf
|
AW: Delphi hängt bei klick auf Frame
Nur im Editor hingedattelt, daher keine Garantie für irgendwas ;-)
Delphi-Quellcode:
Hier wurde für Frames TMein_Frame genutzt.
function TDialog_Hauptprogramm.CreateFrames(): Boolean;
var j: Integer; myFrame : TMein_Frame; function DeleteFrames(): Boolean; var i: Integer; begin try for i := Low(Frame) to High(Frame) do begin if Assigned(Frame[i]) then FreeAndNil(Frame[i]); end; SetLength(Frame, 0); Result := True; except on e: Exception do begin Result := False; ShowMessage(Format('Fehler in DeleteFrames(): %s',e.Message])); end; end; end; begin try // Erst alle Frames löschen Result := DeleteFrames(); if Result then begin TmpQuery.Close; TmpQuery.SQL.Clear; TmpQuery.SQL.Add('SELECT * FROM meine_tabelle'); TmpQuery.SQL.Add('WHERE ID_meine_tablle2 = ' + IntToStr(SpinEdit.Value)); TmpQuery.Open; try TmpQuery.First; while not TmpQuery.Eof do begin SetLength(Frame, length(Frame) + 1); // Frame bauen: myFrame := TMein_Frame.Create(self); if Assigned(myFrame) then begin myFrame.Tag := tmpQuery.RecNo; myFrame.Name := Format('Mein_Frame_%d',[myFrame.Tag]); myFrame.Parent := PnlFramesBack; myFrame.Align := alLeft; // Frame ausstatten: myFrame.IsSelected := False; myFrame.PnlBack.BevelOuter := bvNone; myFrame.PnlBack.BevelWidth := 1; // allen Frame-Komponenten den selben tag vergeben und anklickbar machen: for j := 0 to myFrame.ComponentCount - 1 do begin myFrame.Components[j].Tag := myFrame.Tag; // Sicher, das alles nur TButtons oder deren Nachfahren sind? TButton(myFrame).Components[j]).OnClick := OnFrameClick; TButton(myFrame).Components[j]).Cursor := crHandPoint; end; myFrame.Show; Frame[High(Frame)] := myFrame; end; TmpQuery.Next; end; finally TmpQuery.Close; end; ScrollBoxFrames.Refresh; end; except on e: Exception do begin ShowMessage('Fehler in CreateFrames(): ' + e.Message); Result := False; end; end; end; Im Folgenden wird für Frames TFrame_ButtonTest. Sind die kompatibel oder ist das nur eine "BeispielquelltextZurProblemBeschreibungsdifferenz "?
Delphi-Quellcode:
Wieso brauchst Du den Frame als globale Variabel? Du hast doch zur Laufzeit n Frames?
procedure TDialog_MainUnit.FrameClick(Sender: TObject);
var tmpIdx, i: Integer; begin if not Assigned(Sender) then begin MessageDlg('Vernünftige Fehlermeldung machen.',mtError,[mbOk),0); end else if not Sender is TComponent then begin MessageDlg('Noch ''ne vernünftige Fehlermeldung machen.',mtError,[mbOk),0); end else begin try tmpIdx := TComponent(Sender).Tag; LblFramesAktiv.Caption := 'Aktiver Frame: '; for i := Low(Frame) to High(Frame) do begin TFrame_ButtonTest(Frame[i]).IsSelected := False; TFrame_ButtonTest(Frame[i]).PnlTop.BevelOuter := bvNone; TFrame_ButtonTest(Frame[i]).PnlTop.BevelWidth := 1; end; TFrame_ButtonTest(Frame[tmpIdx]).IsSelected := True; TFrame_ButtonTest(Frame[tmpIdx]).PnlTop.BevelOuter := bvRaised; TFrame_ButtonTest(Frame[tmpIdx]).PnlTop.BevelWidth := 3; LblFramesAktiv.Caption := Format('Aktiver Frame: %s', [TFrame_ButtonTest(Frame[tmpIdx]).Name]); except on e: Exception do begin ShowMessage(Format('Fehler in FrameClick(): %s', [e.Message])); end; end; end; end; |
AW: Delphi hängt bei klick auf Frame
Das DeleteFrames macht ja nur Sinn, wenn man das mehrfach neu aufbaut.
In dem Fall müsste man in DeleteFrames aber auch das Array wieder auf 0 setzen. Und seh gerade, das hier macht in DeleteFrames doch auch keinen Sinn:
Delphi-Quellcode:
Müsste doch eher sein:
if Assigned(Frame) then
FreeAndNil(Frame[i]);
Delphi-Quellcode:
if Assigned(Frame[i]) then
FreeAndNil(Frame[i]); |
AW: Delphi hängt bei klick auf Frame
Hallöle...:P
Delphi-Quellcode:
...früher gabs dafür einen mit dem Rohrstock! :warn:
TmpQuery.Close;
TmpQuery.SQL.Clear; TmpQuery.SQL.Add('SELECT * FROM meine_tabelle'); TmpQuery.SQL.Add('WHERE ID_meine_tablle2 = ' + IntToStr(SpinEdit.Value)); TmpQuery.Open; besser:
Delphi-Quellcode:
:thumb:
TmpQuery.SQL.Text := 'SELECT * FROM meine_tabelle';
TmpQuery.SQL.Add('WHERE ID_meine_tablle2 = :ID'); TmpQuery.ParamByName('ID').AsInteger := IntToStr(SpinEdit.Value); TmpQuery.Open; |
AW: Delphi hängt bei klick auf Frame
Zitat:
Mit der Code Verbesserung hast du schon mal recht! Vielen Dank!:thumb: Leider funktioniert das Programm immer noch nicht:| |
AW: Delphi hängt bei klick auf Frame
Setzt du denn jetzt die Array-Länge wieder zurück?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:58 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