Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Компонент не сохраняет свойства [D7, Win2k]


OlegPFR ©   (2005-11-22 19:26:00) 

В написании компонентов новичек, но надо же когда-то начинать...
Проблема в следующем: Создаю компонент TWizardFrame, созданный на основе
TFrame и содержащий в себе PageControl. В контектном меню выбираю "AddPage",
создается страница, которая в дизайнере ведет себя корректно, принимает
на себя другие компоненты (кнопки, чекбоксы, ...), НО при сохранении проекта
и его переоткрытии все исчезает - компонент TWizardFrame чистый.
Как сделать, чтобы добавленные в этот PageControl моего компонента
закладки TTabSheet сохранялись в DFM'е.


unit WizardFrame;
interface
uses
 SysUtils, Classes, Controls, Forms, ExtCtrls, ComCtrls, JvExComCtrls,
 JvComCtrls;

type
 TWizardFrame = class(TFrame)
 private
   { Private declarations }
   FPageControl: TJvPageControl;
   FOnMyEvent: TNotifyEvent;
 protected
   { Protected declarations }
 public
   { Public declarations }
   constructor Create(AOwner: TComponent); override;
 published
   { Published declarations }
   property OnMyEvent: TNotifyEvent read FOnMyEvent write FOnMyEvent;
   property PageControl: TJvPageControl read FPageControl write FPageControl;
 end;

implementation
{$R *.dfm}

{ TWizardFrame }

constructor TWizardFrame.Create(AOwner: TComponent);
begin
 inherited;
 FPageControl := TJvPageControl.Create(Self);
 FPageControl.Parent := Self;
 FPageControl.Align := alClient;
 FPageControl.Name := 'PageControl';
end;

end.

unit RegWizard;
interface
uses
 SysUtils, Classes, Forms, ExtCtrls, ComCtrls,
 WizardFrame;

procedure Register;

implementation

uses
 Controls, Dialogs, JvPageList, JvExComCtrls, JvComCtrls, JvPageListEditorForm,
 DesignIntf, DesignEditors;

type
 TWizardFrameComponentEditor = class(TComponentEditor)
 private
   procedure InsertPage;
   procedure PrevPage;
   procedure NextPage;
   procedure RemovePage;
   function GetPageControl: TJvPageControl;//TJvCustomPageList;
 public
   procedure ExecuteVerb(Index: Integer); override;
   function GetVerb(Index: Integer): string; override;
   function GetVerbCount: Integer; override;
 end;

procedure Register;
begin
 RegisterClass(TWizardFrame);
 RegisterComponents('Standard', [TWizardFrame]);
 RegisterComponentEditor(TWizardFrame, TWizardFrameComponentEditor);
end;

{ TWizardFrameComponentEditor }

function TWizardFrameComponentEditor.GetPageControl: TJvPageControl;//TJvCustomPageList;
begin
 if Component is TWizardFrame then
   Result := TWizardFrame(Component).PageControl;
end;

procedure TWizardFrameComponentEditor.InsertPage;
var
 C: TJvPageControl;
 P: TTabSheet;
begin
 C := GetPageControl;
 P := TTabSheet(Designer.CreateComponent(TTabSheet, C, 0, 0, 0, 0));
 P.PageControl := C;
 C.ActivePage := P;
 Designer.SelectComponent(C);
 Designer.Modified;

end;

procedure TWizardFrameComponentEditor.ExecuteVerb(Index: Integer);
begin
 case Index of
   0: {PrevPage};
   1: {NextPage};
   2: ;
   3: InsertPage;
   4: {RemovePage};
 end;
end;

function TWizardFrameComponentEditor.GetVerb(Index: Integer): string;
begin
 case Index of
   0: Result := 'Prev Page';
   1: Result := 'Next Page';
   2: Result := '-';
   3: Result := 'Add Page';
   4: Result := 'Delete Page'
   else
     Result := '';
 end;
end;

function TWizardFrameComponentEditor.GetVerbCount: Integer;
begin
 Result := 5;
end;

end.


OlegPFR   (2005-11-25 15:43:00) [1]

Спасибо, помогло. Интересно, а можно ли как-то бороться с глюком расположения фрейма в дизайнере (не сохраняется позиция фрейма в дизайнере при переоткрытии модуля)?


Юрий Зотов   (2005-11-24 16:39:00) [2]

> Как определить, что PageControl уже есть в DFM и его создавать не надо?

Например, перенести код создания из конструктора в AfterCreate, а там перед созданием проверять:

if PageControl = nil then
begin
  ... // создаем
end;

> там, правда, есть недостаток - форма создается без DFM'а.

Это не недостаток, это сделано специально. При генерации текста PAS в него включается директива {$R *.DFM}, а это значит, что если DFM и не было, то IDE создаст его сама.

>  как создать DFM к модулю

По аналогии с генерацией текста PAS (в IOTAModuleCreator есть метод NewFormFile).


OlegPFR   (2005-11-24 11:26:00) [3]

Спасибо, получилось, в DFM сохраняет. Но возникла другая проблема: при переоткрытии формы PageControl создается и в Create и загружается из DFM. Как определить, что PageControl уже есть в DFM и его создавать не надо? Вообще, Frame создается из экперта, который создан по примеру CFPack Орлика, там, правда, есть недостаток - форма создается без DFM'а. Если бы знать, как создать DFM к модулю, то можно было бы обойтись без создания PageControl в конструкторе.


Юрий Зотов   (2005-11-23 22:26:00) [4]

Кто назначается Owner'om TabSheet'ов при их создании? PageControl?

Если Owner'om всех контролов сделать форму (как это и делается средой при их набрасывании на форму вручную), то все будет сохраняться. Даже и без SetSubComponent.


OlegPFR   (2005-11-23 15:59:00) [5]

Частично помогло FPageControl.SetSubComponent(True). В DFM свойства сохраняются следующим образом:

object WizardFrame1: TWizardFrame
  ...
  PageControl.Left ...
  PageControl.Top ...
end

Но добавленные с помощью TWizardFrameComponentEditor страницы TTabSheet, видимые в дизайнере, не сохраняются... Хочется видить в DFM что-то типа:

object WizardFrame1: TWizardFrame
  ...
  object PageControl: TJvPageControl
  ...
     object TabSheet1: TTabSheet
     ...
     end
     object TabSheet2: TTabSheet
     ...
     end
  ...  
  end
end

Вообщем, как сделать так, чтобы созданные в дизайнере TTabSheet сохранялись в DFM'е?


Юрий Зотов   (2005-11-22 20:40:00) [6]

Вариант 1 - сказать, что FPageControl является подкомпонентом:
FPageControl.SetSubComponent(True);

Вариант 2 - сделать владельцем FPageControl форму . В этом случае потребуется замещение деструктора.

type
 TWizardFrame = class(TFrame)
 private
   FPageControl: TJvPageControl;
   ...
 public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override; // !!!
 published
   property PageControl: TJvPageControl read FPageControl; // !!!
   ...
 end;

constructor TWizardFrame.Create(AOwner: TComponent);
begin
 inherited;
 FPageControl := TJvPageControl.Create( GetParentForm(Self));
 ...
end;

destructor TWizardFrame.Destroy;
begin
 FreeAndNil(FPageControl);
 inherited
end;

И в любом случае свойство PageControl должно быть доступно только для чтения, иначе оно запросто может быть переназначено и возникнет утечка памяти.


Наверх

Титульная страница Поиск, карта сайта Написать письмо