Fab*_*zio 3 delphi events components design-time
在仅运行时的包中,我定义了一个发布OnLoaded事件的TFrame后代:
type
TMyMethod = procedure() of object;
TMyFrame = class(TFrame)
protected
FOnLoaded : TMyMethod;
procedure Loaded(); override;
published
property OnLoaded : TMyMethod read FOnLoaded write FOnLoaded;
end;
implementation
{$R *.dfm}
procedure TMyFrame.Loaded();
begin
inherited;
if(Assigned(FOnLoaded))
then FOnLoaded();
end;
Run Code Online (Sandbox Code Playgroud)
在仅限设计时的包中,我注册了TMyFrame组件,如下所示:
unit uMyRegistrations;
interface
uses
Classes, uMyFrame;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('MyTestComponents', [
TMyFrame
]);
end;
Run Code Online (Sandbox Code Playgroud)
我已经安装了designtime包,我可以在工具选项板中找到TMyFrame,并在对象检查器中显示其OnLoaded事件.
我已将TMyFrame拖入表单中,然后通过双击对象检查器分配了OnLoaded事件.在分配事件之后,我注意到每次我尝试在Delphi中打开表单的文件时都会出现访问冲突错误消息(它让我打开".pas"文件,但我无法切换到可视化设计器视图).
我是否正确发布了OnLoaded事件?如果是这样,还有什么不对?
更多信息:
你接受了我的原始答案,但我写的不正确.Rob Kennedy指出了前Embarcadero开发商Allen Bauer关于该主题的一篇文章Assigned.
Allen解释说该Assigned函数只测试方法指针中两个指针的一个指针.IDE在设计时通过将sentinel值分配给任何已发布的方法属性(即事件)来利用此功能.这些sentinel值具有nil方法指针(Assigned检查的指针)中的两个指针之一,以及标识另一个指针中的属性值的索引.
所有这些意味着False您Assigned在设计时致电时返回.只要Assigned在调用之前检查已发布的方法指针,就不会在设计时调用它们.
所以我最初写的不是真的.
所以我挖得更深了一点.我使用了以下非常简单的代码,使用XE7进行测试:
type
TMyControl = class(TGraphicControl)
protected
FSize: Integer;
procedure Loaded; override;
end;
....
procedure TMyControl.Loaded;
begin
inherited;
FSize := InstanceSize;
end;
....
procedure Register;
begin
RegisterComponents('MyTestComponents', [TMyControl]);
end;
Run Code Online (Sandbox Code Playgroud)
这足以在Loaded执行方法时在设计时在IDE中导致AV .
我的结论是,IDE在流式传输时会做一些相当不好的事情,并且在Loaded调用方法时,您的对象不适合使用.但我真的没有比这更好的理解.
您不能在设计时执行事件处理程序,而您的代码就是这样做的.原因是在设计时事件处理程序的代码不可用.
控件的代码可用,IDE已加载它 - 但实现事件处理程序的代码不是.该代码不是设计时包的一部分,它是当前在IDE中打开的项目的一部分.毕竟,它甚至可能还没有编译!
该Loaded方法应该像这样防范:
procedure TMyFrame.Loaded();
begin
inherited;
if not (csDesigning in ComponentState) and Assigned(FOnLoaded) then
FOnLoaded();
end;
Run Code Online (Sandbox Code Playgroud)