You need to destroy the button after completing its code. The standard way to do this is to post a custom message on the form and give the form a message method that will interpret it. For example:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; const WM_KILLCONTROL = WM_USER + 1; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } procedure KillControl(var message: TMessage); message WM_KILLCONTROL; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject); begin PostMessage(self.Handle, WM_KILLCONTROL, 0, integer(Button1)) end; procedure TForm1.KillControl(var message: TMessage); var control: TControl; begin control := TObject(message.LParam) as TControl; assert(control.Owner = self); control.Free; end; end.
This works because the message is placed in the Windows message queue and does not exit until everything before it (including the Click message that the button is currently responding to) has completed processing.
Mason wheeler
source share