Question

Guys, I'd like if anyone knows any event or method that I can intercept when all MDI forms were closed.

Example:

I want to implement an event in my main form where when I close all MDI forms, such an event was triggered.

Grateful if anyone can help.

Était-ce utile?

La solution

MDI child forms (in fact any form), while being destroyed, will notify the main form. You can use this notification mechanism. Example:

type
  TForm1 = class(TForm)
    ..
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation);
      override;

  ..

procedure TForm1.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (Operation = opRemove) and (AComponent is TForm) and
      (TForm(AComponent).FormStyle = fsMDIChild) and
      (MDIChildCount = 0) then begin

    // do work

  end;
end;

Autres conseils

Catch the WM_MDIDESTROY message send to the MDI client window:

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FOldClientWndProc: TFarProc;
    procedure NewClientWndProc(var Message: TMessage);
  end;

...

procedure TForm1.FormCreate(Sender: TObject);
begin
  if FormStyle = fsMDIForm then
  begin
    HandleNeeded;
    FOldClientWndProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
    SetWindowLong(ClientHandle, GWL_WNDPROC,
      Integer(MakeObjectInstance(NewClientWndProc)));
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  SetWindowLong(ClientHandle, GWL_WNDPROC, Integer(FOldClientWndProc));
end;

procedure TForm1.NewClientWndProc(var Message: TMessage);
begin
  if Message.Msg = WM_MDIDESTROY then
    if MDIChildCount = 1 then
      // do work
  with Message do
    Result := CallWindowProc(FOldClientWndProc, ClientHandle, Msg, WParam,
      LParam);
end;

You can have the MainForm assign an OnClose or OnDestroy event handler to each MDI child it creates. Each time an MDI client is closed/destroyed, the handler can check if any more MDI child forms are still open, and if not then do whatever it needs to do.

procedure TMainForm.ChildClosed(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  // the child being closed is still in the MDIChild list as it has not been freed yet...
  if MDIChildCount = 1 then
  begin
    // do work
  end;
end;

Or:

const
  APPWM_CHECK_MDI_CHILDREN = WM_APP + 1;

procedure TMainForm.ChildDestroyed(Sender: TObject);
begin
  PostMessage(Handle, APPWM_CHECK_MDI_CHILDREN, 0, 0);
end;

procedure TMainForm.WndProc(var Message: TMessage);
begin
  if Message.Msg = APPWM_CHECK_MDI_CHILDREN then
  begin
    if MDIChildCount = 0 then
    begin
      // do work
    end;
    Exit;
  end;
  inherited;
end;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top