当所有MDI窗体关闭时的事件

7

大家好,我想知道是否有任何事件或方法可以拦截当所有 MDI 窗体关闭时的情况。

示例:

我想在我的主窗体中实现一个事件,在关闭所有 MDI 窗体时触发此事件。

如果有人能帮忙,将不胜感激。

3个回答

8

MDI子窗体(实际上是任何窗体)在销毁时会通知主窗体。您可以使用此通知机制。示例:

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;

@NGLN - 谢谢!不过你的更强大,如果你需要知道一个子元素何时做了这个和那个... :) - Sertac Akyuz
1
NGLN,Sertac Akyus和Remy Lebeau。感谢你们的回答,都非常出色。你们真的很棒。对于我的情况,Sertac Akyuz的代码最好。它更简单,解决了我的问题。NGLN和Remy,我会保存你们的代码以备将来需要。谢谢。 - Delphiman

4

捕获发送到MDI客户端窗口的WM_MDIDESTROY消息:

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;

2

您可以让主窗体为创建的每个MDI子窗体分配一个OnCloseOnDestroy事件处理程序。每次关闭/销毁MDI客户端时,处理程序可以检查是否还有更多MDI子窗体仍然处于打开状态,如果没有,则执行其需要执行的操作。

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;

或者:

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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接