0
votes

I am in need of some help trying to capture the minimize event of an MDI Child form when it is maximized.

I am able to capture the minimize/restore/maximize events when the form is not maximized when clicking the buttons circled in red in the image below.

MDI Child

I capture the aforementioned events by using WMSysCommand:

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

When I try to capture the same events using WMSysCommand when the MDI Child form is maximized and clicking the buttons circled in red in the image below, it will not call this code.

Maximized MDI Child

No matter what I have tried I have been unsuccessful in catching these events. If someone could point me in the right direction it would be greatly appreciated. Thank you.

2

2 Answers

1
votes

Works fine for me when I try it:

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() does capture the SC_MINIMIZE notification whenever the MDI child is minimized, regardless of whether it was previously maximized or not, as expected.

Make sure TMDIChildForm.WMSysCommand() calls inherited (as shown above) to pass the WM_SYSCOMMAND message to the default handler so Windows has a chance to process it.

0
votes

After doing some further digging I've come across the problem. @Remy please see below.

I am using TActionMainMenuBar in place of a TMainMenu on the parent MDI form. The TActionMainMenuBar handles the minimize/restore/maximize button clicks differently than that of TMainMenu. The code below is from the Vcl.ActnMenus file:

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;

I am unable to catch the minimize event because WMSysCommand is never called by ShowWindow. I have included my fix below:

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;

It is now performing as I would expect it to. If anyone sees something I might have missed or a better way of fixing the problem caused by VCL TActionMainMenuBar please let me know. Thanks.