AGB  ·  Datenschutz  ·  Impressum  







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

"OnClick" Ereignis in Frame auslösen

Ein Thema von MorrisF · begonnen am 3. Apr 2019 · letzter Beitrag vom 10. Apr 2019
Antwort Antwort
MorrisF

Registriert seit: 3. Apr 2019
41 Beiträge
 
#1

"OnClick" Ereignis in Frame auslösen

  Alt 3. Apr 2019, 11:35
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:
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;
Und hier der Code im Hauptformular:
Delphi-Quellcode:
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;
Meine Frage nun:
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.

Geändert von MorrisF ( 3. Apr 2019 um 11:42 Uhr)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#2

AW: "OnClick" Ereignis in Frame auslösen

  Alt 3. Apr 2019, 11:40
tmpFrame.BtnClickMe.OnClick := FrameButtonClick;
  Mit Zitat antworten Zitat
MorrisF

Registriert seit: 3. Apr 2019
41 Beiträge
 
#3

AW: "OnClick" Ereignis in Frame auslösen

  Alt 3. Apr 2019, 11:56
tmpFrame.BtnClickMe.OnClick := FrameButtonClick;
Danke erstmal, für die schnelle Antwort!
Wenn ich das aber so mache, bekomme ich beim kompilieren eine Zugriffsverletzung. Was ist also noch falsch?
(Aber immerhin kann ich es jetzt kompilieren.)

Geändert von MorrisF ( 3. Apr 2019 um 11:59 Uhr)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#4

AW: "OnClick" Ereignis in Frame auslösen

  Alt 3. Apr 2019, 12:30
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.
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: "OnClick" Ereignis in Frame auslösen

  Alt 3. Apr 2019, 12:33
Hi MorrisF

Das kannst du dir sparen:
Delphi-Quellcode:
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;
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.
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:
procedure TFrame_ButtonTest.BtnClickMeClick(Sender: TObject);
begin
if FBoolean then
  Mainfrm.Edit1.Color := clred
else
  Mainfrm.Edit1.Color := clyellow;
end;
FBoolean solltest du in diesem Fall als privates Feld des Basisframes deklarieren.

Gruss
Delbor

PS: Sehe gerade, dass du deine Frameinstanz dynamisch erstellst:
Delphi-Quellcode:
  try
    tmpFrame := TFrame_ButtonTest.Create(self);
TFrame_ButtonTest darf hier allerdings nicht der Name deines Basisframes sein. Ansonsten bleibt sich alles gleich.
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch

Geändert von Delbor ( 3. Apr 2019 um 13:55 Uhr)
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: "OnClick" Ereignis in Frame auslösen

  Alt 3. Apr 2019, 13:28
Hi MorrisF

Hi MorrisF
PS: Sehe gerade, dass du deine Frameinstanz dynamisch erstellst:
Delphi-Quellcode:
  try
    tmpFrame := TFrame_ButtonTest.Create(self);
TFrame_ButtonTest darf hier allerdings nicht der Name deines Basisframes sein. Ansonsten bleibt sich alles gleich.
Da hab ich mich ziemlich vertan. Hier eine Prozedur, die mir verschiedene Frames dynamisch erstellt:

Delphi-Quellcode:
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;
Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
MorrisF

Registriert seit: 3. Apr 2019
41 Beiträge
 
#7

AW: "OnClick" Ereignis in Frame auslösen

  Alt 3. Apr 2019, 14:11
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!
Hier der Code den ich benutze, um um den Frame einzufügen und zu plazieren:
Delphi-Quellcode:
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;
Vielen Dank nochmal für die schnelle Hilfe!

MFG
Morris F.
  Mit Zitat antworten Zitat
MorrisF

Registriert seit: 3. Apr 2019
41 Beiträge
 
#8

AW: "OnClick" Ereignis in Frame auslösen

  Alt 10. Apr 2019, 08:04
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:
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;
Und hier die FrameClick-Prozedur, in der der Frame als angeklickt markiert wird:
Delphi-Quellcode:
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;
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:
Delphi-Quellcode:
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;
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?
Das Createn der Frames funktioniert auch im Hauptprogramm einwandfrei. Aber jetzt kommt der Knackpunkt; Hier meine OnFrameClick Prozedur vom Hauptprogramm:
Delphi-Quellcode:
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;
Diese Prozedur ist sogar noch ähnlicher zu der FrameClick Prozedur vom Testprogramm.
Ich habe nun aber 2 Probleme in dieser Prozedur:
1. Das durchlaufen des Arrays, also folgende Code-passage erzeugt eine Zugriffsverletzung
Delphi-Quellcode:
    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;
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.
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

Geändert von MorrisF (10. Apr 2019 um 09:36 Uhr)
  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 21:02 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