Speaker
Speaker

Reputation: 301

Minimize the whole application when a child modal form is minimized

In another question near this, i get the answer to get modal forms to keep inside a workarea inside the mainform. The way i can accomplish that (thanks to David again) is catching WMSizing, WMMoving, WMGetMaxMinInfo, and for my porpuose WMShowwindow messages. I am not closed to messages handling and i think it is likely the way i manage messages the cause that i am not getting the result i needed.

All the forms in my application are modal. But you can open a lot in the same execution thread. (Mainform, form1, form2, form3... formN). All form(1..N) move inside a workarea in my mainform. Maximize, restore, size, move... all between limits of that workarea.

But i cannot manage how to minimize the whole application from then click on active modal form minimize button, and from click on taskbar button. The application will be used in XP and W7... i am developing in DelphiXE.

The project can be downloaded from here (Project files - Mainform, panel, button, SecondaryForm, unit, nothing more), just to see that i try all the suggestions i found before asking here.

This is the source code of the original unit that keeps the modal forms inside the workarea.

unit uFormularios;

interface

uses Classes, SysUtils, Windows, Messages, Forms, DBGrids, StdCtrls, Menus, Graphics, ComCtrls, Math;

type
  TForm_en_ventana = class(TForm)
  private
    inicializada: boolean;
    bCentrada     : boolean;
    bMaximizada   : boolean;
    ancho_original: integer;
    alto_original : integer;
    procedure WMShowWindow(var Message: TWMShowWindow); message WM_SHOWWINDOW;
    procedure WMSizing(var msg: TMessage); message WM_SIZING;
    procedure WMMoving(Var msg: TMessage); message WM_MOVING;
    procedure WMGetMinMaxInfo(Var msg: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
  public
    constructor Create(AOwner: TComponent); override;
    property centrada: boolean read bCentrada write bCentrada;
    property maximizada: boolean read bMaximizada write bMaximizada;
  end;

procedure MaximizarFormulario(var F; MaximaAltura: integer = 0; MaximoAncho: integer = 0; Centrado: boolean = TRUE);
procedure InicializarVentanaTrabajo(const izq, der, arr, aba: integer);

var
  ESPACIO_DE_TRABAJO, VENTANA_DE_TRABAJO: TRect;

implementation

constructor TForm_en_ventana.Create(AOwner: TComponent);
begin
  inherited;
  centrada     := TRUE;
  maximizada   := false;
  inicializada := false;
end;

Procedure TForm_en_ventana.WMGetMinMaxInfo(Var msg: TWMGetMinMaxInfo);
begin
  inherited;
  with msg.MinMaxInfo^.ptMaxPosition do
    begin
      x := VENTANA_DE_TRABAJO.Left;
      y := VENTANA_DE_TRABAJO.Top;
    end;
  with msg.MinMaxInfo^.ptMaxSize do
    begin
      x := VENTANA_DE_TRABAJO.Right - VENTANA_DE_TRABAJO.Left;
      y := VENTANA_DE_TRABAJO.Bottom - VENTANA_DE_TRABAJO.Top;
    end;
  with msg.MinMaxInfo^.ptMaxTrackSize do
    begin
      x := VENTANA_DE_TRABAJO.Right - VENTANA_DE_TRABAJO.Left;
      y := VENTANA_DE_TRABAJO.Bottom - VENTANA_DE_TRABAJO.Top;
    end;
  with msg.MinMaxInfo^.ptMinTrackSize do
    begin
      x := ancho_original;
      y := alto_original;
    end;
end;

procedure TForm_en_ventana.WMSizing(var msg: TMessage);
var
  R: PRect;
begin
  R        := PRect(msg.LParam);
  R.Left   := Max(R.Left, VENTANA_DE_TRABAJO.Left);
  R.Right  := Min(R.Right, VENTANA_DE_TRABAJO.Right);
  R.Top    := Max(R.Top, VENTANA_DE_TRABAJO.Top);
  R.Bottom := Min(R.Bottom, VENTANA_DE_TRABAJO.Bottom);
  Caption  := 'Ancho: ' + inttostr(ancho_original) + ' - Alto: ' + inttostr(alto_original);
end;

procedure TForm_en_ventana.WMMoving(var msg: TMessage);
var
  R     : PRect;
  dx, dy: integer;
begin
  R  := PRect(msg.LParam);
  dx := 0;
  dy := 0;
  if R.Left < VENTANA_DE_TRABAJO.Left then
    dx := VENTANA_DE_TRABAJO.Left - R.Left;
  if R.Right > VENTANA_DE_TRABAJO.Right then
    dx := VENTANA_DE_TRABAJO.Right - R.Right;
  if R.Top < VENTANA_DE_TRABAJO.Top then
    dy := VENTANA_DE_TRABAJO.Top - R.Top;
  if R.Bottom > VENTANA_DE_TRABAJO.Bottom then
    dy := VENTANA_DE_TRABAJO.Bottom - R.Bottom;
  OffsetRect(R^, dx, dy);
end;

procedure TForm_en_ventana.WMShowWindow(var Message: TWMShowWindow);
begin
  if inicializada then
    Exit;
  inicializada          := TRUE;
  ancho_original        := Width;
  alto_original         := Height;
  Constraints.MinHeight := Height;
  Constraints.MinWidth  := Width;
  if centrada then
    begin
      Left := (((VENTANA_DE_TRABAJO.Right - VENTANA_DE_TRABAJO.Left) - Width) div 2) + VENTANA_DE_TRABAJO.Left;
      Top  := (((VENTANA_DE_TRABAJO.Bottom - VENTANA_DE_TRABAJO.Top) - Height) div 2) + VENTANA_DE_TRABAJO.Top;
    end;
  if maximizada then
    SendMessage(Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
end;

procedure InicializarVentanaTrabajo(const izq, der, arr, aba: integer);
begin
  VENTANA_DE_TRABAJO.Left   := izq;
  VENTANA_DE_TRABAJO.Right  := der;
  VENTANA_DE_TRABAJO.Top    := arr;
  VENTANA_DE_TRABAJO.Bottom := aba;
end;

procedure MaximizarFormulario(var F; MaximaAltura: integer = 0; MaximoAncho: integer = 0; Centrado: boolean = TRUE);
begin
  LockWindowUpdate(TForm(F).Handle);
  TForm(F).Left := ESPACIO_DE_TRABAJO.Left;
  if MaximoAncho = 0 then
    TForm(F).Width := ESPACIO_DE_TRABAJO.Right
  else
    begin
      if ESPACIO_DE_TRABAJO.Right < MaximoAncho then
        TForm(F).Width := ESPACIO_DE_TRABAJO.Right
      else
        TForm(F).Width := MaximoAncho;
    end;
  TForm(F).Top := ESPACIO_DE_TRABAJO.Top;
  if MaximaAltura = 0 then
    TForm(F).Height := ESPACIO_DE_TRABAJO.Bottom
  else
    begin
      if ESPACIO_DE_TRABAJO.Bottom < MaximaAltura then
        TForm(F).Height := ESPACIO_DE_TRABAJO.Bottom
      else
        TForm(F).Height := MaximaAltura;
    end;
  if ((MaximoAncho <> 0) or (MaximaAltura <> 0)) and (Centrado) then
    begin
      TForm(F).Left := (ESPACIO_DE_TRABAJO.Right - TForm(F).Width) div 2;
      TForm(F).Top  := (ESPACIO_DE_TRABAJO.Bottom - TForm(F).Height) div 2;
    end;
  LockWindowUpdate(0);
end;

initialization

SystemParametersInfo(SPI_GETWORKAREA, 0, @ESPACIO_DE_TRABAJO, 0);
VENTANA_DE_TRABAJO := ESPACIO_DE_TRABAJO;

end.

Thanks to anybody who can help me!

Upvotes: 4

Views: 2456

Answers (3)

Kevin Berry
Kevin Berry

Reputation: 161

Thank you, JFGravel! This worked great for me, but I could never get the SC_RESTORE to get caught here, but restore works fine without, so here's my short version:

  if (Message.CmdType and $FFF0) = SC_MINIMIZE then
    ShowWindow(Application.Handle, SW_SHOWMINNOACTIVE)
  else
    inherited;

Upvotes: 1

Marus Gradinaru
Marus Gradinaru

Reputation: 3022

I needed this too, and I tried the other answer but it's not working. Fortunately I managed to make it work, like this:

procedure TFoodsForm.WMSysCommand(var Msg: TWMSysCommand);
begin
 if (fsModal in FormState) and (Msg.CmdType and $FFF0 = SC_MINIMIZE)
  then Application.MainForm.WindowState:= wsMinimized
  else inherited;
end;

Upvotes: 2

JFGravel
JFGravel

Reputation: 21

Simply catch the Minimize and Restore messages in the Modal Form and do this ...

procedure TTheModalForm.WMSysCommand(var Msg: TWMSysCommand);
begin
  if (fsModal in FormState) or not Application.MainForm.Visible then
  begin
    case Msg.CmdType of
      SC_MINIMIZE:
      begin
        ShowWindow(Application.Handle, SW_SHOWMINNOACTIVE);
      end;

      SC_RESTORE:
      begin
        ShowWindow(Application.Handle, SW_SHOWNORMAL);
        inherited;
      end;

    else
      inherited;
    end;
  end
  else
    inherited;
end;

Upvotes: 2

Related Questions