Как разбить вкладки TPageControl на отдельные файлы в Delphi?

у меня есть форма VCL с пятью вкладками TPageControl на нем. Каждый довольно несвязано и имеет много отдельных элементов управления и логики обработки...поэтому я хочу разбить его, чтобы легче было иметь дело с кодом для "только этой вкладки". Имея строку типа

//-------------------------- begin rules tab methods -------------------

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

В настоящее время я рассматриваю создание фрейма VCL для каждой страницы TTabPage. Если бы я это сделал, я бы тоже необходимо загрузить все кадры в TPageControl в конструкторе или при отображении вкладки.

это хороший подход? Было бы лучше сделать целую TForm для каждой вкладки? Должен ли я продолжать обертывать вкладки в TPageControl, или это должно быть изменено на TTabControl, если содержимое загружается динамически? Если это хороший подход, лучше загружать все вкладки при запуске, или каждый раз, когда вкладка отображается? (возможно, плюсы/минусы, если это не совсем очевидно, что лучше в большинстве / всех случаев)

2 ответов


вы можете использовать фреймы или формы.

  • С кадрами вы должны добавить TabControl в качестве родителя для каждого кадра.
  • С формами у вас есть док каждая форма в PageControl (заголовок формы будет автоматически заголовок TabControl).

procedure TMyForm.AddPage( AFormClass : TFormClass );
var
  LForm : TForm;
begin
  LForm := AFormClass.Create( Self );
  LForm.ManualDock( PageControl1, nil, alClient );
  LForm.Show;
end;

пример

создать форму базовых настроек

unit UI_Form_SettingBase;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TUISettingBase_Form = class( TForm )
  private

  protected
    procedure DoSaveData; virtual;
  public
    function CanSaveData : Boolean; virtual;
    procedure SaveData;
  end;

  TUISettingBase_FormClass = class of TUISettingBase_Form;

var
  UISettingBase_Form : TUISettingBase_Form;

implementation

{$R *.dfm}
{ TUISettingBase_Form }

function TUISettingBase_Form.CanSaveData : Boolean;
begin
  Result := True;
end;

procedure TUISettingBase_Form.DoSaveData;
begin

end;

procedure TUISettingBase_Form.SaveData;
begin
  if CanSaveData
  then
    DoSaveData;
end;

end.

выведите все формы настроек из этой формы и переопределите DoSaveData и дополнительно CanSaveData методы

Общие настройки (с простым флажком)

unit UI_Form_SettingCommon;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UI_Form_SettingBase, Vcl.StdCtrls;

type
  TUISettingCommon_Form = class(TUISettingBase_Form)
    CheckBox1: TCheckBox;
  private

  protected
    procedure DoSaveData; override;
  public

  end;

var
  UISettingCommon_Form: TUISettingCommon_Form;

implementation

{$R *.dfm}

procedure TUISettingCommon_Form.DoSaveData;
begin
  inherited;
  // code to save the data
end;

end.

настройки подключения (с простым управлением редактирования)

unit UI_Form_SettingConnection;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UI_Form_SettingBase, Vcl.StdCtrls;

type
  TUISettingConnection_Form = class( TUISettingBase_Form )
    Edit1 : TEdit;
  private
  protected
    procedure DoSaveData; override;
  public
  end;

var
  UISettingConnection_Form : TUISettingConnection_Form;

implementation

{$R *.dfm}
{ TUISettingConnection_Form }

procedure TUISettingConnection_Form.DoSaveData;
begin
  inherited;
  // code to save the data
end;

end.

сложение частей вместе: реальная форма настройки

основная форма настройки также является производной от SettingBase

unit UI_Form_Settings;

interface

uses
  System.Generics.Collections,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UI_Form_SettingBase, Vcl.StdCtrls,
  Vcl.ExtCtrls, Vcl.ComCtrls;

type
  TUISettings_Form = class( TUISettingBase_Form )
    PageControl1 : TPageControl;
    Panel1 : TPanel;
    Save_Button : TButton;
  private
    FForms : TList<TUISettingBase_Form>;
    procedure AddSettingPage( ASettingFormClass : TUISettingBase_FormClass );
  protected
    procedure DoSaveData; override;
  public
    function CanSaveData : Boolean; override;
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
  end;

var
  UISettings_Form : TUISettings_Form;

implementation

{$R *.dfm}

uses
  UI_Form_SettingCommon, UI_Form_SettingConnection;
{ TUISettings_Form }

procedure TUISettings_Form.AddSettingPage( ASettingFormClass : TUISettingBase_FormClass );
var
  LForm : TUISettingBase_Form;
begin
  LForm := ASettingFormClass.Create( Self );
  try
    LForm.ManualDock( PageControl1, nil, alClient );
    LForm.Show;
    FForms.Add( LForm );
    LForm := nil;
  finally
    LForm.Free;
  end;
end;

procedure TUISettings_Form.AfterConstruction;
begin
  inherited;
  FForms := TList<TUISettingBase_Form>.Create;
  // add all the setting forms
  AddSettingPage( TUISettingCommon_Form );
  AddSettingPage( TUISettingConnection_Form );
end;

procedure TUISettings_Form.BeforeDestruction;
begin
  inherited;
  FForms.Free;
end;

function TUISettings_Form.CanSaveData : Boolean;
var
  LForm : TUISettingBase_Form;
begin
  // iterate all setting forms if they can save the data
  Result := True;
  for LForm in FForms do
    Result := Result and LForm.CanSaveData;
end;

procedure TUISettings_Form.DoSaveData;
var
  LForm : TUISettingBase_Form;
begin
  inherited;
  // iterate all setting forms and save the data
  for LForm in FForms do
    LForm.SaveData;
end;

end.

одна вещь, в частности, которую я хотел бы сделать (фокус этого вопроса), - это каким-то образом разбить TPageControl, содержащий пять таблиц TTabSheets. Каждая вкладка представляет собой довольно сплоченный раздел пользовательского интерфейса (и соответствующую логику обработки), поэтому было бы неплохо разбить каждую вкладку на отдельные файлы.

можно использовать TFrame для этого. Дайте каждой странице свой собственный фрейм, который вы можете реализовать и спроектировать в своих отдельных файлах со своими DFMs.

для каждой разбитой вкладки я хотел бы начать с добавления новых форм VCL? или VCL кадров?

кадров. Не используйте встроенные формы, они не очень хорошо работают. Для этой цели были разработаны рамы.

должен ли я оставить TPageControl или изменить его на TTabControl, если содержимое каждой вкладки загружается с панели?

после того как вы создаете новую рамку и конструируете ее по мере необходимости, вы можете после этого либо:

  1. поместите рамку на палитру компонентов (щелкните правой кнопкой мыши на рамке в конструкторе и выберите "Добавить в палитру"), а затем вы можете поместить ее на нужную TTabSheet во время разработки. Установите кадр Align to alClient Если вы хотите, чтобы заполнить весь TTabSheet.

  2. создайте экземпляр объекта Frame в коде во время выполнения, а затем установите его Parent свойства нужного TTabSheet.