自定义按钮OnClick事件

时间:2016-03-06 21:21:27

标签: delphi onclick delphi-xe7

我在运行时创建按钮,并且希望能够设置自定义OnClick事件,每个按钮在单击时都会传递它自己的自定义值:

尝试分配自定义OnClick过程时出错:

E2010 Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'

这是我如何使用它:

procedure myOnClick(Sender:TObject; Info1:string; info2:integer);
begin
  // process info1, info2 based on which button is Sender
end;

procedure TForm1.Button1Click(Sender: TObject);
var vBtn:Tbutton;
  Idx:integer;
  vStr:string;
begin
   // ...

   // create btn
   vBtn := Tbutton.Create(nil);
   vBtn.Parent := Form1.ButtonsPanel;
   vBtn.Tag := Idx;
   vBtn.OnClick:=myOnCLick(self,vStr,vBtn.Tag);

   // assign btn
   //...

end;

如何使用自定义点击事件,程序,以便在点击按钮时传递特定于该按钮的值?

修改

现在我使用CustomOnClick:

procedure TForm1.CustomOnClick(Sender: TObject);
begin
  myOnClick(Sender,TControl(Sender).Tag);
end;

vBtn.OnClick:=Form1.CustomOnClick; // works, but only accepts Sender parameter

正如大卫所说,我已经使用了Tag属性。现在我需要更多的信息,并希望摆脱这个中间人' CustomOnClick并直接调用myOnClick。

1 个答案:

答案 0 :(得分:3)

方法1

您可以存储"按钮信息"像那里一样分开:

type
  TButtonInfo = record
    info1: string;
    info2: Integer;
    info3: Double;

    constructor Create(const AInfo1: string; AInfo2: integer; AInfo3: Double);
  end;

  TButtonInfoDictionary = class(TDictionary<TObject,TButtonInfo>)
  end;

  TForm6 = class(TForm)
  .....
  private
    { Private declarations }
    FButtonInfoDict: TButtonInfoDictionary;
    procedure OnButtonClick(Sender: TObject);
  public
    { Public declarations }
    destructor Destroy; override;
  end;

implementation

constructor TButtonInfo.Create(const AInfo1: string; AInfo2: integer;
  AInfo3: Double);
begin
  Info1:=AInfo1;
  Info2:=AInfo2;
  Info3:=AInfo3;
end;

procedure TForm6.btnAddNewButtonClick(Sender: TObject);
var
  btn: TButton;
begin
  if not Assigned(FButtonInfoDict) then
    FButtonInfoDict:=TButtonInfoDictionary.Create;

  btn:=TButton.Create(nil);
  btn.Parent:=Self;
  btn.Align:=alTop;
  btn.Caption:='btn'+FButtonInfoDict.Count.ToString;
  btn.OnClick:=OnButtonClick;

  FButtonInfoDict.Add(btn, TButtonInfo.Create(FButtonInfoDict.Count.ToString, FButtonInfoDict.Count, 0));
end;

destructor TForm6.Destroy;
begin
  FreeAndNil(FButtonInfoDict);
  inherited;
end;

procedure TForm6.OnButtonClick(Sender: TObject);
var
  ButtonInfo: TButtonInfo;
begin
  if Assigned(FButtonInfoDict) then
    if FButtonInfoDict.TryGetValue(Sender, ButtonInfo) then
      Caption:=ButtonInfo.Info1+'  ' + ButtonInfo.info2.ToString;
end;

方法2 正如大卫所说,更喜欢。

&#34;展开&#34; TButton类并为新类添加所需的属性:

type
  TButton = class(Vcl.StdCtrls.TButton)
  private
    FInfo2: integer;
    FInfo1: string;
  public
    property Info1: string read FInfo1 write FInfo1;
    property Info2: integer read FInfo2 write FInfo2;
  end;

  TForm6 = class(TForm)
  .....
  private
    { Private declarations }
    procedure OnButtonClick(Sender: TObject);
  public
    { Public declarations }
  end;

procedure TForm6.btnAddNewButtonClick(Sender: TObject);
var
  btn: TButton;
begin
  btn:=TButton.Create(nil);
  btn.Parent:=Self;
  btn.Align:=alTop;
  btn.Caption:='btn'+Self.Tag.ToString;
  btn.Info1:=Self.Tag.ToString;
  btn.Info2:=Self.Tag;
  btn.OnClick:=OnButtonClick;

  Self.Tag:=Self.Tag + 1;
end;

procedure TForm6.OnButtonClick(Sender: TObject);
begin
  if Sender is TButton then
    Caption:=TButton(Sender).Info1+'  ' + TButton(Sender).info2.ToString;
end;

方法3 ,不需要的

为方法1中的商店TButtonInfo使用动态分配的内存:

PButtonInfo = ^TButtonInfo;

procedure TForm6.btnAddNewButtonClick(Sender: TObject);
var
  btn: TButton;
  pInfo: PButtonInfo;
begin
  btn:=TButton.Create(nil);
  btn.Parent:=Self;
  btn.Align:=alTop;
  btn.Caption:='btn'+Self.Tag.ToString;
  btn.OnClick:=OnButtonClick;

  New(pInfo); // once we have allocated memory, we need to release it after all.
  // but we dont have event, where we can call Dispose(PButtonInfo(btn.tag));
  // so, we have memory leak...
  // You can change TButtonInfo declaration from record to class,
  // and use .Create against New, but memory leak still there
  pInfo.info1:=Self.Tag.ToString;
  pInfo.info2:=Self.Tag;
  btn.Tag:=NativeInt(pInfo);

  Self.Tag:=Self.Tag + 1;
end;

procedure TForm6.OnButtonClick(Sender: TObject);
begin
  if Sender is TButton then
    Caption:=PButtonInfo(TButton(Sender).Tag).Info1+'  ' + PButtonInfo(TButton(Sender).Tag).info2.ToString;
end;