AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Delphi hängt bei klick auf Frame

Ein Thema von MorrisF · begonnen am 11. Apr 2019 · letzter Beitrag vom 12. Apr 2019
Antwort Antwort
Seite 1 von 3  1 23   
MorrisF

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

Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 10:47
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:
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
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.559 Beiträge
 
Delphi 6 Enterprise
 
#2

AW: Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 11:34
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.
Ralph
  Mit Zitat antworten Zitat
MorrisF

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

AW: Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 11:52
Habe jetzt
TMein_Frame(Frame[i]) := TMein_Frame.Create(self); durch
Frame[i] := TMein_Frame.Create(self); ausgetauscht. Hat allerdings keinen unterschied gemacht

Morris

Geändert von MorrisF (11. Apr 2019 um 12:23 Uhr)
  Mit Zitat antworten Zitat
MorrisF

Registriert seit: 3. Apr 2019
32 Beiträge
 
#4

AW: Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 11:54
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.
TMein_Frame ist die Frame Unit, die ich im Projekt habe, ich habe den Frame auch in den uses meines Haupformulars.
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?

Geändert von MorrisF (11. Apr 2019 um 12:09 Uhr)
  Mit Zitat antworten Zitat
MorrisF

Registriert seit: 3. Apr 2019
32 Beiträge
 
#5

AW: Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 12:19
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
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
1.093 Beiträge
 
Delphi 7 Professional
 
#6

AW: Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 12:36
Nur im Editor hingedattelt, daher keine Garantie für irgendwas
Delphi-Quellcode:
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;
Hier wurde für Frames TMein_Frame genutzt.
Im Folgenden wird für Frames TFrame_ButtonTest.

Sind die kompatibel oder ist das nur eine "BeispielquelltextZurProblemBeschreibungsdifferenz "?
Delphi-Quellcode:
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;
Wieso brauchst Du den Frame als globale Variabel? Du hast doch zur Laufzeit n Frames?

Geändert von Delphi.Narium (11. Apr 2019 um 12:52 Uhr) Grund: von Jumpy entdeckten Fehler behoben
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.559 Beiträge
 
Delphi 6 Enterprise
 
#7

AW: Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 12:45
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:
if Assigned(Frame) then
   FreeAndNil(Frame[i]);
Müsste doch eher sein:
Delphi-Quellcode:
if Assigned(Frame[i]) then
   FreeAndNil(Frame[i]);
Ralph

Geändert von Jumpy (11. Apr 2019 um 12:48 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
4.227 Beiträge
 
Delphi 10.1 Berlin Professional
 
#8

AW: Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 12:51
Hallöle...
Delphi-Quellcode:
TmpQuery.Close;
TmpQuery.SQL.Clear;
TmpQuery.SQL.Add('SELECT * FROM meine_tabelle');
TmpQuery.SQL.Add('WHERE ID_meine_tablle2 = ' + IntToStr(SpinEdit.Value));
TmpQuery.Open;
...früher gabs dafür einen mit dem Rohrstock!

besser:
Delphi-Quellcode:
TmpQuery.SQL.Text := 'SELECT * FROM meine_tabelle';
TmpQuery.SQL.Add('WHERE ID_meine_tablle2 = :ID');
TmpQuery.ParamByName('ID').AsInteger := IntToStr(SpinEdit.Value);
TmpQuery.Open;
  Mit Zitat antworten Zitat
MorrisF

Registriert seit: 3. Apr 2019
32 Beiträge
 
#9

AW: Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 12:55
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:
if Assigned(Frame) then
   FreeAndNil(Frame[i]);
Müsste doch eher sein:
Delphi-Quellcode:
if Assigned(Frame[i]) then
   FreeAndNil(Frame[i]);
In meinem Hauptprogramm baue ich die Frames mehrfach auf. Daher das DeleteFrames.
Mit der Code Verbesserung hast du schon mal recht! Vielen Dank! Leider funktioniert das Programm immer noch nicht
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.559 Beiträge
 
Delphi 6 Enterprise
 
#10

AW: Delphi hängt bei klick auf Frame

  Alt 11. Apr 2019, 12:59
Setzt du denn jetzt die Array-Länge wieder zurück?
Ralph
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 10:58 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf