Solved

How to capture a MDIChild close event in the parent

Posted on 2002-04-16
18
649 Views
Last Modified: 2010-08-05
I try to trigger some procedure in MDI application parent from when a MDI child closed.

Thanks.
0
Comment
Question by:jlislo
  • 8
  • 5
  • 3
  • +1
18 Comments
 
LVL 17

Expert Comment

by:inthe
Comment Utility
have you tried:

uses form1;

on form2(mdichild).close event;

form1.myprocedure;
0
 

Author Comment

by:jlislo
Comment Utility
Not yet.

Which event on the main form you will place the "on form2(mdichild).close event;"

Question is which main form even got trigger when the child close.

Thanks.
0
 
LVL 17

Expert Comment

by:inthe
Comment Utility
No no i mean use the child forms close event.

on its close event you could call your main forms procedure

form1.myprocedure;
or
form1.button2.click;
0
 
LVL 2

Expert Comment

by:freshman3k
Comment Utility
Hello!

Just in case you need more events there are
Follow should work:
private
    { Private declarations }
    FClientInstance : TFarProc;
    FPrevClientProc : TFarProc;
    procedure ClientWndProc(var aMessage: TMessage);


implementation

procedure TfrmMForm.FormShow(Sender: TObject);
begin
   FPrevClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
   FClientInstance := MakeObjectInstance(ClientWndProc);
   SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FClientInstance));
end;

procedure TfrmMForm.ClientWndProc(var aMessage: TMessage);

   procedure DoDefault;
   begin
      with aMessage do
        Result := CallWindowProc(FPrevClientProc, ClientHandle, Msg, wParam,
lParam);
   end;

begin
   with aMessage do
     case Msg of
         WM_MDICREATE:
           begin
             {this event is when an application wants to create a child window}
              {put your procedure here}
             DoDefault;
           end;
         WM_MDIDESTROY:
           begin
            {this event is when when an MDI Child is closed.So this event is what you need
            {put your procedure here}
              DoDefault;
           end;
         WM_MDIACTIVATE:
           begin
              DoDefault;
            {this event is when a new MDI child window is activated  
            {put your procedure here}
           end;
         WM_MDINEXT:
           begin
              DoDefault;
            {this event is when a next or previous child window is activated }
            {put your procedure here}
           end;
         else
           DoDefault;
     end;
end;

Good Luck!
0
 
LVL 2

Expert Comment

by:freshman3k
Comment Utility
Hello!

Just in case you need more events there are
Follow should work:
private
    { Private declarations }
    FClientInstance : TFarProc;
    FPrevClientProc : TFarProc;
    procedure ClientWndProc(var aMessage: TMessage);


implementation

procedure TfrmMForm.FormShow(Sender: TObject);
begin
   FPrevClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
   FClientInstance := MakeObjectInstance(ClientWndProc);
   SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FClientInstance));
end;

procedure TfrmMForm.ClientWndProc(var aMessage: TMessage);

   procedure DoDefault;
   begin
      with aMessage do
        Result := CallWindowProc(FPrevClientProc, ClientHandle, Msg, wParam,
lParam);
   end;

begin
   with aMessage do
     case Msg of
         WM_MDICREATE:
           begin
             {this event is when an application wants to create a child window}
              {put your procedure here}
             DoDefault;
           end;
         WM_MDIDESTROY:
           begin
            {this event is when when an MDI Child is closed.So this event is what you need
            {put your procedure here}
              DoDefault;
           end;
         WM_MDIACTIVATE:
           begin
              DoDefault;
            {this event is when a new MDI child window is activated  
            {put your procedure here}
           end;
         WM_MDINEXT:
           begin
              DoDefault;
            {this event is when a next or previous child window is activated }
            {put your procedure here}
           end;
         else
           DoDefault;
     end;
end;

Good Luck!
0
 

Author Comment

by:jlislo
Comment Utility
For inthe:

If I call the main form in MDIChild.onClose event, the MDIChildCount still count the one is closing. I like to use main form's event if possible. Thanks.

For freshman3k
I will try this. Thanks.
0
 

Author Comment

by:jlislo
Comment Utility
For freshman3k

question, where did you place the following code?

begin
  with aMessage do
    ...
  end ;
end;

Thanks.
0
 

Author Comment

by:jlislo
Comment Utility
For freshman3k

Sorry never mind, I didn't read through your code. Let me try this. Thanks.
0
 

Author Comment

by:jlislo
Comment Utility
For freshman3k

Why MDIChildCount still = 1 after  WM_MDIDESTROY?

Did I need to do Application.Processmessage to get a correct MDIChildCount ?

Thanks.

Jammy
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
listening . . .
i would done it like barry . . .

call a mainform-procedure you have coded there in the onclose or ondestroy-event of the childform

why do you need an event?
you can call a notify-procedure
from your coded mainform-procedure,
if you need an on...-event

the notify-procedure
you must code also byself

meikl ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
or you could just send a wm_user+xx message to the mainform,
and code a message-handler in your mainform
... just as third suggestion

meikl ;-)
0
 

Author Comment

by:jlislo
Comment Utility
Hi meikl,

I need to know when a child is create/destroy/active/deactive so I can adjest my main form menu items. Call main from from child does not give me a correct child count. (child.OnClose) What is your thought of the correct way to do this?

Thanks.

Jammy
0
 
LVL 2

Expert Comment

by:freshman3k
Comment Utility
Hello!

Try this code ,this time it has only what you want and some changes:

private
   { Private declarations }
   FClientInstance : TFarProc;
   FPrevClientProc : TFarProc;
   procedure ClientWndProc(var aMessage: TMessage);

implementation

procedure TfrmMForm.FormShow(Sender: TObject);
begin
  FPrevClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
  FClientInstance := MakeObjectInstance(ClientWndProc);
  SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FClientInstance));
end;

procedure TfrmMForm.FormClose(Sender: TObject);
begin
 SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FPrevClientProc));
end;

procedure TfrmMForm.ClientWndProc(var aMessage: TMessage);
begin
  with aMessage do
    case Msg of
      WM_MDIDESTROY:
          begin
           {put your procedure here}
             aMessage.Result := CallWindowProc(FPrevClientProc, ClientHandle, Msg, wParam,lParam);
          end;
    else
      aMessage.Result := CallWindowProc(FPrevClientProc, ClientHandle, Msg, wParam,lParam);  
    end;
end;


0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
>does not give me a correct child count
?
as you now in any way that the child will be closed,
why not decrement the childcount by one,where you do need it
or
you could provide the childform itself as parameter, if needed
like
MainformChildCloseInformationProc(self);
and use this as reference instead of the childcount

i guess also freshmans suggestion will not give you
the right childcount, as the proc is called before the childform is destroyed

meikl ;-)

0
 
LVL 2

Expert Comment

by:freshman3k
Comment Utility
Hello!

Oh now I understand,Here is the modified code(I didnt try it yet):

private
  { Private declarations }
  FClientInstance : TFarProc;
  FPrevClientProc : TFarProc;
  CC : Integer;
  procedure ClientWndProc(var aMessage: TMessage);

implementation

procedure TfrmMForm.FormShow(Sender: TObject);
begin
 FPrevClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
 FClientInstance := MakeObjectInstance(ClientWndProc);
 SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FClientInstance));
end;

procedure TfrmMForm.FormClose(Sender: TObject);
begin
SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FPrevClientProc));
end;

procedure TfrmMForm.ClientWndProc(var aMessage: TMessage);
 
 procedure DoDefault;
  begin
     with aMessage do
       Result := CallWindowProc(FPrevClientProc,ClientHandle, Msg, wParam,lParam);
  end;

begin
 with aMessage do
   case Msg of
     WM_MDIDESTROY:
         begin
           CC:=CC-1;
           {put your procedure here}
           DoDefault;
         end;
     WM_MDICREATE:
         begin
           CC:=CC+1;
           {put your procedure here}
           DoDefault;
         end;
   else
     DoDefault;  
   end;
end;

And now the varible CC contains the childcount

Good Luck!
0
 
LVL 2

Accepted Solution

by:
freshman3k earned 50 total points
Comment Utility
Hello!

Oh now I understand,Here is the modified code(I didnt try it yet):

private
  { Private declarations }
  FClientInstance : TFarProc;
  FPrevClientProc : TFarProc;
  CC : Integer;
  procedure ClientWndProc(var aMessage: TMessage);

implementation

procedure TfrmMForm.FormShow(Sender: TObject);
begin
 FPrevClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
 FClientInstance := MakeObjectInstance(ClientWndProc);
 SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FClientInstance));
end;

procedure TfrmMForm.FormClose(Sender: TObject);
begin
SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FPrevClientProc));
end;

procedure TfrmMForm.ClientWndProc(var aMessage: TMessage);
 
 procedure DoDefault;
  begin
     with aMessage do
       Result := CallWindowProc(FPrevClientProc,ClientHandle, Msg, wParam,lParam);
  end;

begin
 with aMessage do
   case Msg of
     WM_MDIDESTROY:
         begin
           CC:=CC-1;
           {put your procedure here}
           DoDefault;
         end;
     WM_MDICREATE:
         begin
           CC:=CC+1;
           {put your procedure here}
           DoDefault;
         end;
   else
     DoDefault;  
   end;
end;

And now the varible CC contains the childcount

Good Luck!
0
 

Author Comment

by:jlislo
Comment Utility
meikl,

"why not decrement the childcount by one,where you do need it"

I understand if I decrement one I will get to correct number, but why? Is something wrong in MDIChildcount?


freshman3k,

If I add MessageDlg into your code like this

    WM_MDIDESTROY:
        begin
          CC:=CC-1;
          {put your procedure here}
          DoDefault;
          MessageDlg('C:'+inttostr(MDIChildCount), mtInformation, [mbOK], 0);
 
        end;

I will return to correct number but when you close the last child it loop here twice (second time give me the correct number)

But if I put some other procedure here it loop onece and I need to dec the count.

Thank you both very much, if no comment add, I will accept freshman3k's answer.


0
 

Author Comment

by:jlislo
Comment Utility
Thank you very much!
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

743 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now