Autor Téma: Zachycení požadavku na konec aplikace v cyklu s Application.HandleMessage;  (Přečteno 743 krát)

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 316
  • Karma: 0
Vážená komunito,

v Delphi 10 v Firemonkey aplikaci mám čekací kód, viz níže. Používám jej k tomu, abych zastavil jednu část kódu a umožnil obsluhu jiné části (tlačítek aj.). V případě, že je aplikace v tomto cyklu, nelze ji ukončit například pomocí alt+f4. Věděl by někdo, jak zachytit alt+f4 událost tak, abych mohl tento cyklus přerušit a aplikaci ukončit?

Kód: Delphi [Vybrat]
  1. procedure Wait(const ms: cardinal);
  2. var
  3.   Stop: cardinal;
  4.   Timer: cardinal;
  5. begin
  6.   Stop := GetTickCount + ms;
  7.   Timer := SetTimer(0, 0, ms, nil);
  8.   try
  9.     repeat
  10.       Application.HandleMessage;
  11.     until Application.Terminated or (Integer(GetTickCount - Stop) >= 0);  // pri preteceni 32-bit cardinal (49 dni) konci taky
  12.   finally
  13.     KillTimer(0, Timer);
  14.   end;
  15. end;
  16.  

Děkuji.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3006
  • Karma: 108
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Excellent
Rated 1 time
Jakmile je nekde takova obsluha, tak je to spatne.

Proc si radeji nespustis na tu svou operaci vlakno a hlavni (UI) vlakno nechej na pokoji. V tom pripade klidne v FormDestroy hlavniho formulare muzes pak zastavit svoje vlakno.

Nevim co chces delat, ale ja bezne ve FMX (ale i ve VCL) spoustim anonymni vlakno a to pak pripadne kdyz potrbuje zmeny promitnou do UI, tak pres thread synchronize nebo podobne. Tvuj pristup je spatne.
Embarcadero MVP - Czech republic

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 316
  • Karma: 0
Očekával jsem takovouto odpověď.

Nejsem si úplně tak jistý, zda lze řešit přes vlákno následující situace:

Mám frejm č.1 a na něm tlačítko, které po kliku vyvolá frejm č.2 na kterém bude výběr z několika dalších tlačítek (možností). Kód:

proc Tlačítko.OnClick;
begin
  Zobraz_Frejm_c2;
  while Zobraz_Frejm_c2.Visible do Wait(100);

  case Zobraz_Frejm_c2.Co_se_vybralo of
    ..
    ..
  end;
end;

To znamená, že v OnClick obsloužím rovnou i výsledek z Zobraz_Frejm_c2. Něco jako ShowModal.

 

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3006
  • Karma: 108
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
aha, ty myslis neco jako kdyz jsem popisoval https://delphi.cz/post/Delphi-trik-6-genericke-anonymni-metody.aspx

Tak presne tak se to resi, predas si kod, kde chces pokracovat a pri zavreni formulare ho pustis

Kód: Delphi [Vybrat]
  1.  
  2. TBasicEvent = TProc<TfrmBasic>;
  3.  
  4. procedure TfrmBasic.FormClose(Sender: TObject; var Action: TCloseAction);
  5. begin
  6.   if Assigned(FCloseProc) then
  7.   begin
  8.     FCloseProc(Self);
  9.     FCloseProc:= nil;
  10.     Action := TCloseAction.caFree;
  11.     Exit;
  12.   end;
  13. end;
  14.  
  15. procedure TfrmBasic.RunDialog(const pProc: TBasicEvent);
  16. begin
  17.   FCloseProc:= pProc;
  18.   {$IF DEFINED(Win64) or DEFINED(Win32)}
  19.   ShowModal;
  20.   {$ELSE}
  21.   Self.Show;
  22.   {$ENDIF}
  23. end;
  24.  
  25. // toto je jine volani
  26.  
  27. procedure TfrmListGPSSelectS.btnAddOM2Click(Sender: TObject);
  28. var
  29.   iEntity: Integer;
  30. begin
  31.   TfrmListSkladyOM.RunDialog(
  32.     procedure (oInstance: TfrmBasic)
  33.     begin
  34.       if oInstance.ModalResult in [mrOk, mrNo] then
  35.       begin
  36.         if oInstance.ModalResult = mrOk then
  37.         begin
  38.          //xxx
  39.         end
  40.       end;
  41.     end
  42.   );
  43.  
  44. end;
  45.  


Embarcadero MVP - Czech republic

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3006
  • Karma: 108
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
A abych te uklidnil, mam tak postavenou celkem velkou aplikaci pro Android, kde je ShowModal zakazano, protoze jinak te Android zabije, takze to funguje dost dobre.
Embarcadero MVP - Czech republic

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 316
  • Karma: 0
U Androida to taky řeším jinak. Váš příklad je ale něco jiného, než jsem myslel. Zkomplikoval jsem to frejmama. Níže je ten nejjednodušší kód se kterým se musel setkat snad každý:

Kód: Delphi [Vybrat]
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls, Buttons;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     Button1: TButton;
  12.     Volba1: TSpeedButton;
  13.     Volba2: TSpeedButton;
  14.     procedure Button1Click(Sender: TObject);
  15.   private
  16.     { Private declarations }
  17.   public
  18.     { Public declarations }
  19.   end;
  20.  
  21. var
  22.   Form1: TForm1;
  23.  
  24. implementation
  25.  
  26. {$R *.dfm}
  27.  
  28. procedure TForm1.Button1Click(Sender: TObject);
  29. begin
  30.   // zobrazíme dvě tlačítka na výběr
  31.   Volba1.Down    := false;
  32.   Volba2.Down    := false;
  33.   Volba1.Visible := true;
  34.   Volba2.Visible := true;
  35.  
  36.   // čekáme co si uživatel vybere
  37.   while not Volba1.Down and not Volba2.Down do Application.HandleMessage;
  38.  
  39.   // výsledek
  40.   if Volba1.Down then showmessage('1')
  41.   else if Volba2.Down then showmessage('2');
  42.  
  43.   // skryjeme možnosti
  44.   Volba1.Visible := false;
  45.   Volba2.Visible := false;
  46. end;
  47.  
  48. end.
  49.  

V rámci klik procedury čekám na uživatele, co si vybere za tlačítko. Toto snad asi nelze řešit jinak než pomocí Application.HandleMessage.
Ano, lze si udělat nějaký Timer a přes nějaké řídicí proměnné toto obsloužit, ale ztrácí to jednoduchost a přehlednost.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3006
  • Karma: 108
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Takto bych to nikdy nenaprogramoval, a kdyz je pouzito Application.HandleMessage tak je to evidentne riskantni kod. a pokud toto povazujes ze prehledne a vzhledem k tomu jake mas problemy viz. prvni prispevek, tak mam pravdu.

Osobne bych v tomto konkretni pripade mel spolecnou obsluhu tech tlacitek na Click.
Embarcadero MVP - Czech republic

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 316
  • Karma: 0
Riskantní části si lze ohlídat. Z mého pohledu jsou vlákna riskantnější.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3006
  • Karma: 108
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Riskantní části si lze ohlídat. Z mého pohledu jsou vlákna riskantnější.

Tak to jsem rad, takze chapes ze to Application.HandleMessage nejak reaguje na to ALT+F4 a ty ze na to musis reagovat na kazdem miste kde mas takovou konstrukci,
tj. nejmene asi testovat Application.Terminated
Embarcadero MVP - Czech republic

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3343
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Níže je ten nejjednodušší kód se kterým se musel setkat snad každý:
Jj, setkal, ale nekdy pred 30+ lety, kdyz se programovalo pod DOSem tj. bez operacniho systemu a clovek si se zelezem mohl delat, co chtel. Ale ne v event driven prostredi -> tam plati, co pise Radek.


Offline Marek Weyda

  • Hrdina
  • ****
  • Příspěvků: 258
  • Karma: 8
    • Verze Delphi: Delphi 2007, 10.1 Berlin
Přidám také svojí trošku do mlýna - největší chyby před lety ve velkém projektu, který jsem dával dohromady po bývalých programátorech, tak byly vždy v souvislosti s použitím Application.ProcessMessages, Application.HandleMessage. Do toho doporučuji se moc nepouštět, když si na to vzpomenu zpětně, tak je docela zajímavé, co všechno to způsobovalo.