Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Button zerstören? (https://www.delphipraxis.net/13539-button-zerstoeren.html)

Moyyer 20. Dez 2003 17:59


Button zerstören?
 
Hallo Alle Zusammen

Ich habe hier eine ganz einfaches Programm. Es erstellt 500 Buttons.
Nun will ich, das wenn ich einen bestimmten Button drücke, dieser verschwindet (sich zerstört). Aber bei mir kommt immer die Fehlermeldung "Abstrakter Fehler". Was muss ich ändern, damit es funktioniert? Oder geht es überhaupt?

Delphi-Quellcode:

const
MAX_BUTTONS = 500;

procedure TForm1.Button1Click(Sender: TObject);
var
    i: integer;
begin
  SetLength(pbTemp,MAX_BUTTONS);
  for i:=0 to MAX_BUTTONS - 1 do
  begin
    pbTemp[i] := TButton.Create(nil);
    pbTemp[i].Name := 'ButtonNr' + IntToStr(i);
    pbTemp[i].Parent := Form1;
    pbTemp[i].Top := 16 * i;
    pbTemp[i].Left := 300;
    pbtemp[i].OnClick := butclick;
    pbtemp[i].Tag := i;
  end;
end;

procedure TForm1.ButClick(Sender: TObject);
var a: integer;
begin
a := (sender as Tbutton).tag;
label1.caption := inttostr(a);
pbtemp[a].Free;
end;

Jens Schumann 20. Dez 2003 19:04

Re: Button zerstören?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
das liegt daran, dass Du den Button, der das OnClick Event gefeuert hat im selben zerstörst.
D.h. der Button ruft den OnClick-Handler auf. Nach dem der Code im OnClick-Handler abgearbeitet
wurde kehrt dieser zum Button zurück. Nur zum welchem Button soll er denn zurück ??? Der Button
wurde ja freigegeben. Deshalb empfehle ich im OnClick-Handler den Button nicht freizugeben, sondern
mit PostMessage eine Botschaft an das Formular zu senden. Über wParam des Messagerecords kannst Du
den Arrayindex übergeben.
Siehe Anlage

Moyyer 20. Dez 2003 19:32

Re: Button zerstören?
 
Vielen Dank. Isst genau dass was ich gebraucht habe. :angle:

daywalker-dj-k 20. Mär 2004 12:03

Re: Button zerstören?
 
hallo,
hab da mal ne frage zum "button-prog". wie müsste ich das ganze lösen, wenn ich einfach in einer schleife einige objekte löschen möchte?

Delphi-Quellcode:
PostMessage(Handle,PM_FREEBUTTON,TComponent(Sender).Tag,0);
da müsste ich doch jetzt quasi nur "TComponent(Sender)" durch meine komponente (über FindComponent) ersetzen.

nur was muss ich nun hier machen:

Delphi-Quellcode:
FreeAndNil(FButtonArray[Message.wParam]);
ich habe ja kein array mit den objektnamen und möchte auch keins erstellen. was bedeutet denn das "message.wparam" überhaupt. Muss ich bei FreeAndNil nicht einfach nur den Objektnamen wie "Edit1" einsetzen?


danke schonmal
gruß
tkliewe



hier mal kurz der ganze quelltext:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  iCnt : Integer;
begin
  SetLength(FButtonArray,MAX_BUTTONS);
  For iCnt:=0 to MAX_BUTTONS-1 do
    begin
    FButtonArray[iCnt]:=TButton.Create(Self);
    FButtonArray[iCnt].Parent:=Self;
    FButtonArray[iCnt].Caption:='Button '+IntToStr(iCnt+1);
    FButtonArray[iCnt].SetBounds(100,12+iCnt*(FButtonArray[iCnt].Height+4),FButtonArray[iCnt].Width,FButtonArray[iCnt].Height);
    FButtonArray[iCnt].Tag:=iCnt;
    FButtonArray[iCnt].OnClick:=ButtonClick;
    end;
  Button1.Enabled:=False;
end;

procedure TForm1.ButtonClick(Sender: TObject);
begin
  {PostMessage wird hier verwendet, weil PostMessage ans Ende der Botschafts-
   warteschlange gestellt wird und deshalb erst abgearbeitet wird wenn alle
   anderen Botschaft, wie z.B. die Click Botschaft an den Button abgearbeitet
   wurde}
  PostMessage(Handle,PM_FREEBUTTON,TComponent(Sender).Tag,0);
end;

procedure TForm1.PMFREEBUTTON(var Message: TMessage);
begin
  FreeAndNil(FButtonArray[Message.wParam]);
end;

Jens Schumann 20. Mär 2004 17:24

Re: Button zerstören?
 
Zitat:

Zitat von daywalker-dj-k
wie müsste ich das ganze lösen, wenn ich einfach in einer schleife einige objekte löschen möchte?

Wenn ButtonX nicht Bestandteil von FButtonArray ist brauchst Du das ganze Zeug mit PostMessage nicht. Dann reicht der folgende
Delphi-Quellcode:
Codeprocedure TForm1.ButtonXClick(Sender : TObject);
var
  iCnt : Integer;
begin
  For iCnt:=Low(FButtonArray) to High(FButtonArray) do
    FreeAndNil(FButtonArray[iCnt]);
end;
Zitat:

Zitat von daywalker-dj-k
ich habe ja kein array mit den objektnamen und möchte auch keins erstellen. was bedeutet denn das "message.wparam" überhaupt. Muss ich bei FreeAndNil nicht einfach nur den Objektnamen wie "Edit1" einsetzen?

Wenn die Buttons in keinem Array sind, dann musst Du die Buttons geschickt benamen. Dann kannst FindComponentwie folgt nutzen:
Delphi-Quellcode:
procedure TForm1.ButtonXClick(Sender : TObject);
var
  iCnt : Integer;
begin
  For iCnt:=0 to 9 do // wir haben 10 Buttons
    FindComponent('Button'+IntToStr(iCnt)).Free;
end;
Objektnamen sind wie andere Namen auch nur Schall und Rauch. Wichtig ist, dass Du eine gültige Referenz auf das Objekt hast. Über den Namen des Objektes sorgt der Compiler dafür das dem so ist. Ob die Referenz in einer Instanzenvariablen oder in Array oder sonst wo gespeichert ist ist dabei egal.

devnull 20. Mär 2004 22:05

Re: Button zerstören?
 
Ich hab hierzu auch noch eine Frage:
Ich habe einem Button des FButtonArrays die Funktion gegeben, dass Programm zu beenden.

Erstellen eines neuen Buttons
Delphi-Quellcode:
  SetLength(Form1.FButtonArray, 10);
  Form1.FButtonArray[iCnt]:= TButton.Create(Form1);
  Form1.FButtonArray[iCnt].Parent := Form1;
  Form1.FButtonArray[iCnt].Caption := 'Programm Beenden';
  //Form1.FButtonArray[iCnt].Tag := iCnt;
  Form1.FButtonArray[iCnt].Left := x+25;
  Form1.FButtonArray[iCnt].Top := y;
  Form1.FButtonArray[iCnt].Width := w;
  Form1.FButtonArray[iCnt].Height := h;
  @Form1.FButtonArray[iCnt].OnClick := @MeinEigenesOnClick;

Nachdem auf ein Button geklickt wurde
Delphi-Quellcode:
procedure MeinEigenesOnClick (Self: TObject; Sender: TObject);
var prg_gesucht : string;
begin
  prg_gesucht := TButton(Sender).Caption;

  if prg_gesucht = 'Programm beenden' then begin
     MessageDlg ('Beenden ...',mtInformation,[mbOk],0);
     // Fehlt hier was ???
     Form1.Close;
  end;
  [...]
Seitdem ich dies so mache (Beenden des Programms) kommt nach Schließen des Programms der Windows-Fehler-Sound
und in der Delphi-Umgebung die Debugger-Exception "Ungültige Zeigeroperation".


Kann mir jemand helfen ???


MFG
devnull

Keex 21. Mär 2004 09:26

Re: Button zerstören?
 
hmm, ich hab das hier mit Buttonserstellen auch mal ausprobiert (<- newb ;))
klappt auch alles soweit, nur wenn ich versuche den neuen buttons ein ereignis zuzuweisen mit

