Autor Téma: FMX komponenta - detekce kliku mimo  (Přečteno 5128 krát)

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 360
  • Karma: 0
FMX komponenta - detekce kliku mimo
« kdy: 04-01-2022, 09:10:04 »
Dobrý den,

pro Firemonkey mám komponentu třídy TLayout. Na této komponentě mám zobrazení textu, možnost kliku, rozbalení dalšího obsahu a tak. Potřeboval bych ale zachytit klik mimo tuto komponentu a její obsah zase sbalit. Něco jako je roletka u TComboBox, kde mi ale princip není moc jasný. Na internetu nic funkčního není, resp. ne, když to chci řešit interně v komponentě.

Nenapadá někoho jakým způsobem se to dá řešit?

Děkuji.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3531
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:FMX komponenta - detekce kliku mimo
« Odpověď #1 kdy: 04-01-2022, 13:18:43 »
S FXM jsem nic podstatneho nedelal, ale rekl bych, ze to musi byt podobne, jako u VCL: TControl implementuje IControl, ktery obsahuje mechanismus Enter/Exit resp. Activate/DeActivate. Takze si ty metody prekryt a udelat si, co potrebujes.

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 360
  • Karma: 0
Re:FMX komponenta - detekce kliku mimo
« Odpověď #2 kdy: 04-01-2022, 15:35:34 »
Dobrý den,

četl jsem něco o OnExit (DoExit). Po vytvoření procedury DoExit a jejím override je ale volána jen když deaktivuji celý Form (nebo jej ukončuji). Zítra se podívám na OnDeactivate a dám vědět.

Děkuji.
 

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3531
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:FMX komponenta - detekce kliku mimo
« Odpověď #3 kdy: 04-01-2022, 22:34:39 »
četl jsem něco o OnExit (DoExit). Po vytvoření procedury DoExit a jejím override je ale volána jen když deaktivuji celý Form (nebo jej ukončuji). Zítra se podívám na OnDeactivate a dám vědět.
To je zrejme tim, ze ten TLayout neni focusable (to by musel byt potomek TWinControls = mit handle okna - to se takove eventy volaji pri ztrate focusu), takze docilit toho, aby se to chovalo jako dropdown list u comboboxu nemusi byt jednoduse, pokud vubec, resitelne.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3544
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:FMX komponenta - detekce kliku mimo
« Odpověď #4 kdy: 04-01-2022, 23:59:52 »
To je zrejme tim, ze ten TLayout neni focusable (to by musel byt potomek TWinControls = mit handle okna - to se takove eventy volaji pri ztrate focusu), takze docilit toho, aby se to chovalo jako dropdown list u comboboxu nemusi byt jednoduse, pokud vubec, resitelne.

Tohle není pravda. FMX si az na vyjimky na handle okna nehraje a vubec je nepotrebuje. I ten ComboBox je seskladan z primitiv a neni to nativni prvek. U nekterych controlu se da zapnout platformova verze (typicky TEdit, datumove vstupy) pres Property ControlType.

Ale zpet. Pokud to dobre chapu, tak zkus tohle:

Misto Layout pouzij TPanel. Na formulari mam dva TPanel, a v kazdem je TRectangle at neco vidime.

fmx soubor:
Kód: Delphi [Vybrat]
  1. object Form2: TForm2
  2.   Left = 0
  3.   Top = 0
  4.   Caption = 'Form2'
  5.   ClientHeight = 480
  6.   ClientWidth = 640
  7.   FormFactor.Width = 320
  8.   FormFactor.Height = 480
  9.   FormFactor.Devices = [Desktop]
  10.   OnCreate = FormCreate
  11.   DesignerMasterStyle = 0
  12.   object Panel1: TPanel
  13.     Position.X = 256.000000000000000000
  14.     Position.Y = 32.000000000000000000
  15.     TabOrder = 0
  16.     OnEnter = Panel1Enter
  17.     OnExit = Panel1Exit
  18.     object Rectangle1: TRectangle
  19.       Align = Client
  20.       HitTest = False
  21.       Size.Width = 120.000000000000000000
  22.       Size.Height = 120.000000000000000000
  23.       Size.PlatformDefault = False
  24.     end
  25.   end
  26.   object Panel2: TPanel
  27.     Position.X = 400.000000000000000000
  28.     Position.Y = 32.000000000000000000
  29.     TabOrder = 1
  30.     object Rectangle2: TRectangle
  31.       Align = Client
  32.       HitTest = False
  33.       Size.Width = 120.000000000000000000
  34.       Size.Height = 120.000000000000000000
  35.       Size.PlatformDefault = False
  36.     end
  37.   end
  38. end
  39.  

