?
Solved

Is this inherited? how?

Posted on 2003-03-14
19
Medium Priority
?
385 Views
Last Modified: 2010-04-04
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
Comment
Question by:prefix
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
  • 2
  • +3
19 Comments
 
LVL 3

Expert Comment

by:LukA_YJK
ID: 8141688
As far as I understand now you wrote in all special froms FormM1...FormMk this code OnClose := MyOnClose (maybe in OnCreate)
0
 
LVL 6

Accepted Solution

by:
BAlexandrov earned 500 total points
ID: 8141743
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
 
LVL 2

Expert Comment

by:steve_hsk
ID: 8142140
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
Industry Leaders: 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!

 
LVL 17

Expert Comment

by:geobul
ID: 8142293
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
 
LVL 9

Expert Comment

by:mocarts
ID: 8143605
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
 
LVL 1

Author Comment

by:prefix
ID: 8148997
This really works!! Thanks!
0
 
LVL 17

Expert Comment

by:geobul
ID: 8149861
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
 
LVL 6

Expert Comment

by:BAlexandrov
ID: 8149955
... and change the .dfm files of all forms to begin with "inherited"...
0
 
LVL 17

Expert Comment

by:geobul
ID: 8150088
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
 
LVL 6

Expert Comment

by:BAlexandrov
ID: 8150125
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
 
LVL 17

Expert Comment

by:geobul
ID: 8150175
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
 
LVL 6

Expert Comment

by:BAlexandrov
ID: 8150204
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
 
LVL 17

Expert Comment

by:geobul
ID: 8150317
I've never done so and I've never had problems doing so.
0
 
LVL 6

Expert Comment

by:BAlexandrov
ID: 8150615
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
 
LVL 9

Expert Comment

by:mocarts
ID: 8150742
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
 
LVL 17

Expert Comment

by:geobul
ID: 8150745
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
 
LVL 17

Expert Comment

by:geobul
ID: 8150754
My previous post was addressed to BAlexandrov.
0
 
LVL 1

Author Comment

by:prefix
ID: 8156776
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
 
LVL 3

Expert Comment

by:LukA_YJK
ID: 8157191
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

Industry Leaders: 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!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Suggested Courses
Course of the Month12 days, 21 hours left to enroll

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question