Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 390
  • Last Modified:

Is this inherited? how?

Hi.
    I asked someone for a question, and he showed me some code, and I read and understood, but I found one thing here:
    Form1.OnClose := MyOnClose;
    This will make the Form1.OnClose event call MyOnClose procedure instead of its OnClose procedure. But this will occur another issue, some forms need to execute something in its OnClose procedure, so I cannot ignore it, but I need every form call MyOnClose when it close, how? Is this inherited? I cannot modify so many forms - too many forms, so, how to inherit the form1(and other forms in this case) its own OnClose and then call MyOnClose?
    Thank you!!
0
prefix
Asked:
prefix
  • 7
  • 5
  • 2
  • +3
1 Solution
 
LukA_YJKCommented:
As far as I understand now you wrote in all special froms FormM1...FormMk this code OnClose := MyOnClose (maybe in OnCreate)
0
 
BAlexandrovCommented:
Before assignment of Form1.OnClose := MyOnClose; tou must save original somewhere like:

OrigOnClose := Form1.OnClose;
Form1.OnClose := MyOnClose;


in MyOnClose at end (or begin)  call

If Assigned(OrigOnClose) Then OrigOnClose;


Bojidar Alexandrov
0
 
steve_hskCommented:
Hi Prefix ...

Unfortunately you cannot inherit event handlers, but only methods, functions and procedures.

Secondly, there exists no hidden or default functionality that you need to inherit from the onClose event occuring.

So if you wanted to use a generic MyOnClose handler, in each form's constructor you would need to setup the handler :

Constructor TForm1.Create (...);
Begin
   OnClose := OnMyClose;
End;

Constructor TForm2.Create (...);
Begin
   OnClose := OnMyClose;
End;

PROCEDRUE MyOnClose (Sender : TObject);
BEGIN  
   // Handle your specific requirements here
   If Sender = Form1 THEN
   BEGIN
      // Specific stuff ...
      // This is the main form, so close the app
      Application.Terminate ;
   END
   ELSE If Sender = Form2 THEN
   BEGIN
      // This is not the main form
      Form2.CLose ;
      // etc etc ...
   END;  
END;

There is always an alternative, and you could capture the close message for each form, and then use a generic handler too !

PROCEDURE WCCLOSE (VAR Msg : Tmessage); MESSAGE WM_CLOSE;

PROCEDURE TForm1.WCCLOSE (VAR Msg : Tmessage);
BEGIN
     // 1.0 Ask the user whether vthey want to quit the app
     IF MessageDlg(MSGTITLE +#13+#10+
                   'Request for application closure. Proceed with termination ?'
                   , mtConfirmation,
                   [mbYes, mbNo],
                   0) = mrYes then
     BEGIN
          // 1.1 Finally End Application's Instance
          Application.Terminate ;
     END;
END;

Hope this helps,
STeve
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
geobulCommented:
Hi,

You can inherit it:

// Unit1.TForm1: ancestor of all your other forms:
type
  TForm1 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation

{$R *.DFM}

// this is your MyOnClose procedure
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ShowMessage('Form1.Close');
end;

// A descendant form
uses Unit1; // where TForm1 is declared

type
  TForm2 = class(TForm1) // TForm1 instead of TForm
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ShowMessage('Form2.Close');
  inherited; // calls Form1.OnClose
end;

You may exclude Form1 from autocreation list of the project (Form1 is not the main form). Form1 will never be created and used as a form. Its purpose is to add some functionality to other forms that inherit from TForm1.

Regards, Geo
0
 
mocartsCommented:
if this is from q about TabControl then you must change a bit class design. in mdichild form add a property TabControl and operate on it in child form. use this form as base form for all mdichild forms (inherit from it). in inherited forms you can safely use onClose etc. events.

type
  TForm2 = class(TForm)
    Label1: TLabel;
    procedure FormActivate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    FTab: TTabControl;
  public
    property Tab: TTabControl read FTab write FTab;
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

procedure TForm2.FormActivate(Sender: TObject);
var
  idx: Integer;
begin
  Caption := TimeToStr(now);
  if assigned(Tab) then begin
    idx := Tab.Tabs.IndexOfObject(Sender);
    if idx > -1 then
      Tab.TabIndex := idx;
  end;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
var
  idx: Integer;
begin
  Action := caFree;
  if assigned(Tab) then begin
    idx := Tab.Tabs.IndexOfObject(Sender);
    if idx > -1 then
      Tab.Tabs.Delete(idx);
  end;
end;

in unit1:

procedure TForm1.StartTheForm(TheForm: TFormClass);
var
  FormName: TForm2;
begin
  FormName := TForm2.Create(Self);
  FormName.Tab := TabControl1;
  FormName.Show;
  TabControl1.Tabs.AddObject(FormName.Caption, FormName);
  TabControl1.TabIndex := pred(TabControl1.Tabs.Count);
end;

wbr, mo.
0
 
prefixAuthor Commented:
This really works!! Thanks!
0
 
geobulCommented:
Hi prefix,

You asked how to inherit TForm.OnClose and I showed you how this could be done.

Accepted answer works, of course, but:

1. there is no inheritance at all.

2. needs 3 changes in every form:
- add: a declaration of OrigOnClose;
- add: OrigOnClose := Form1.OnClose; in OnCreate
- add: if Assigned(...) then ...; in OnClose.
My example (with inheritance) needs 3 chages also:
- change: TForm to TForm1 (you may give it a name as you wish) in the definition of the forms;
- remove: Form1.OnClose := MyOnClose; from OnCreate;
- add: inherited; in OnClose.

You can achieve the desired result with two lines less and let OOP work for you.

Regards, Geo
0
 
BAlexandrovCommented:
... and change the .dfm files of all forms to begin with "inherited"...
0
 
geobulCommented:
BAlexandrov, don't understand me wrong. Your code is correct and works well (I already said that). I'm talking about using OOP features and let them work for us. If the questioner doesn't want to use inheritance there is even easier way: in OnClose event of every form add one extra line at the end:

MyOnClose(Sender,Action);

and remove OnClose := MyOnClose; in OnCreate event.

Regards, Geo
0
 
BAlexandrovCommented:
Of course your way is far more clear, but the questioner do not want (or minimise) modifying existing forms. And with your sollution he must update also the dfm files - you have forgot to mention that.

He is a beginner and want fast solltuon - let him choose what him want.

regards,
Bojidar Alexandrov
0
 
geobulCommented:
I can't understand. Why should he have to modify any dfm files manually? Changing
 
FormX = class(TForm)
to
FormX = class(TGenericForm)

is enough.

Regards, Geo
0
 
BAlexandrovCommented:
It may work but is not correct.

When you inherit forms you must update also the first line of dfm and change "object" to "inherited"

Do it visually and see yourself the result form.
0
 
geobulCommented:
I've never done so and I've never had problems doing so.
0
 
BAlexandrovCommented:
And you never have understand what you do and never have more than one level of inheritance.

You have a dfm file attached at TForm level and if you want the successors to be correct they must inherit this dfm too, else you end up with two classes used same dfm and what if you want the successor to be different?

Make it OOP way!
0
 
mocartsCommented:
in MDI interface accepted answer will work until you close last form. remaining forms closing can raise access violations as saved event handler refers to last opened form instance..
you can of course maintain some list of event handlers, but that's so ugly :)
OOP way is to design classes with complete functionality enclosed in it. i.e. you assign to MDIChild TabControl property and MDIChild knows how to operate on it in case of activation and closing (and on Showing, too)

wbr, mo.
0
 
geobulCommented:
That's your opinion. I have as many levels of inheritance as I want, of course. And every form class has its own dfm file.
0
 
geobulCommented:
My previous post was addressed to BAlexandrov.
0
 
prefixAuthor Commented:
Hi, everyone here:
   First thanks for all of your help. I accepted BAlexandrov's comment as answer because in my case, I have already done some code in this procedure which is in my MDIMainForm:
procedure OnMDIChildClose(Sender: TObject; var Action: TCloseAction)

I used this procedure to set the ChildForm := nil, and remove the associated tab in the tabcontrol.

This procedure is for all of my MDIChildForms, so, it's very easy to add more one line of code in this procedure.

And the biggest problem was, there are more than 20 Childforms in my project, geobul's mothod is an OOP way but it would take much work in this case. - But i used BAlexandrov's method, I only modified my MDIMainForm, add a few code,  that's already done(it works correctly). Even modifying one ChildForm - it's needn't.

So at last, i preferred to BAlexandrov's comment.

geobul and mocarts's comment I have read and I could understand, thank you all the same.
0
 
LukA_YJKCommented:
Wow, easy, men, I'm still getting comment notifications ;) Glad to see you all. I think BAlexandrov is right in sence of that all initial settings are stored in .dfm files, even for Event properties. Geobul, your solution is beautiful as always...
By the way, everybody say WELCOME to BAlexandrov! Bojidar = God's Gift ;)
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 5
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now