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

时间:2016-09-14 19:40:08

标签: delphi delphi-xe6 dfm

我有一个自定义控件:

type
   TContosoFrobber = class(TCustomControl)
   private
   end;

在内部,我的组件会创建控件

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;

其中 TMyDateTimePicker TDateTimePicker的简单后代

TMyDateTimePicker = class(TDateTimePicker)
protected
end;

总结我的所作所为:

  • 声明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

为什么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
  • 如何阻止dfm包含未发布的属性?
  • 如何阻止dfm包含两次

Hack解决方法

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

initialization
    RegisterClass(TMyDateTimePicker);

finalization
    UnRegisterClass(TMyDateTimePicker);

end.

现在dfm包含一个没有业务知道的控件。每当我保存表格时,它都会包含对它不应该的内容的引用。最糟糕的是:我验证了它对TMyDateTimePicker的错误信念。

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

已知错误?

enter image description here

1 个答案:

答案 0 :(得分:12)

问题是您将错误的Owner分配给TDateTimePicker。您分配的是TContosoFrobber的所有者,而不是TContosoFrobber本身:

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

或者:正如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;