这是真的吗?
例如,我有form1
和button1
。我只能在button1.onClick
的设计时间内指定到Button26Click
。
TForm1 = class(TForm)
procedure Button26Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
我也有单位2:
unit ProcAndFunc;
interface
uses sysutils,forms;
procedure createArrTable(Sender: TObject);
我可以在设计时中将 createArrTable
分配给button1.onClick
吗?
感谢。
确定。 1单元
TForm1 = class(TForm)
myButton1 : TButton;
procedure Button26Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
UNIT2
TForm2 = class(TForm)
myButton2 : TButton;
procedure ButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
只是想知道它是如何工作的。我应该unit2
我应该更改ButtonClick
到myButton1.OnClick
的内容
How to make a separate unit for event methods, which IDE allows me to assign to component events at design time?似乎我重复了问题。但那个答案并不适合我。还有其他方法吗?
EDIT3(08.08.2016): 我创建了这个TDataModule;
unit Unit3;
interface
uses
System.SysUtils, System.Classes,dialogs;
type
TDataModule3 = class(TDataModule)
procedure Click2(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
DataModule3: TDataModule3;
implementation
{%CLASSGROUP 'Vcl.Controls.TControl'}
{$R *.dfm}
procedure TDataModule3.Click2(Sender: TObject);
begin
ShowMessage('hello world');
end;
end.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, unit3;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage('hello world');
end;
end.
我仍然无法在设计时将DataModule3.Click2分配给button1.onclick。 (screenshot)。我还需要做什么?
答案 0 :(得分:1)
您不能将该过程指定为事件处理程序,因为它不是类的方法。因此,您可以使该过程成为另一个类的方法,并确保设计器可以看到该类的全局实例。
然而,在我看来,这将是一个非常糟糕的解决方案。最佳做法是尽可能将UI逻辑与应用程序逻辑分离。干净的解决方案是简单地从事件处理程序调用该过程。这意味着您的程序仍然可以以其当前形式提供给其他方,并且不需要看起来像一个事件处理程序。您也可以删除我怀疑您在任何情况下都不使用的response.write("Hello again"); response.end();
参数。
答案 1 :(得分:1)
我可以在设计时将
createArrTable
分配给button1.onClick
吗?
不是在设计时,不是。 createArrTable()
不是类的成员,因此在运行时无法通过对象指针访问。因此它不满足OnClick
事件处理程序通常所需的签名。 IDE将不允许您在设计时分配它。
但是,可以在运行时分配createArrTable()
,并进行一些小的调整。
OnClick
事件(以及一般的大多数RTL / VCL事件)是使用闭包实现的,它由2个指针组成 - 指向过程代码本身的指针和指针对象。
当在运行时触发事件时,编译的代码从闭包中提取对象指针,并使用传递给过程的Self
参数的对象调用该过程。缺少Self
参数会阻止您当前的createArrTable()
实现用作OnClick
事件处理程序。如果你按原样分配它,参数列表将在运行时被破坏。
但是,如果您向Self
添加显式 createArrTable()
参数,则可以避免该问题,并跳过类对象要求:
procedure createArrTable(Self: Pointer; Sender: TObject);
在调用过程时,按钮仍会尝试将对象指针从闭包传递到Self
,但现在您已为对象指针创建了空间,以便正确传递并且不会损坏其他参数。对象指针本身变得无关紧要,可以设置为你想要的任何东西,甚至是零。
但是,由于createArrTable()
仍然不是某个类的成员,因此您无法将直接分配给OnClick
事件,但您可以使用TMethod
}变量以便于分配,例如:
var
M: TMethod;
begin
M.Code := @createArrTable;
M.Data := WhateverYouWantSelfToBe;
Button1.OnClick := TNotifyEvent(M);
end;
现在createArrTable()
会在运行时触发OnClick
时按预期工作。
我应该
unit2
我可以将ButtonClick
分配给myButton1.OnClick
无。它已经是一个合适的事件处理程序。您只需将unit2
添加到uses
中interface
部分的unit1
子句中,以便IDE在设计时可以看到ButtonClick()
,那么您就可以将Form2.ButtonClick
分配给myButton1.OnClick
。只需知道您必须在运行时设置项目以在 Form2
之前创建Form1
,否则当DFM流系统尝试访问{{}时,您可能会崩溃代码1}}在分配ButtonClick
的值时通过无效的Form2
对象。
为避免必须更改表单的创建顺序,您可以将事件处理程序放在单独的Form1.myButton.OnClick
中,然后将其方法链接到表单上的事件。只需确保在创建表单之前在运行时创建TDataModule
:
Access DataModule's event from another Form (delphi design-time)