Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Ermitteln woher ein Control den Fokus erhalten hat (https://www.delphipraxis.net/150899-ermitteln-woher-ein-control-den-fokus-erhalten-hat.html)

H4ndy 29. Apr 2010 20:23


Ermitteln woher ein Control den Fokus erhalten hat
 
Hallo,

Ich habe im Moment eine ziemliche Kopfnuss zu knacken, welche mit einer Art Popup-Fenster zusammenhaengt.
Das Popup soll sich immer schliessen, sobald es den Fokus verliert - soweit kein Problem.

Ich habe eine Statusbar, drueckt man diese, dann geht das Popup auf. Druecke ich diese erneut, schliesst sich das Popup und geht wieder auf. Nicht verwunderlich, aber genau das will ich verhindern. Wenn man auf die Statusbar klickt, waehrend man sozusagen noch im Popup ist, bzw. dieses liest, dann soll es bei diesem Klick einfach zu gehen.

Hier ist jetzt aber das Problem - das OnDeactivate und OnClose the Popups kommt immer vorm OnClick der Statusbar.
Die einzige Loesung, die mir im Moment einfaellt, ist, irgendwie herauszufinden, welches Fenster zuletzt den Fokus hatte, allerdings hab ich keine Ahnung, wie ich das anstellen kann.

Und genau das ist meine Frage: Jemand Ahnung ob, und wenn ja, wie man das ermitteln kann?
Ich glaub jedenfalls das es geht, da z.B. KeePass (www.keepass.info) beim Auto-Ausfuellen das letzte Fenster wieder in den Vordergrund holt und dort dann Logindaten eintraegt.

Wenn ich diese Info habe, kann ich einfach die erneute Anzeige unterbinden...

PS:
Nicht ueber die nicht vorhandenen Umlaute wundern,
aber ich sitze gerade in den USA an einem Notebook mit US-Tastatur ;)

David Martens 29. Apr 2010 20:47

Re: Ermitteln woher ein Control den Fokus erhalten hat
 
Also ich würde das mit zwei boolean Variablen machen. z.B.: bPopupShows, bStatusbarPressed

- initial beide false
- beim Click auf die Stausbar: bStatusbarPressed := true wenn bPopupShows = false und bStatusbarPressed = false sonst bStatusbarPressed := false
- beim Click auf die Stausbar: bPopupShows := false wenn bPopupShows = true
- beim OnShow des Popup: bPopupShows := true

Ich hoffe ich hab jetzt nichts durcheinander gebracht.

Eigentlich musst du dir nur über die Events hinaus merken was gedrückt wurde und was angezeigt worden ist. Das geht am einfachsten mit eigenen Variablen im Objekt.

Gruß David

H4ndy 29. Apr 2010 21:06

Re: Ermitteln woher ein Control den Fokus erhalten hat
 
Hallo,

Die Idee ist gut, aber beruecksichtig nicht, dass das Popup jederzeit "von jedem Conrol" geschlossen werden kann.
Mit deiner Loesung muesste ich zweimal auf die Statusbar klicken, um das Popup wieder anzuzeigen, auch wenn das Popup z.B. durch einen Klick ins Formular geschlossen wurde.

Zitat:

Zitat von David Martens
Eigentlich musst du dir nur über die Events hinaus merken was gedrückt wurde und was angezeigt worden ist. Das geht am einfachsten mit eigenen Variablen im Objekt.

Richtig, aber ich brauche zusaetzlich noch die Info, ob das Popup jetzt geschlossen wurde, weil ich nochmal auf die Statusbar geklickt habe oder einfach irgendwo ins Formular.

Ich hoffe ich hab jetzt nix verdreht im Kopf :shock:

Tryer 29. Apr 2010 22:49

Re: Ermitteln woher ein Control den Fokus erhalten hat
 
Das Problem ist auseinanderzuhalten ob Popup.Deactivate und StatusBar.Click "direkt" aufeinander folgen, ansonsten wäre es ja legitim das dein Popupfenster erst verschwindet um dann beim Click wieder zu erscheinen.

Delphi-Quellcode:
type
  TMainForm = class(TForm)
  ..
  private
    ShowPopupOnClick: Boolean;
  ..
...
   
procedure TMainForm.StatusBarMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  //Würde sehr kurz nach Popup.Deactivate aufgerufen
  //wenn die Zeitspanne größer ist wird das Popup angezeigt
  ShowPopupOnClick := Abs(GetTickCount - Popup.TimeStampHide) > 20;
end;

procedure TMainForm.StatusbarClick(Sender: TObject);
begin
  if ShowPopupOnClick then
    Popup.Show;
end;

//##############################################################

type
  TPopup = class(TForm)
  ..
  public
    TimeStampHide: Integer;
  ..

procedure TPopup.FormDeactivate(Sender: TObject);
begin
  TimeStampHide := GetTickCount;
  Hide;
end;
Grüsse, Dirk

alzaimar 30. Apr 2010 07:12

Re: Ermitteln woher ein Control den Fokus erhalten hat
 
Verpasse jedem Control ein OnEnter-Ereignis, bei dem Du dir den Sender in einem privaten Feld merkst. Das ist nämlich das Control, das den Focus gerade erhalten hat.

Im OnClick prüfst Du einfach, wer den Focus zuletzt hatte und reagierst dann entsprechend:

