当 MDI 子窗体最大化时捕获 Delphi MDI 子窗体最小化事件

Catch Delphi MDI Child minimize event when the MDI Child form is maximized

我需要一些帮助来尝试捕获 MDI 子窗体最大化时的最小化事件。

单击下图中红色圆圈中的按钮时,当表单未最大化时,我能够捕获 minimize/restore/maximize 事件。

我使用 WMSysCommand 捕获上述事件:

procedure TMDIChildForm.WMSysCommand(var Msg: TWMSysCommand);
begin
  if Msg.CmdType = SC_MINIMIZE then
  begin
    //my code here
  end;
end;

当我尝试在 MDI 子窗体最大化时使用 WMSysCommand 捕获相同的事件并单击下图中红色圆圈中的按钮时,它不会调用此代码。

无论我尝试过什么,我都没有成功捕捉到这些事件。如果有人能指出我正确的方向,将不胜感激。谢谢。

当我尝试时对我来说效果很好:

type
  TMDIChildForm = class(TForm)
  private
    { Private declarations }
    procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
  public
    { Public declarations }
  end;

procedure TMDIChildForm.WMSysCommand(var Msg: TWMSysCommand);
begin
  inherited; // <-- ADD THIS!!
  if Msg.CmdType = SC_MINIMIZE then
  begin
    // code here
  end;
end;

WMSysCommand() 会在 MDI 子项最小化时捕获 SC_MINIMIZE 通知,无论它之前是否按预期最大化。

确保 TMDIChildForm.WMSysCommand() 调用 inherited(如上所示)将 WM_SYSCOMMAND 消息传递给默认处理程序,以便 Windows 有机会处理它。

在做了一些进一步的挖掘之后,我遇到了这个问题。 @Remy 请看下面。

我正在使用 TActionMainMenuBar 代替父 MDI 窗体上的 TMainMenu。 TActionMainMenuBar 处理 minimize/restore/maximize 按钮点击的方式与 TMainMenu 不同。下面的代码来自 Vcl.ActnMenus 文件:

type  
  TInternalMDIAction = class(TWindowAction)
  private
    { Private declarations }
  public
    { Public declarations }
    procedure ExecuteTarget(Target: TObject); override;
  end;

procedure TInternalMDIAction.ExecuteTarget(Target: TObject);
begin
  case MDIAction of
    maActivate: SendMessage(GetParent(Form.Handle), WM_MDIACTIVATE, Form.Handle, 0);
    maClose: Form.Close;
    maRestore: SendMessage(GetParent(Form.Handle), WM_MDIRESTORE, Form.Handle, 0);
    maMinimize: ShowWindow(Form.Handle, SW_MINIMIZE);
  end;
end;

我无法捕获最小化事件,因为 ShowWindow 从未调用过 WMSysCommand。我在下面包含了我的修复:

type  
  TInternalMDIAction = class(TWindowAction)
  private
    { Private declarations }
  public
    { Public declarations }
    procedure ExecuteTarget(Target: TObject); override;
  end;

procedure TInternalMDIAction.ExecuteTarget(Target: TObject);
begin
  case MDIAction of
    maActivate: SendMessage(GetParent(Form.Handle), WM_MDIACTIVATE, Form.Handle, 0);
    maClose: Form.Close;
    //maRestore: SendMessage(GetParent(Form.Handle), WM_MDIRESTORE, Form.Handle, 0);
    //maMinimize: ShowWindow(Form.Handle, SW_MINIMIZE);
    maRestore: SendMessage(Form.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
    maMinimize: SendMessage(Form.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
  end;
end;

它现在的表现符合我的预期。如果有人看到我可能遗漏的内容或解决由 VCL TActionMainMenuBar 引起的问题的更好方法,请告诉我。谢谢