delphi 如何判断对象是否是从流创建的

fwzugrvs  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(199)

在Create / AfterConstruction代码中,我有两个独立的需求来检测是否正在从流中创建对象。
在第一种情况下,我有一个被引用的现有对象,因此它被实现为一个组件,以允许使用用户将该组件放在表单或数据模块上。并且需要在程序的不同运行中对于该对象示例保持唯一。在内部,Uuid保存在我们自己的类中,但我们在IDE中向用户提供了一个UuidString属性。我需要知道是否在首次创建时分配Uuid并注册组件,或者等到Loaded例程(如果不是从流中读取,则永远不会调用该例程)。
在第二种情况下,我有一组组件,为应用程序提供一个'OnReady'事件。一旦对象完全初始化(可能是异步的),事件就被调用。如果对象正在被流处理,那么我可以覆盖Loaded方法来进行额外的配置,但如果它没有被流处理,Loaded将永远不会被调用,我应该在AfterConstruction中开始额外的工作。
查看文档时,我认为我可以使用:

if( not (csLoading in Self.ComponentState) ) then
    ...

或者,若要特别在设计工具中拦截新建立的对象:

if( (csDesigning in Self.ComponentState) And
    not (csLoading in Self.ComponentState) ) then
  ...

然而,在查看代码(我不是一个真正的 Delphi 程序员的背景)后,我看到csLoading只在Create / AfterConstruction执行 * 之后 * 才设置。
在Create / AfterConstruction执行过程中,我是否可以判断是否将调用Loaded?
我已经意识到,通过流创建的 * 所有 * 组件都将具有Owner<>nil,但预计在运行时创建的组件通常也将具有Owner<>nil
我此刻唯一的想法是看看店主是不是装着这样的东西:

if( (Self.Owner<>nil) And (not (csLoading in Self.Owner.ComponentState)) ) then
    ...

这是正确的方法吗?或者有没有更好的“ Delphi 方法”来做?

xuo3flqw

xuo3flqw1#

假设您的属性名为UUIDString,后面有一个字段FUUIDString,那么这种方法应该可以实现:

type
  TMyComponent = class(TComponent)
  private
    FUUIDString: string;
    function GetUUIDString: string;
  protected
    procedure Loaded; override;
  public
    property UUIDString: string read GetUUIDString write FUUIDString;
  end;

function TMyComponent.GetUUIDString: string;
begin
  if FUUIDString = '' then
    FUUIDString := CreateNewUUIDString;
  Result := FUUIDString;
end;

procedure TMyComponent.Loaded;
begin
  inherited;
  RegisterUUIDString(UUIDString);
end;

如果UUIDString在流阅读期间被加载,它将包含存储的值。否则Loaded内部的寄存器调用将生成一个新的值。

xxe27gdn

xxe27gdn2#

你离解决方案很近了。你只需要重写正确的程序。

我使用“CreateWnd”的原因如下:

1.我需要初始化需要父级(面板)准备好句柄的图像,所以这个程序是正确的地方。
1.当建立ComponentState(使用csDesigning和/或csLoading)时,会呼叫它。
1.此时,任何已发布的属性都可用(已从DFM流入)。
1.它只被调用一次。
我正在使用的组件是一个“Picture- Button”,它是由一个TCustomPanel组成的,上面有一个TSpeedButton,面板上最多有4个图像。所以我想在面板上放置初始(默认)图像,这需要确定组件是何时第一次创建的(放在窗体上)。请参阅下面的一些代码〉〉

………
protected
  { Protected declarations }
  procedure CreateWnd; override;
  procedure DoInitialConfig;
………

procedure TJEPicButton.CreateWnd;
begin
  inherited;
  if (csDesigning in ComponentState) and not (csLoading in ComponentState) then
  begin   // Initial State Only
    DoInitialConfig;
  end;
  // More code here....
 end;

procedure TJEPicButton.DoInitialConfig;
begin
  // Load initial (default) image(s) on panel
  // The user can (using Object Inspector) replace this image(s) with his own…
end;

相关问题