![]() |
"OnClick" Ereignis in Frame auslösen
Hallo ihr lieben Bewohner des Delphi-PRAXIS Forums,
ich habe folgende Grundsituation: Ich habe ein Formular und eine Frame-Unit. Den Frame habe ich auf das Formular gepackt. Nun habe ich auf dem Frame einen Button und wenn der gedrückt wird, soll sich ein Label auf dem Formular ändern (damit man sieht, obs geklappt hat). Hier der Code für Das OnClick Event des Buttons im Frame:
Delphi-Quellcode:
Und hier der Code im Hauptformular:
procedure TFrame_ButtonTest.BtnClickMeClick(Sender: TObject);
begin try Self.OnClick(Self); except on e: Exception do begin ShowMessage('Fehler in BtnClickMeClick(): ' + e.Message); end; end; end;
Delphi-Quellcode:
Meine Frage nun:
procedure TDialog_MainUnit.FormCreate(Sender: TObject);
var tmpFrame: TFrame_ButtonTest; tmpSender: TObject; begin try tmpFrame := TFrame_ButtonTest.Create(self); try if Assigned(tmpFrame) then begin tmpFrame.BtnClickMe.OnClick := FrameButtonClick(tmpSender); tmpFrame.BtnClickMeClick(tmpSender) := FrameButtonClick(tmpSender); //beide Varianten gehen nicht end; finally tmpFrame.Free; end; except on e: Exception do begin ShowMessage('Fehler in FormCreate(): ' + e.Message); end; end; end procedure TDialog_MainUnit.FrameButtonClick(Sender: TObject); begin try LblText.Caption := 'Dat geht gut!'; except on e: Exception do begin ShowMessage('Fehler in FrameButtonClick(): ' + e.Message); end; end; end; Wie kann ich das OnClick Event vom Button im Frame der Prozedur "FrameButtonClick()" im Hautpformular zuweisen? Oder gibt es einen einfacheren Weg, um den Text auf dem Label im Hautpformular per Klick auf den Button im Frame zu ändern? Vielen Dank im Voraus für eure Antworten und Ratschläge. MFG Morris F. |
AW: "OnClick" Ereignis in Frame auslösen
Delphi-Quellcode:
tmpFrame.BtnClickMe.OnClick := FrameButtonClick;
|
AW: "OnClick" Ereignis in Frame auslösen
Zitat:
Wenn ich das aber so mache, bekomme ich beim kompilieren eine Zugriffsverletzung. Was ist also noch falsch? (Aber immerhin kann ich es jetzt kompilieren.) |
AW: "OnClick" Ereignis in Frame auslösen
Zugriffverletzung beim Kompilieren?
An welcher Stelle? Im FormCreate erstellst Du 'nen Frame. Weist dem OnClick-Ereignis seines Buttons 'ne Routine zu. Gibst den Frame wieder frei. Damit sind Frame und Button weg, zur Laufzeit wird es dann keinen Button geben, der auf OnClick reagieren kann und die zugewiesene Routine aufruft. Auf LblText.Caption wird daher nie der Text 'Dat geht gut!' erscheinen. (Müsste es nicht 'Dat jeht jut!' heißen? ;-)) Irgendwie verstehe ich nicht, was Du gerade beabsichtigst. |
AW: "OnClick" Ereignis in Frame auslösen
Hi MorrisF
Das kannst du dir sparen:
Delphi-Quellcode:
TFrame_ButtonTest ist der Basisframe, den du dir unter <Datei=>Neu=>weiter=>(??)Frame erstellt hast. Wenn du nun diesen Frame auf die Form legen willst, findest du ihn (sofern eer zum Projekt gehört) im OI unter Standard=>Frames. Wenn du ihn hier anklickst und anschliessend auf die Form klickst, öffnet sich ein Dialog, in dem sämtliche für dieses Projekt definierten Frames aufgeführt sind. Klich ihn hier an, und er wird dir auf der Form eingefügt - allerdings nicht der Basisframe, den du entwickelt hast, sondern eine Instanz davon, zB. DeinFrame1.
procedure TFrame_ButtonTest.BtnClickMeClick(Sender: TObject);
begin try Self.OnClick(Self); except on e: Exception do begin ShowMessage('Fehler in BtnClickMeClick(): ' + e.Message); end; end; end; Diese Instanz erbt vom Basisframe alle public deklarierten Methoden, also auch dein Button.OnClick. Startest du nun dein Programm, siehst du diese Instanz, inklusive dem Button, den du auf dem Basisframe eingefügt hast. Klicke ihn, um den Code auszuführen, den du für den Button definiert hast. Es reicht also vollkommen, wenn du im OnClick des Basisframes folgenden Code einfügst:
Delphi-Quellcode:
FBoolean solltest du in diesem Fall als privates Feld des Basisframes deklarieren.
procedure TFrame_ButtonTest.BtnClickMeClick(Sender: TObject);
begin if FBoolean then Mainfrm.Edit1.Color := clred else Mainfrm.Edit1.Color := clyellow; end; Gruss Delbor PS: Sehe gerade, dass du deine Frameinstanz dynamisch erstellst:
Delphi-Quellcode:
TFrame_ButtonTest darf hier allerdings nicht der Name deines Basisframes sein. Ansonsten bleibt sich alles gleich.
try
tmpFrame := TFrame_ButtonTest.Create(self); |
AW: "OnClick" Ereignis in Frame auslösen
Hi MorrisF
Zitat:
Delphi-Quellcode:
Gruss
procedure TCM_First.CreateMainSectionFrames;
begin SelectAllPicturesFrame1 := TSelectAllPicturesFrame.Create(CM_First); SelectAllPicturesFrame1.Parent := PnlMainFrames; SelectAllPicturesFrame1.Align := alClient; SelectAllPicturesFrame1.Visible := False; FotoProjectFrame1 := TFotoProjectFrame.Create(CM_First); FotoProjectFrame1.Parent := PnlMainFrames; FotoProjectFrame1.Align := alClient; FotoProjectFrame1.Visible := False; DisplayImportPicFrame1 := TDisplayImportPicFrame.Create(Self); DisplayImportPicFrame1.Parent := PnlMainFrames; //<===4 DisplayImportPicFrame1.Align := alClient; DisplayImportPicFrame1.Visible := False; TestFrame1 := TTestFrame.Create(CM_First); TestFrame1.Parent := PnlMainFrames; //<===3 TestFrame1.Align := alClient; TestFrame1.Visible := False; end; Delbor |
AW: "OnClick" Ereignis in Frame auslösen
Vielen Dank, für die vielen Antworten und die Hilfe!
Ich hab jetzt noch ein wenig rumprobiert und mich dazu entschlossen, den Frame in der Laufzeit(im Code) auf das Hauptformular einzufügen. Habe auch im der Frame-Unit die unnötige Prozedur auskommentiert und es geht! Vielen Danke euch allen!:thumb: Hier der Code den ich benutze, um um den Frame einzufügen und zu plazieren:
Delphi-Quellcode:
Vielen Dank nochmal für die schnelle Hilfe!
procedure TDialog_MainUnit.FormCreate(Sender: TObject);
var tmpFrame: TFrame_ButtonTest; begin try tmpFrame := TFrame_ButtonTest.Create(Self); if Assigned(TFrame_ButtonTest(tmpFrame)) then begin TFrame_ButtonTest(tmpFrame).BtnClickMe.OnClick := FrameButtonClick; TFrame_ButtonTest(tmpFrame).Parent := PnlAllBack; TFrame_ButtonTest(tmpFrame).Align := alClient; TFrame_ButtonTest(tmpFrame).Show; end; except on e: Exception do begin ShowMessage('Fehler in FormCreate(): ' + e.Message); end; end; end; MFG Morris F. |
AW: "OnClick" Ereignis in Frame auslösen
Hallo ihr Lieben,
danke nochmal für die Hilfe bis hier hin! Allerdings hat sich mir nun ein weiteres Problem aufgetan. Ich habe mein Programm ein wenig erweitert, so dass ich den angeklickten Frame 1. überall anklicken kann und das onClick Ereignis auf jeder Komponente ausgelöst wird, 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 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:57 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