【问题标题】:Catch Delphi MDI Child minimize event when the MDI Child form is maximized当 MDI Child 窗体最大化时捕获 Delphi MDI Child 最小化事件
【发布时间】:2017-05-10 22:23:39
【问题描述】:

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

单击下图中红色圈出的按钮时,当表单未最大化时,我能够捕获最小化/恢复/最大化事件。

我使用 WMSysCommand 捕获上述事件:

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

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

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

【问题讨论】:

    标签: delphi mdi minimize mdichild wm-syscommand


    【解决方案1】:

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

    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 有机会处理它。

    【讨论】:

    • 我在实际应用中的代码中有inherited;,只是忘了把它和我的原始帖子放在一起。我将您的帖子标记为答案,因为它应该抓住事件。我创建了一个示例应用程序,即使 MDI 子节点最大化,WMSysCommand 也会捕获事件。这让我相信我的应用程序中一定存在阻止这种行为的现有代码。我们正在拦截其他一些 Windows 消息。不确定这是否是导致此错误的代码。我将继续调查并相应地更新这篇文章。感谢您的帮助。
    【解决方案2】:

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

    我正在使用 TActionMainMenuBar 代替父 MDI 表单上的 TMainMenu。 TActionMainMenuBar 处理最小化/恢复/最大化按钮点击的方式与 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 引起的问题的更好方法,请告诉我。谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多