Kód: Delphi [Vybrat]
  1. unit Unit2;
  2.  
  3. interface
  4.  
  5. uses
  6.   System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  7.   FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.ListBox,
  8.   FMX.StdCtrls, FMX.Controls.Presentation, FMX.Objects;
  9.  
  10. type
  11.   TForm2 = class(TForm)
  12.     Panel1: TPanel;
  13.     Panel2: TPanel;
  14.     Rectangle1: TRectangle;
  15.     Rectangle2: TRectangle;
  16.     procedure Panel1Exit(Sender: TObject);
  17.     procedure FormCreate(Sender: TObject);
  18.     procedure Panel1Enter(Sender: TObject);
  19.   private
  20.     { Private declarations }
  21.   public
  22.     { Public declarations }
  23.   end;
  24.  
  25. var
  26.   Form2: TForm2;
  27.  
  28. implementation
  29.  
  30. {$R *.fmx}
  31.  
  32. procedure TForm2.FormCreate(Sender: TObject);
  33. begin
  34.    Panel1.CanFocus := True;
  35.    Panel1.HitTest := True;
  36.    Panel2.CanFocus := True;
  37.    Panel2.HitTest := True;
  38.    Rectangle1.HitTest := False; // vypneme hittest u vnitrni komponenty, takze probubla do panelu
  39.    Rectangle2.HitTest := False; // to same
  40. end;
  41.  
  42. procedure TForm2.Panel1Enter(Sender: TObject);
  43. begin
  44.   Rectangle1.Stroke.Color := TAlphaColorRec.Red;
  45. end;
  46.  
  47. procedure TForm2.Panel1Exit(Sender: TObject);
  48. begin
  49.   Rectangle1.Stroke.Color := TAlphaColorRec.Grey;
  50. end;
  51.  
  52.  



Embarcadero MVP - Czech republic

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 360
  • Karma: 0
Re:FMX komponenta - detekce kliku mimo
« Odpověď #5 kdy: 05-01-2022, 07:36:52 »
Děkuji za kód, ale není to tak dobře. OnExit přijde jen když kliknu na panel2. Potřebuji ale zachytit klik kdekoliv. Prostě musí v FMX existovat "něco", co dokáže zachytit událost kliku myši ať už je kdekoliv na formuláři. Je přeci nesmyslné reagovat na klik jen když je myš v "designboxu" (nebo jak to nazvat) objektu a navíc jen s HitTest := true. Neumím si představit složitější aplikaci bez takovéto interakce. A to platí nejen pro klik, ale i pro pohyb myši, klávesy atp.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3531
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:FMX komponenta - detekce kliku mimo
« Odpověď #6 kdy: 05-01-2022, 08:56:13 »
Tohle není pravda. FMX si az na vyjimky na handle okna nehraje a vubec je nepotrebuje.
OK. Psal jsem, ze s FMX jsem delal jen na urovni kladece komponent a ne programatora.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3544
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:FMX komponenta - detekce kliku mimo
« Odpověď #7 kdy: 05-01-2022, 09:19:53 »
Děkuji za kód, ale není to tak dobře. OnExit přijde jen když kliknu na panel2. Potřebuji ale zachytit klik kdekoliv. Prostě musí v FMX existovat "něco", co dokáže zachytit událost kliku myši ať už je kdekoliv na formuláři. Je přeci nesmyslné reagovat na klik jen když je myš v "designboxu" (nebo jak to nazvat) objektu a navíc jen s HitTest := true. Neumím si představit složitější aplikaci bez takovéto interakce. A to platí nejen pro klik, ale i pro pohyb myši, klávesy atp.

Tak chces zachytavat mys nebo zmenu focusu? Jestli sis nevsiml, tak ten muj kod reaguje na zmenu focusu, tedy i stisk TAB.
Embarcadero MVP - Czech republic

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3544
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:FMX komponenta - detekce kliku mimo
« Odpověď #8 kdy: 05-01-2022, 09:21:24 »
Tohle není pravda. FMX si az na vyjimky na handle okna nehraje a vubec je nepotrebuje.
OK. Psal jsem, ze s FMX jsem delal jen na urovni kladece komponent a ne programatora.


V pohode, ja to musel napsat, nez tim bude nekdo argumentovat.
Embarcadero MVP - Czech republic

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3544
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:FMX komponenta - detekce kliku mimo
« Odpověď #9 kdy: 05-01-2022, 10:01:41 »
Děkuji za kód, ale není to tak dobře. OnExit přijde jen když kliknu na panel2. Potřebuji ale zachytit klik kdekoliv. Prostě musí v FMX existovat "něco", co dokáže zachytit událost kliku myši ať už je kdekoliv na formuláři. Je přeci nesmyslné reagovat na klik jen když je myš v "designboxu" (nebo jak to nazvat) objektu a navíc jen s HitTest := true. Neumím si představit složitější aplikaci bez takovéto interakce. A to platí nejen pro klik, ale i pro pohyb myši, klávesy atp.

Tak chces zachytavat mys nebo zmenu focusu? Jestli sis nevsiml, tak ten muj kod reaguje na zmenu focusu, tedy i stisk TAB.

Jako rychlý hack jde dat panel (misto Layout) pres cely form a nastavit mu CanFocus := True  a na nej davat jine komponenty. Tim padem kamkoliv kliknes mimo focusable komponent bude mit Focus ten hlavni panel.