Delphi-Quellcode:
Type
  TPublicEventsWinControl = Class (TWinControl)
    Public
    property OnEnter;
    Property OnClick;
  End;

procedure TForm1.FormCreate(Sender: TObject);
Var
  i : integer;

Begin
  For i:=0 to ComponentCount - 1 do
    If Components[i] is TWinControl Then Begin
// Problem: Haben die Controls schon ein OnEnter / OnClick, wird das hier überschrieben.
      TPublicEventsWinControl(Components[i]).OnEnter := RememberFocus;
      TPublicEventsWinControl(Components[i]).OnClick := AllControlsOnClick;
    End;
End;

Procedure TForm11.AllControlsOnClick (Sender : TObject);
Begin
  If fLastControl = MyStatusbar Then
    ThePopup.visible := Not ThePopup.Visible
  else
    ThePopup.Visible := False;
End;

Procedure TForm1.RememberFocus (Sender : TObject);
Begin
  fLastControl := Sender as TWinControl;
End;

Tryer 30. Apr 2010 08:08

Re: Ermitteln woher ein Control den Fokus erhalten hat
 
OnClick von allen Controls zu überschreiben würde ich durchaus als Problem sehen..
Das On/Enter/OnClick der Form müsste auch noch überschrieben werden.
Mangels Delphi kann ich gerade nur raten das dann beim Focuswechsel erst Form.OnEnter und danach Statusbar.OnEnter ausgelöst wird - dann hätte man dann wieder die "Doppeltriggerung".

Vielleicht eher in der Art "Form.OnActivate: Wenn Maus über Statusbar und Maustaste gedrückt dann Veränderung bei OnClick bis zum nächsten MouseDown sperren (Hide passiert über Popup.Deactivate)"
Mir gefällt die GetTickCount - Lösung auch nicht wirklich ;)

Grüsse, Dirk

idefix2 30. Apr 2010 08:21

Re: Ermitteln woher ein Control den Fokus erhalten hat
 
Zitat:

// Problem: Haben die Controls schon ein OnEnter / OnClick, wird das hier überschrieben.
Das Problem lässt sich durch den Einsatz einer ClassHelper Klasse für TWinControl vermeiden. Dort kann das Original-Onenter und onclick Ereignis überschrieben, aber der Einstiegspunkt, falls er existiert, gemerkt und in dem überschriebenen Ereignis anschliessend aufgerufen werden.

H4ndy 30. Apr 2010 14:25

Re: Ermitteln woher ein Control den Fokus erhalten hat
 
Danke!

Ich hab es jetzt ueber den "Timer" im OnClose ueber eine Klassenvariable geloest, das erschien mir der Situation am angemessensten.
Das Formular mit der Statusbar ist schon ziemlich "Resourcenintensiv", von daher finde ich das globale "Erweitern" aller OnActivates, etc. als zu kritisch bzw. unnoetig, zumal da wirklich viele Komponenten drauf sind.

Noch mal vielen Danke fuer die qualitativen Beitraege!
:dp:

Und weil Teilen freude macht (D2010, k.A. ab welcher Version das noch funktioniert):
Delphi-Quellcode:
  TPopup = class(TForm)
  public
    class var
      LastVisibleTime: Cardinal;
  private
    class constructor Create;
    // initializes the LastVisibleTime class var

    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  end;

class constructor TPopup.Create;
begin
  LastVisibleTime := 0;
end;

procedure TPopup.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  LastVisibleTime := GetTickCount;
end;

{Anderes Form}

procedure TIrgendeinForm.StatusBarClick(Sender: TObject);
begin
  if (TPopup.LastVisibleTime + 300) < GetTickCount then
  begin
    // Show only if there's a small time difference (300ms or more) to the
    // last OnClose of the Popup. This is to "close" the Popup with
    // clicking on the Statusbar again.
    TPopup.Execute(bla bla bla);
  end;
end;

alzaimar 30. Apr 2010 15:35

Re: Ermitteln woher ein Control den Fokus erhalten hat
 
Zitat:

Zitat von idefix2
Zitat:

// Problem: Haben die Controls schon ein OnEnter / OnClick, wird das hier überschrieben.
Das Problem lässt sich durch den Einsatz einer ClassHelper Klasse für TWinControl vermeiden. Dort kann das Original-Onenter und onclick Ereignis überschrieben, aber der Einstiegspunkt, falls er existiert, gemerkt und in dem überschriebenen Ereignis anschliessend aufgerufen werden.

Genau. Das wollte ich aber dem Fragesteller überlassen.

Hawkeye219 30. Apr 2010 16:46

Re: Ermitteln woher ein Control den Fokus erhalten hat
 
Hallo,

hier ist noch ein Vorschlag:

Delphi-Quellcode:
type
  TPopupForm = class (TForm)
    procedure FormDeactivate (Sender: TObject);
  private
    const
      WM_HideWindow = WM_APP + 1;
    procedure WMHideWindow (var aMsg: TMessage); message WM_HideWindow;
  end;

procedure TPopupForm.FormDeactivate (Sender: TObject);
begin
  PostMessage(Handle, WM_HideWindow, 0, 0);
end;

procedure TPopupForm.WMHideWindow (var aMsg: TMessage);
begin
  Hide;
end;

//

procedure TMainForm.StatusBarMouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,
  Y: Integer);
begin
  PopupForm.Visible := not PopupForm.Visible;
end;
Gruß Hawkeye


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:29 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz