21.06.2016, Vladimír Klaus, navštíveno 2269x

Delphi

V Delphi při použití komponenty TApplicationEvents je možné obsloužit událost OnMinimize. Pokud si s tím budete hrát, asi to bude splňovat běžné potřeby, ale jen do té doby, než zjistíte, že je tato událost vyvolána až poté, co byla vykonána minimalizace. Co dělat, když potřebujete něco zařídit těsně před tím, než se minimalizace vykoná?

Po dlouhém hledání, trochu výzkumech a reálném vyzkoušení (Delphi XE 7, Windows 10) je tu něco, co mi opravdu funguje!

Nejprve přidejte do části public hlavního formuláře tuto proceduru:

public
  procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
end;

Její implementace pak bude vypadat takto:

procedure TMainForm.WMSysCommand(var Msg: TWMSysCommand);
begin
  if (Msg.CmdType = SC_MINIMIZE) then begin
    //tady můžete provést něco, co se má stát těsně před minimalizací...
    //...
  end;
  //no a pak vykonáte to, co se má, tedy třeba tu minimalizaci,
  //ale i maximalizaci nebo restore...
  DefaultHandler(Msg);
end;

Jak to reálně využít? Třeba tak, že si potřebujete zapamatovat stav okna před minimalizací - buď je okno normální nebo maximalizované. No a pak by bylo fajn po obnovení (restore) vrátit okno do stavu, který byl před minimalizací. Tedy něco, co funguje zcela normálně, pokud kliknete na ikonu v hlavním panelu. Když to ještě zkombinujete s minimalizací do oznamovací oblasti (a použití komponenty TTrayIcon), může to vypadat třeba takto:

procedure TMainForm.WMSysCommand(var Msg: TWMSysCommand);
begin
  //pokud jde o minimalizaci
  if (Msg.CmdType = SC_MINIMIZE) then begin
    if MainForm.WindowState=wsMaximized then begin
      //pokud před minimalizací je okno v maximalizovaném stavu,
      //poznamenám si to
      TrayIcon.Tag:=1;
    end else begin
      TrayIcon.Tag:=0;
    end;
    //pokud mám v nastavení zaškrtnuto, že chci minimalizovat
    //do oznamovací oblasti...
    if ChBMinimalizovatDoOznamovaciOblasti.Checked then begin
      MinimalizaceDoOznamovaciOblasti;
    end else begin
      //jinak provedu běžnou minimalizaci
      DefaultHandler(Msg);
    end;
  end else begin
    //a nebo provedu běžnou maximalizaci nebo obnovení
    DefaultHandler(Msg);
  end;
end;

Obnova z oznamovací oblasti bude vypadat nějak takto:

procedure TMainForm.ObnoveniZOznamovaciOblasti;
begin
  //zobrazím okno
  MainForm.Show;
  //a případně provedu maximalizaci
  if TrayIcon.Tag=1 then begin
    MainForm.WindowState:=wsMaximized;
  end;
  //aplikaci dám do popředí
  BringAppToFront(Application.Handle);
  //a schovám ikonku
  TrayIcon.Visible:=false;
end;

Je třeba ještě poznamenat, že pokud použijete tento způsob, tak nelze použít výše zmíněné TApplicationEvents, protože vše běží po jiné linii, kdy si vše řídíte sami.