Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How can I create a form within an interface? 1

Status
Not open for further replies.

DjangMan

Programmer
Jun 1, 2001
1,785
CA
I have a status form that will be displayed and keep the user 'entertained' while I'm working on their request. Up until now I've used a form and displayed it non-modally and updated it's contents as required.

I'm wondering how I might be able to wrap that form within an interface? I'm just starting to understand them but I wouldn't know where to start coding it.
 
Hi DjangMan,

nice question!

here's a starter:
Code:
unit u_class_interfacedForm;

interface

uses Forms, SysUtils;

type
 TFormClass = class of TForm;

 IForm = interface
 ['{42E64582-9DFA-4658-8FA4-F17BA0600004}']
 end;

 TIForm = class(TInterfacedObject, IForm)
 private
   ContainedForm : TForm;
   procedure Show;
 public
   constructor Create(AFormClass : TFormClass);
   destructor destroy; override;
 end;

implementation

{ TIForm }
constructor TIForm.Create(AFormClass: TFormClass);
begin
  ContainedForm := AFormClass.Create(nil);
  ContainedForm.Show;
end;

destructor TIForm.destroy;
begin
  if Assigned(ContainedForm) then
   FreeAndNil(ContainedForm);
  inherited;
end;

end.

How to use it:

Code:
procedure DoSomeWork;

var SplashForm : IForm;

begin
 SplashForm := TIForm.Create(TSplashForm); // this will create and show a form of type TSplashForm (replace it with your formtype)
 DoSomethingUseFull;
 // no need to hide/destroy the form, the interface will take care of that since the SplashForm will no longer be referenced after the procedure ends
end;

As you can see, nice clean AND compact code.
If you have Delphi2010 I could add anonymous methods into the mix, but that is for another discussion :)

/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Thank you! I'm using your TIADOQuery interface in my projects now. I would have certainly missed the TFormClass. I'll post back with example code when I written some just to add to the knowledge base.
 
I got it, I think. Your interface will wrap around any type of TForm and if I have public methods in my form I can access them using something like:
Code:
  TSplashForm(SplashForm.ContainedForm).MyFormMethod;

Am I getting it?

I'm guessing that the anonymous methods would let me avoid the typecasting...
 
Yes indeed.

there are several solutions however.
let's make this thread a bit more "advanced".

- Solution 1 : Use RTTI:

Code:
unit u_class_interfacedForm;

interface

uses Forms, SysUtils;

type
 TFormClass = class of TForm;
 TExecute = procedure of object;

 IForm = interface
 ['{42E64582-9DFA-4658-8FA4-F17BA0600004}']
   procedure CallMethod(Name : String);
 end;

 TIForm = class(TInterfacedObject, IForm)
 private
   ContainedForm : TForm;
 public
   procedure CallMethod(Name : String);
   constructor Create(AFormClass : TFormClass);
   destructor Destroy; override;
 end;

implementation

{ TIForm }
procedure TIForm.CallMethod(Name: String);

var Routine : TMethod;
    Execute : TExecute;
    
begin
 Routine.Data := Pointer(ContainedForm) ;
 Routine.Code := ContainedForm.MethodAddress(Name);
 if Assigned(Routine.Code) then
  begin
   Execute := TExecute(Routine) ;
   Execute; // call the method
  end
 else
  raise Exception.CreateFmt('Method %s not found!', [Name]); 
end;


constructor TIForm.Create(AFormClass: TFormClass);
begin
  ContainedForm := AFormClass.Create(nil);
  ContainedForm.Show;
end;

destructor TIForm.Destroy;
begin
  if Assigned(ContainedForm) then
   FreeAndNil(ContainedForm);
  inherited;
end;

end.

I added 'CallMethod' to my interface, you can use it to call a published method on your class (remember, only published methods genereate RTTI).

our splashform:
Code:
unit Unit6;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TfrmSplash = class(TForm)
  private
    { Private declarations }
  published // important!!!!
    { Public declarations }
    procedure HelloWorld;
  end;

var
  frmSplash: TfrmSplash;

implementation

{$R *.dfm}

{ TfrmSplash }

procedure TfrmSplash.HelloWorld;
begin
 ShowMessage('Hello World!');
end;

end.

How to use it:

Code:
procedure TForm5.FormCreate(Sender: TObject);

var form : IForm;

begin
 form := TIForm.Create(TfrmSplash);
 form.CallMethod('HelloWorld');
end;

There are a lot of drawbacks however:
- need for published methods
- what about parameters??
- you lose compile time checking



-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top