2016-09-14 7 views
6

У меня есть пользовательский элемент управления:Как сообщить Delphi не включать в 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).

ДФМ

Именно поэтому я не мог понять, почему я получил ошибку во время разработки:

Класс 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

+0

Попробуйте не устанавливать владельца. Передавайте 'nil' своим владельцем при его создании. (Разумеется, вам придется явно освободить его и в этом случае). –

ответ

12

Проблема заключается в том, что вы назначаете неправильный Owner к TDateTimePicker. Вы назначаете ваш Владелец TContosoFrobber «s вместо самого TContosoFrobber:

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

Или: как уже упоминалось Джерри дож, вы можете использовать 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; 
+0

Всякий раз, когда я делаю такие вещи, я обычно передаю 'nil' и никогда не имел проблемы. Можете ли вы объяснить, какая разница на самом деле? –

+4

Когда 'TDataModule' /' TFrame'/'TForm' сохраняются в DFM, любые компоненты, которые они непосредственно принадлежат, которые не имеют назначенного родителя, также получают потоковое вещание. В приведенном примере объект 'TMyDateTimePicker' не имеет назначенного родителя. Если его «Владелец» установлен в форму, это может привести к возникновению проблемы. Установка «TContosoFrobber» в качестве Владельца устраняет проблему (и избегает необходимости явного «Свободного» во время уничтожения). –

+0

@RemyLebeau good exp – Sami