Delphi-Quellcode:
Buttonarray[i].OnClick := TForm1.EigenerClick;
kommt der Fehler "Incompatible Types: TNotifyevent and Procedure".
ich hab das aber doch genauso gemacht wie ihr hier :gruebel:

devnull 21. Mär 2004 10:05

Re: Button zerstören?
 
Ersetz die Zeile mal mit der unten stehenden:
Delphi-Quellcode:
Buttonarray[i].OnClick := TForm1.EigenerClick;
-->
Delphi-Quellcode:
@Form1.FButtonArray[iCnt].OnClick := @MeinEigenesOnClick;

MFG
devnull

daywalker-dj-k 21. Mär 2004 11:22

Re: Button zerstören?
 
hallo,
@ Jens Schumann

du hast mir ja geschrieben, dass ich einfach mit findcomponent das objekt suchen soll und dann mit free "löschen". dann habe ich aber wieder das geleiche problem wie der ursprüngliche poster ("Abstrakter fehler"). ich dachte halt, dass mir das "PostMessage" diesen fehler behebt.

mfg
tkliewe

Jens Schumann 22. Mär 2004 09:49

Re: Button zerstören?
 
Zitat:

Zitat von daywalker-dj-k
du hast mir ja geschrieben, dass ich einfach mit findcomponent das objekt suchen soll und dann mit free "löschen". dann habe ich aber wieder das geleiche problem wie der ursprüngliche poster ("Abstrakter fehler"). ich dachte halt, dass mir das "PostMessage" diesen fehler behebt.

Suchst Du in dem OnClick Event mit FindComponent auch den Button, der das Event ausgelöst hat?
Das darfst Du natürlich nicht. Habe ich oben auch extra geschrieben. Wenn Du das unbedingt möchtest, dann kannst Du PostMessage nutzen. In den lParam packst Du die Objektreferenz, die Du mit Findcomponent gefunden hast. In dem Messagehandler kannst Du dann aus lParam die Objektreferenz ziehen und den Button freigeben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:44 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