Frage

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.

War es hilfreich?

Lösung

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;

Andere Tipps

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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top