Commit 28b15805 authored by Rickard Engberg's avatar Rickard Engberg
Browse files

Example of Delphi frame inheritance

parents
/*.local
/*.identcache
/*.stat
/Win32/Debug/*.dcu
/__history
/*.skincfg
object AbstractContentFrame: TAbstractContentFrame
Left = 0
Top = 0
Width = 451
Height = 305
Align = alClient
TabOrder = 0
object CaptionPanel: TPanel
Left = 0
Top = 0
Width = 451
Height = 41
Align = alTop
Caption = 'CaptionPanel'
TabOrder = 0
end
end
unit AbstractContentFrameUnit;
(*
The Abstract Content Frame introduces basic functionality like Ok, Cancel,
positioning, a title panel etc. When the OK or Cancel button of the
generic dialog form is clicked, it calls the methods OK or Cancel which
in turn calls the virtual methods DoOk or DoCancel. These can be overridden
in the descandant frames to perform specific functionality for the
respective frame/content type.
*)
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
type
TAbstractContentFrame = class( TFrame )
CaptionPanel : TPanel;
protected
procedure DoOk; virtual;
procedure DoCancel; virtual;
public
// Notice that the Ok(Cancel method (called from outside of this frame class) and the
// DoOk and DoCancel virtual methods are separated. This makes for a cleaner implementation
// in the descendants, and is in line with the pattern to never, ever have functionality
// code in Delphi form event methods (like OnClick).
// In my oppinion, no funktional code should ever be put in public methods. Public
// methods should always use private methods or, if they should be virtual, protected methods.
procedure Ok;
procedure Cancel;
end;
TContentFrameType = class of TAbstractContentFrame;
implementation
{$R *.dfm}
procedure TAbstractContentFrame.DoOk;
begin
end;
procedure TAbstractContentFrame.DoCancel;
begin
end;
procedure TAbstractContentFrame.Ok;
begin
DoOk;
end;
procedure TAbstractContentFrame.Cancel;
begin
DoCancel;
end;
end.
inherited CompanyContentFrame: TCompanyContentFrame
object Label1: TLabel [0]
Left = 24
Top = 80
Width = 74
Height = 13
Caption = 'Company name'
end
object Edit1: TEdit
Left = 120
Top = 77
Width = 313
Height = 21
TabOrder = 1
Text = 'Edit1'
end
end
unit CompanyContentFrameUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, AbstractContentFrameUnit,
Vcl.StdCtrls, Vcl.ExtCtrls;
type
TCompanyContentFrame = class( TAbstractContentFrame )
Edit1 : TEdit;
Label1 : TLabel;
protected
// These Do-functions are called by their respective Ok/Cancel methods, which are in
// turn called by the generic dialog when the user clicks on a dialog button. This
// illustrates the interfacing between the generic dialog and the form.
procedure DoOk; override;
procedure DoCancel; override;
end;
var
CompanyContentFrame : TCompanyContentFrame;
implementation
{$R *.dfm}
procedure TCompanyContentFrame.DoOk;
begin
inherited;
ShowMessage( 'The company dialog was OK''d' );
end;
procedure TCompanyContentFrame.DoCancel;
begin
inherited;
ShowMessage( 'The company dialog was cancelled' );
end;
end.
object GenericDialogForm: TGenericDialogForm
Left = 0
Top = 0
BorderStyle = bsDialog
Caption = 'The Dialog Frame'
ClientHeight = 388
ClientWidth = 672
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
PixelsPerInch = 96
TextHeight = 13
object PanelContent: TPanel
Left = 0
Top = 0
Width = 672
Height = 328
Align = alClient
Caption = 'PanelContent'
ShowCaption = False
TabOrder = 0
end
object PanelButtons: TPanel
Left = 0
Top = 328
Width = 672
Height = 60
Align = alBottom
Caption = 'PanelButtons'
ShowCaption = False
TabOrder = 1
object OkButton: TButton
Left = 472
Top = 16
Width = 75
Height = 25
Caption = 'OkButton'
Default = True
ModalResult = 1
TabOrder = 0
OnClick = OkButtonClick
end
object CancelButton: TButton
Left = 568
Top = 16
Width = 75
Height = 25
Cancel = True
Caption = 'CancelButton'
ModalResult = 2
TabOrder = 1
OnClick = CancelButtonClick
end
end
end
unit GenericDialogFormUnit;
(*
The generic dialog form gets created only once as the application starts up, making for
a very lean startup. The generic form could even be created on demand, using a simple getter
function that creates the form as it is needed.
*)
interface
uses
AbstractContentFrameUnit,
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TGenericDialogForm = class( TForm )
PanelContent : TPanel;
PanelButtons : TPanel;
OkButton : TButton;
CancelButton : TButton;
procedure CancelButtonClick( Sender : TObject );
procedure OkButtonClick( Sender : TObject );
private
FContentFrame : TAbstractContentFrame;
FContentFrameType : TContentFrameType;
procedure SetContentFrameType( const AContentFrameType : TContentFrameType );
procedure DoOkClick;
procedure DoCancelClick;
public
property ContentFrame : TAbstractContentFrame read FContentFrame;
property ContentFrameType : TContentFrameType read FContentFrameType write SetContentFrameType;
end;
var
GenericDialogForm : TGenericDialogForm;
implementation
{$R *.dfm}
procedure TGenericDialogForm.SetContentFrameType( const AContentFrameType : TContentFrameType );
begin
// Discard a possible earlier frame content. This could be done by other means, of course
FreeAndNil( FContentFrame );
// Set the new frame type if you need to
FContentFrameType := AContentFrameType;
// Create the new content frame and assign it as the new ContentFrame
FContentFrame := AContentFrameType.Create( Application.MainForm );
FContentFrame.Parent := PanelContent;
end;
procedure TGenericDialogForm.DoOkClick;
begin
Assert( Assigned( FContentFrame ), 'Content frame not assigned' );
// This will call the Ok method of the current form. Notice that we don't need
// to include the specialized frame class in the uses statement of this unit, only
// its abstract parent.
FContentFrame.Ok;
end;
procedure TGenericDialogForm.DoCancelClick;
begin
Assert( Assigned( FContentFrame ), 'Content frame not assigned' );
// This will call the Cancel mathod of the current form. Notice that we don't need
// to include the specialized frame class in the uses statement of this unit, only
// its abstract parent.
FContentFrame.Cancel;
end;
procedure TGenericDialogForm.OkButtonClick( Sender : TObject );
begin
// Nothing but executing the private Do-methods in an OnClick event
DoOkClick;
end;
procedure TGenericDialogForm.CancelButtonClick( Sender : TObject );
begin
// Nothing but executing the private Do-methods in an OnClick event
DoCancelClick;
end;
end.
object MainForm: TMainForm
Left = 0
Top = 0
Caption = 'The Fame Inheritance Example'
ClientHeight = 378
ClientWidth = 662
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object OpenDialogButton1: TButton
Left = 32
Top = 40
Width = 121
Height = 25
Caption = 'Open Person Dialog'
TabOrder = 0
OnClick = OpenDialogButton1Click
end
object OpenDialogButton2: TButton
Left = 32
Top = 71
Width = 121
Height = 25
Caption = 'Open Company Dialog'
TabOrder = 1
OnClick = OpenDialogButton2Click
end
end
unit MainFormUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TMainForm = class( TForm )
OpenDialogButton1 : TButton;
OpenDialogButton2 : TButton;
procedure OpenDialogButton1Click( Sender : TObject );
procedure OpenDialogButton2Click( Sender : TObject );
end;
var
MainForm : TMainForm;
implementation
{$R *.dfm}
uses
GenericDialogFormUnit,
PersonContentFrameUnit,
CompanyContentFrameUnit;
procedure TMainForm.OpenDialogButton1Click( Sender : TObject );
begin
(*
Getting the correct frame could very easily be changed to use a frame factory pattern
*)
GenericDialogForm.ContentFrameType := TPersonContentFrame;
GenericDialogForm.ShowModal;
end;
procedure TMainForm.OpenDialogButton2Click( Sender : TObject );
begin
(*
Getting the correct frame could very easily be changed to use a frame factory pattern
*)
GenericDialogForm.ContentFrameType := TCompanyContentFrame;
GenericDialogForm.ShowModal;
end;
end.
inherited PersonContentFrame: TPersonContentFrame
ExplicitWidth = 451
ExplicitHeight = 305
object Label1: TLabel [0]
Left = 24
Top = 80
Width = 50
Height = 13
Caption = 'Full Name:'
end
inherited CaptionPanel: TPanel
Width = 451
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 451
end
object Edit1: TEdit
Left = 120
Top = 77
Width = 313
Height = 21
TabOrder = 1
Text = 'Edit1'
end
end
unit PersonContentFrameUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, AbstractContentFrameUnit,
Vcl.StdCtrls, Vcl.ExtCtrls;
type
TPersonContentFrame = class( TAbstractContentFrame )
Label1 : TLabel;
Edit1 : TEdit;
protected
// These Do-functions are called by their respective Ok/Cancel methods, which are in
// turn called by the generic dialog when the user clicks on a dialog button. This
// illustrates the interfacing between the generic dialog and the form.
procedure DoOk; override;
procedure DoCancel; override;
public
end;
implementation
{$R *.dfm}
procedure TPersonContentFrame.DoOk;
begin
inherited;
ShowMessage( 'The person dialog was OK''d' );
end;
procedure TPersonContentFrame.DoCancel;
begin
inherited;
ShowMessage( 'The person dialog was cancelled' );
end;
end.
program TheFrameInheritanceExample;
uses
Vcl.Forms,
MainFormUnit in 'MainFormUnit.pas' {MainForm} ,
AbstractContentFrameUnit in 'AbstractContentFrameUnit.pas' {AbstractContentFrame: TFrame} ,
GenericDialogFormUnit in 'GenericDialogFormUnit.pas' {GenericDialogForm} ,
PersonContentFrameUnit in 'PersonContentFrameUnit.pas' {PersonContentFrame: TFrame} ,
CompanyContentFrameUnit in 'CompanyContentFrameUnit.pas' {CompanyContentFrame: TFrame};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm( TMainForm, MainForm );
Application.CreateForm( TGenericDialogForm, GenericDialogForm );
Application.Run;
end.
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment