Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

How to capture a MDIChild close event in the parent

Posted on 2002-04-16
18
Medium Priority
?
679 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
ID: 6945415
have you tried:

uses form1;

on form2(mdichild).close event;

form1.myprocedure;
0
 

Author Comment

by:jlislo
ID: 6945506
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
ID: 6945548
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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 2

Expert Comment

by:freshman3k
ID: 6945573
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
ID: 6945580
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
ID: 6945594
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
ID: 6945718
For freshman3k

question, where did you place the following code?

begin
  with aMessage do
    ...
  end ;
end;

Thanks.
0
 

Author Comment

by:jlislo
ID: 6945720
For freshman3k

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

Author Comment

by:jlislo
ID: 6945732
For freshman3k

Why MDIChildCount still = 1 after  WM_MDIDESTROY?

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

Thanks.

Jammy
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6945798
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
ID: 6945803
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
ID: 6945818
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
ID: 6945850
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
ID: 6945979
>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
ID: 6946009
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 200 total points
ID: 6946024
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
ID: 6946105
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
ID: 6946132
Thank you very much!
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

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.

Question has a verified solution.

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

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
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…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …
Suggested Courses

971 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