我有一个自定义控件:
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
这就是我无法理解为什么我在设计时遇到错误的原因:
Class TMyDateTimePicker not found
为什么要找那个班?该类在实现细节中;它没有发布用于流式传输.流媒体系统甚至试图创建它!?所以我检查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包含它两次?
黑客解决方法
我知道可怕的黑客攻击:告诉DFM控制它不应该让任何业务知道:
initialization RegisterClass(TMyDateTimePicker); finalization UnRegisterClass(TMyDateTimePicker); end.
现在dfm包含一个没有业务知道的控件.每次我保存表单时,它都会包含对不应该的内容的引用.最糟糕的是:我验证了它对TMyDateTimePicker的错误信念.
为什么Delphi XE6在重新安装之前没有这样做?也许我需要安装最新更新的长期以来不支持的Delphi版本?
已知错误?
解决方法
问题是您将错误的所有者分配给TDateTimePicker.您正在分配您的TContosoFrobber所有者而不是TContosoFrobber本身:
constructor TContosoFrobber.Create(AOwner: TComponent); begin inherted Create(AOwner); FMyControl := TMyDateTimePicker.Create(Self); // <-- not AOwner! end;
或者:正如Jerry Doge所提到的,你可以使用零所有者.你只需手动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;