我有一个自定义控件:

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;

所以总结一下我所做的:
  • 声明一个私有(private)变量 TDateTimePicker
  • 将其公开为 公共(public) (即非 发布的 )属性,其类型为 TDateTimePicker
  • 通过多态,控件实际上是TDateTimePicker
  • 后代

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

    DFM

    这就是为什么我不明白为什么在设计时出现错误的原因:



    为什么要寻找那个类(class)?实现细节中的那个类;它不是为流媒体发布的。流媒体系统如何尝试创建它!?所以我检查了 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 中:
  • 属性是 public ,而不是 发布

  • 如何阻止表单流系统在 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 将其包含两次?

  • 黑客解决方法

    我知道可怕的黑客:告诉 DFM 关于它不应该知道的控制:
    initialization
        RegisterClass(TMyDateTimePicker);
    
    finalization
        UnRegisterClass(TMyDateTimePicker);
    
    end.
    

    现在 dfm 包含一个它不知道的控件。任何时候我保存表单时,它都会包含对它不应该的东西的引用。最糟糕的是:我验证了对 TMyDateTimePicker 的错误信念。

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

    已知错误?

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

    最佳答案

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

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

    或者:正如 Jerry Doge 所提到的,您可以改用 nil Owner。您只需要手动对 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;
    

    关于delphi - 如何告诉 Delphi 在 DFM 中不包含未发布的属性?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39498418/

    10-09 09:33