Pokud ti to nestaci, tak se podivej jak je delany ten ComboBox, ale nevim, zda je to presne v tvem pripade pouzitelne.
Embarcadero MVP - Czech republic

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 360
  • Karma: 0
Re:FMX komponenta - detekce kliku mimo
« Odpověď #10 kdy: 05-01-2022, 10:34:26 »
Rád bych to řešil v rámci komponenty. Ať už ji dám na formulář nebo panel či layout. Po těch letech už mě FMX moc nepřekvapuje - neustálé obcházení základních funkcí, stovky chyb a nedodělaných komponent :(

ComboBox je řešený přes TPopup, což je custom form, které se globálně obsluhují v FMX.Platform.Win.WndProc (pokud se dobře pamatuji). Nechápu, proč zde není vyvedená cestička dál a třeba všem objektům s AutoCapture není předána. Bylo by to elegantní a funkční. Nezbývá, než si to zprogramovat a zase držet další pas soubory v projektu.

Přes TPopup to zkouším teď, ale nenašel jsem způsob, jak se dostat ještě před ClosePopup proceduru, která je zavolána již pozdě (po zrušení některých ukazatelů). Kdyby existovalo nějaké CanClosePopup jako je CloseQuery.
« Poslední změna: 05-01-2022, 10:46:20 od age.new »

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 360
  • Karma: 0
Re:FMX komponenta - detekce kliku mimo
« Odpověď #11 kdy: 05-01-2022, 12:06:15 »
Tak se mi podařilo docílit požadovaného efektu pomocí TPopup, ale narazil jsem na další nesmyslnou chybu. Objekt umístěný v TPopup ztrácí HitTest vlastnost, resp. MouseDown událost se zaznamená jen na neprůhledných pixelech objektu. Takže pokud máte část průhlednou, tak klik v tomto místě skryje TPopup objekt i když byl klik uvnitř. To se děje u TLayout i TRectangle. Nastavený HitTest jak u TPopup, tak ani u jiných objektů nepomůže.... asi se zde objevuje vlastnost u formulářů, které když jsou průhledné, tak HitTest nezabere i když je nastavený. Takto je to ale nedomyšlené.
« Poslední změna: 05-01-2022, 12:10:40 od age.new »

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3544
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:FMX komponenta - detekce kliku mimo
« Odpověď #12 kdy: 05-01-2022, 12:16:11 »
Tak se mi podařilo docílit požadovaného efektu pomocí TPopup, ale narazil jsem na další nesmyslnou chybu. Objekt umístěný v TPopup ztrácí HitTest vlastnost, resp. MouseDown událost se zaznamená jen na neprůhledných pixelech objektu. Takže pokud máte část průhlednou, tak klik v tomto místě skryje TPopup objekt i když byl klik uvnitř. To se děje u TLayout i TRectangle. Nastavený HitTest jak u TPopup, tak ani u jiných objektů nepomůže.... kdybych dostal korunu za každou chybu, tak již mám postavený dům.

Jen pro zajimavost: jak by jsi toho docilil u VCL? Podle mne by ses nedostal vubec nikam - to jen takova poznamka. Myslim si, ze to pres TPopup neni dobre reseni.
Podle mne jdes spatnou cestou. Porad nechapu proc se ti nelibi reseni pres ztratu fokusu, tj. dokud neco nema jiny fokus tak se nic nastane.
Embarcadero MVP - Czech republic

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3531
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:FMX komponenta - detekce kliku mimo
« Odpověď #13 kdy: 05-01-2022, 12:28:46 »
Podle mne jdes spatnou cestou. Porad nechapu proc se ti nelibi reseni pres ztratu fokusu, tj. dokud neco nema jiny fokus tak se nic nastane.
No protoze bys musel zajistit, ze vsechny widgety okolo jsou nebo lezi na focusable widgetu, aby ke ztrate fokusu doslo, takze porusujes zapouzdrenost komponenty. Ale je pravda, ze neco takove bys horko tezko dociloval i u VCL - tam by ses musel nejspis centralne povesit na nejake zpravy jako WM_ACTIVATE, WM_KILLFOCUS a neco kolem mysi a porozhlednout se, komu presne patri.

Treba v browserech a JavaScriptu se to resi obsluhou udalosti onClick, kterou tam ma ale kazdy element a udalosti lze obsluhovat hromadne pres JQUERY a mam dojem, ze pres OnClick, na ktery muze byt poveseno vic posluchacu, se to delava i v dotNetu.

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 360
  • Karma: 0
Re:FMX komponenta - detekce kliku mimo
« Odpověď #14 kdy: 05-01-2022, 12:35:39 »
Přes fokus to není dobrá cesta. Některé objekty fokus nemají a pak by to nefungovalo. TComboBox to má řešené přes TPopup. Udělám to stejně, sic s omezením grafických prvků na max 99% průhlednost.

Domnívám se, že u VCL se nabízí řešení více. Globální hook, zachytávání message událostí ...