Autor |
Beitrag |
fuulf
      
Beiträge: 24
|
Verfasst: Do 17.12.09 13:12
Hallo,
das Programm soll zur Laufzeit einen Button dynamisch erstellen. Dann soll unter definierten Bedingungen, wobei eine dieser Bedingungen ist, dass der Benutzer auf den Button geklickt hat, der Button wieder mit .free gelöscht und der zugehörige Speicher freigegeben werden. Wenn ich das versuche, gibt es eine Zugriffsverletzung, weil das Programm noch auf den Button zugreifen will, aber der Button sich ja schon selbst gelöscht hat.
|
|
thepaine91
      
Beiträge: 763
Erhaltene Danke: 27
Win XP, Windows 7, (Linux)
D6, D2010, C#, PHP, Java(Android), HTML/Js
|
Verfasst: Do 17.12.09 13:17
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 17.12.09 13:33
Moin!
fuulf hat folgendes geschrieben : | das Programm soll zur Laufzeit einen Button dynamisch erstellen. Dann soll unter definierten Bedingungen, wobei eine dieser Bedingungen ist, dass der Benutzer auf den Button geklickt hat, der Button wieder mit .free gelöscht und der zugehörige Speicher freigegeben werden. Wenn ich das versuche, gibt es eine Zugriffsverletzung, weil das Programm noch auf den Button zugreifen will, aber der Button sich ja schon selbst gelöscht hat. |
Man kann VCL-Controls (also auch Buttons) nicht in ihren Ereignissen freigeben, das wird immer mit einer Exception belohnt.
Einfacher Lösungsansatz: Reicht es nicht, den Button einfach .Visible := FALSE zu setzen? Evtl. erzeugst du ja danach wieder einen, dann kannst du dir das sparen und den schon existierenden weiterverwenden.
Komplexer: Eine private WindowsMessage definieren, einen Handler dazu schreiben, in diesem den Button freigeben, die Message im OnClick des Buttons an das eigene Handle posten.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
fuulf 
      
Beiträge: 24
|
Verfasst: Do 17.12.09 13:38
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure Klick(Sender: TObject); private public end;
var Form1: TForm1; Knopf: TButton;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject); begin Knopf := tbutton.create(form1); Knopf.parent := form1; Knopf.OnClick := Klick; end;
procedure TForm1.Klick(Sender: TObject); begin Knopf.Free; end;
end. |
Also visible := false reicht nicht. Wie genauer funktioniert denn der beschriebene komplexere Lösungsansatz?
Moderiert von Narses: Code- durch Delphi-Tags ersetzt
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 17.12.09 13:47
Moin!
fuulf hat folgendes geschrieben : | Also visible := false reicht nicht. |
Darf ich mal so ganz nebenbei fragen, warum das nicht reicht?
fuulf hat folgendes geschrieben : | Wie genauer funktioniert denn der beschriebene komplexere Lösungsansatz? |
Ich such dir einen passenden Thread dazu raus, das gibt´s hier schon mehrfach im Forum.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
fuulf 
      
Beiträge: 24
|
Verfasst: Do 17.12.09 13:58
Weil zwar wieder neue Buttons erzeugt werden sollen, aber nicht unbedingt so viele, wie vorher da waren. Umgekehrt könnte es aber auch sein, dass mehr Buttons erzeugt werden sollen, als es vorher gab. Das hängt vom Benutzer ab.
Also bei www.delphi-forum.de/...light=windowsmessage scheint es im Prinzip ein ähnliches Problem zu sein, aber hat mir jetzt auch nicht so viel geholfen..
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 17.12.09 14:08
Moin!
fuulf hat folgendes geschrieben : | Weil zwar wieder neue Buttons erzeugt werden sollen, aber nicht unbedingt so viele, wie vorher da waren. Umgekehrt könnte es aber auch sein, dass mehr Buttons erzeugt werden sollen, als es vorher gab. Das hängt vom Benutzer ab. |
In diesem Fall würde ich zwei Listen empfehlen, eine mit sichtbaren und die andere mit den unsichtbaren Buttons. Direkt die Maximalanzahl erstellen (und das Formular als Eigentümer angeben, dann braucht man sich nicht um die Freigabe kümmern) und dann nur noch zwischen den Listen hin- und herschieben.  Ist nebenbei auch resourcenschonender.
Dann schau mal hier.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
thepaine91
      
Beiträge: 763
Erhaltene Danke: 27
Win XP, Windows 7, (Linux)
D6, D2010, C#, PHP, Java(Android), HTML/Js
|
Verfasst: Do 17.12.09 14:29
Man könnte es so machen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| private procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
procedure TForm1.FormCreate(Sender: TObject); begin Application.OnMessage := AppMessage; end;
procedure TForm1.ErstellterButtonClick(Sender: TObject); begin PostMessage(Application.Handle, WM_USER + 55, 1,0); end;
procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean); begin if msg.message = wm_user + 55 then if msg.wParam = 1 then begin FreeAndNil(Knopf); Handled := true; end; end; |
|
|
fuulf 
      
Beiträge: 24
|
Verfasst: Mo 28.12.09 17:15
Könnte man es vielleicht auch unprofessioneller mit einem Timer machen, der über .ComponentState überprüft, ob der Button noch irgendeine Ereignisprozedur am laufen hat, bzw. ob der Button noch überhaupt irgendwas macht?
Würde es reichen csLoading zu überprüfen?
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Sa 02.01.10 02:27
Moin!
fuulf hat folgendes geschrieben : | Könnte man es vielleicht auch unprofessioneller mit einem Timer machen, der über .ComponentState überprüft, ob der Button noch irgendeine Ereignisprozedur am laufen hat, bzw. ob der Button noch überhaupt irgendwas macht? |
Man kann eine Menge Sachen machen, die Frage ist, wieviel Aufwand das ist und wie "sicher" sich diese Lösung verhält. Bei deinem zuletzt vorgeschlagenen Ansatz sehe ich für beide Kriterien keine Pluspunkte.  Mein Tipp: Finger davon lassen.
fuulf hat folgendes geschrieben : | Würde es reichen csLoading zu überprüfen? |
Was sollte das bringen?
Du hast mittlerweile mehrere Ansätze vorgeschlagen bekommen, die mehr oder weniger sicher das Problem lösen. Warum einen fraglichen Ansatz verfolgen, wenn es schon bessere Lösungen gibt?
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 02.01.10 03:46
Du kannst ja immer die noch fehlenden Buttons erzeugen und zu viel vorhandene freigeben: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| private MyButtons: TList<TButton>;
MyButtons := TList<TButton>.Create(True); MyButtons.Free;
var i: Integer; NewButton: TButton; begin for i := MyButtons.Count to Pred(CurrentCount) do begin NewButton := TButton.Create(nil); NewButton. ... MyButtons.Add(NewButton); end; for i := MyButtons.Count downto CurrentCount do MyButtons.Delete(i); for i := 0 to Pred(MyButtons.Count) do MyButtons.Caption := IntToStr(i); end; | Oder zwei Listen wie auch schon vorgeschlagen, oder, oder...
Es hängt auch sehr davon ab was mit den Buttons passiert und wodurch die Anzahl festgelegt wird, ob diese beliebig sein kann, ...
Du kannst dann die passende Variante benutzen.
|
|
|