如何告诉Delphi不在DFM中包含未发布的属性?

Ian*_*oyd 6 delphi dfm delphi-xe6

我有一个自定义控件:

type
   TContosoFrobber = class(TCustomControl)
   private
   end;
Run Code Online (Sandbox Code Playgroud)

在内部,我的组件创建一个控件:

type
   TContosoFrobber = class(TCustomControl)
   private
      FMyDateTimePicker: TDateTimePicker;
   public
      constructor Create(AOwner : TComponent); override;
      property DateTimePicker: TDateTimePicker read FMyDateTimePicker;
   end;

constructor TContosoFrobber.Create(AOwner: TComponent);
begin
   inherted Create(AOwner);

   FMyControl := TMyDateTimePicker.Create(AOwner);
end;
Run Code Online (Sandbox Code Playgroud)

其中TMyDateTimePicker是TDateTimePicker的简单后代

TMyDateTimePicker = class(TDateTimePicker)
protected
end;
Run Code Online (Sandbox Code Playgroud)

总结一下我做了什么:

  • 声明一个私有变量 TDateTimePicker
  • 将其公开为类型的公共(即非公开)属性TDateTimePicker
  • 通过多态性,控制实际上是一个后代的TDateTimePicker

这一切都奏效 - 直到最近我重新安装Delphi XE6(在Windows 10上).

DFM

这就是我无法理解为什么我在设计时遇到错误的原因:

找不到类TMyDateTimePicker

为什么要找那个班?该类在实现细节中; 它没有发布用于流式传输.流媒体系统甚至试图创建它!?所以我检查DFM:

  object cfBeachBall: TContosoFrobber
     Left = 445
     Top = 25
     Width = 101
     Height = 22
     ...snip...
     object TMyDateTimePicker
        Left = 0
        Top = 0
        Width = 101
        Height = 22
        Date = 37306.581535243100000000
        Time = 37306.581535243100000000
        TabOrder = 0
        TabStop = False
     end
  end
Run Code Online (Sandbox Code Playgroud)

为什么TInternalDateTimePicker结果在dfm中结束:

  • 该物业是公开的,未公布

如何阻止表单流式传输系统在dfm中放置未发布的属性?

更糟糕的是有缺陷的IDE

它不仅有时包括它不应该的财产.有时它包括属性不应该两次:

  object cfPlasticBag: TContosoFrobber
     Left = 445
     Top = 25
     Width = 101
     Height = 22
     ...snip...
     object TMyDateTimePicker
        Left = 0
        Top = 0
        Width = 101
        Height = 22
        Date = 37306.581535243100000000
        Time = 37306.581535243100000000
        TabOrder = 0
        TabStop = False
     end
     object TMyDateTimePicker
        Left = 0
        Top = 0
        Width = 101
        Height = 22
        Date = 37306.581535243100000000
        Time = 37306.581535243100000000
        TabOrder = 0
        TabStop = False
     end
  end
Run Code Online (Sandbox Code Playgroud)
  • 如何阻止dfm包含未发布的属性?
  • 我如何阻止dfm包括它两次?

黑客解决方法

我知道可怕的黑客攻击:告诉DFM控制它不应该让任何业务知道:

initialization
    RegisterClass(TMyDateTimePicker);

finalization
    UnRegisterClass(TMyDateTimePicker);

end.
Run Code Online (Sandbox Code Playgroud)

现在dfm包含一个没有业务知道的控件.每次我保存表单时,它都会包含对不应该的内容的引用.最糟糕的是:我证实了它错误地相信a TMyDateTimePicker.

为什么Delphi XE6在重新安装之前没有这样做?也许我需要安装最新更新的长期以来不支持的Delphi版本?

已知错误?

在此输入图像描述

Rem*_*eau 12

问题是,你要分配错误Owner的TDateTimePicker.您正在分配您TContosoFrobber的所有者而不是TContosoFrobber自己:

constructor TContosoFrobber.Create(AOwner: TComponent);
begin
  inherted Create(AOwner);
  FMyControl := TMyDateTimePicker.Create(Self); // <-- not AOwner!
end;
Run Code Online (Sandbox Code Playgroud)

或者:正如Jerry Doge所说,你可以使用nil所有者.你只需要Free()在TDataTimePicker手动:

type
  TContosoFrobber = class(TCustomControl)
  private
    FMyDateTimePicker: TDateTimePicker;
  public
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
    ...
  end;

constructor TContosoFrobber.Create(AOwner: TComponent);
begin
  inherted Create(AOwner);
  FMyControl := TMyDateTimePicker.Create(nil);
end;

destructor TContosoFrobber.Destroy;
begin
  FMyControl.Free;
  inherted Destroy;
end;
Run Code Online (Sandbox Code Playgroud)

  • 当`TDataModule` /`TFrame` /``TForm`被保存到DFM时,他们直接拥有的没有"Parent"分配的任何组件也会被流式传输.在给出的示例中,`TMyDateTimePicker`对象没有分配"Parent".如果其"所有者"设置为表格,则可以解决问题.设置`TContosoFrobber`作为所有者避免了这个问题(避免在销毁期间需要明确的`Free`). (4认同)