views:

1862

answers:

2

Hi, I'm developing MDI application which assigns a tab for each created MDI child. I need to "catch" OnActivate, OnCreate and OnDestroy events of child form in the main (parent) form code. Simply calling the code in children form is impossible for me, as there are many form's classes that are used as MDI children, also the plugin can load it's own form...

So, my question is: how to catch that MDI child form has been activated/deactivated without using child form's events ?

+3  A: 

I wrote a Taskbar type of component a bunch of years ago that does just this type of thing. It's called TrmMDITaskbar. You can find a copy of it on Torrys, it's a part of the rmControls library package. It handles activation, minimizing, maximizing etc.

The gist of how it works is that it hooks the MDIParents window handle looking for MDIChild events and does stuff based on those events.

If you're looking to write your own I would suggest that as a good place to start.

Ryan.

P.S. The version on Torrys is a little older but should still work. I do have a newer version available on my support website. (Mills Enterprise)

Ryan J. Mills
thanks. finally I solved it using code from SpTBXLib which hooks using WH_CBT flag ... :)
migajek
hi ryan, i`ll love to try that component but the support website gives me an Error 403 - Forbidden (You tried to access a document for which you don't have privileges.)
Alin Sfetcu
@Alin Sfetcu, I've recently changed my hosting service and have yet to get all of my links and forums reinstalled. To tell the truth I thought I had the support forums functioning already. I'll look into that ASAP. Sorry for the goof. As I stated the Torry site copy should still work.
Ryan J. Mills
A: 

You could always hook the events "after the fact" from your code at runtime. Basically create a generic OnActivate that looks something like this:

type
  TEventHolder = class
  private
    FSFActivate: TNotifyEvent;
  published
    property SavedFormActivate : TNotifyEvent 
        read FSFActivate write fSFActivate;
  end;

type
  TMainForm = class(Tform)
    :
    SavedEvents : tStringList;
    procedure ChildFormActivate(Sender: TObject);
    procedure InitChildForm(MdiForm:TForm);
  end;

procedure TMainForm.ChildFormActivate(Sender: TObject);
var
  i : integer;
begin
  // your special processing here this is called for the child form.
  i := SavedEvents.IndexOf(ClassName);
  if i <> -1 then
    tEventHolder(SavedEvents.Objects[i]).SavedFormActivate(Sender);
end;

procedure TMainForm.InitChildForm(MdiForm:TForm);
var
  OrigEvents : TEventHolder; 
begin
  if not Assigned(SavedEvents) then
    SavedEvents := tSTringlist.create;
  if Assigned(MdiForm.OnActivate) then
    begin
      OrigEvents := tEventHolder.create;
      OrigEvents.SavedFormActivate := MdiForm.OnActivate;
      SavedEvents.AddObject(MdiForm.ClassName,OrigEvents); 
    end;
  MdiForm.OnActivate := ChildFormActivate;
end;

Then call the InitChildForm to set the event handlers to your generic versions at some point in your program (most likely right after you create the form). Of course upon main form closure you will want to free the SavedEvents (and linked objects).

skamradt