Delphi-PRAXiS

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 Screen.OnActiveControlChange - gibt es Alternative? (https://www.delphipraxis.net/118855-screen-onactivecontrolchange-gibt-es-alternative.html)

taaktaak 16. Aug 2008 14:44


Screen.OnActiveControlChange - gibt es Alternative?
 
Moin, Moin.
Ich hab eine Klasse, die Focuswechsel innerhalb meiner Anwendung verfolgt. Ziel ist es, insbesondere nach einem Klick auf einen Help-Button den Focus auf das vorher aktive Conrol zurücksetzen zu können. In diesem Thread hatte ich vor einiger Zeit einen ersten Lösungsversuch vorgestellt. Die damaligen von SirThornberry benannten Restriktionen konnten von mir leider nicht beseitigt werden.

Letztlich ist die Verwendung von Screen.OnActiveControlChange innerhalb der Klasse indiskutabel, da das Ganze nur funktioniert, wenn ich im übrigen Programmcode auf die Verwendung dieses Events verzichte. Als Notlösung ist im untenstehenden Code ein "eigenes" OnActiveControlChange enthalten, dass in der Anwendung anstelle des gleichnamigen Events von TScreen verwendet werden kann.

Das ist aber in meinen Augen keine vernünftige Lösung. Mein Ziel ist, die Nachricht über einen Focuswechsel ohne Verwendung von Screen.OnActiveControlChange zu erhalten und die Adresse des Controls zu speichern - und da komme ich nicht weiter.

Meine Versuche WM_SETFOCUS und WM_KILLFOCUS zu verwenden, scheiterten. Die Botschaften werden offenbar von der Klasse nicht empfangen. Dann fand ich CM_FOCUSCHANGED, eine, wenn ich das richtig verstanden habe, Delphi-interne Botschaft. Aber auch darauf reagierte meine Klasse nicht. Zuletzt habe ich versucht nachzuvollziehen, wie Delphi das Screen.OnActiveControlChange verwendet, aber auch das führte leider zu keinem Erfolg. Habe nicht feststellen können, ob Delphi hierzu überhaupt irgendwelche Windows-Botschaften verwendet; es scheint mir so, dass dieses Event von der VCL eigenständig ausgelöst wird.

Auch wenn's jetzt ein bisschen lang wird, hier mal der aktuelle Code:

Delphi-Quellcode:
unit rzM_WatchFocus;
//
// Application may NOT use Screen.OnActiveControlChange !!!
//      Replacement >> WatchFocus.OnActiveControlChange !!!
//
// bad solution!!!!!!!!!!! 
//
interface { ----------------------------------------------------------------- }

uses Classes,Controls,Forms;

type TWatchFocus = class(TControl)

                    private

                     FActiveControlChange             : TNotifyEvent;

                     FActControl,
                     FLastControl,
                     FStoreControl                    : TWinControl;

                     procedure CollectFocus          (Sender:TObject);

                    public

                     procedure    StoreLastFocus;
                     procedure  RestoreLastFocus;
                     property   OnActiveControlChange : TNotifyEvent
                                                         read FActiveControlChange
                                                         write FActiveControlChange;

                     constructor Create               (AOwner:TComponent); override;
                     destructor Destroy;                                  override;

                    end;

var WatchFocus  : TWatchFocus;

implementation { ------------------------------------------------------------ }

procedure TWatchFocus.CollectFocus(Sender:TObject);
begin
  if Assigned(FActiveControlChange) then FActiveControlChange(Self);
  FLastControl:=FActControl;
  FActControl :=Screen.ActiveControl;
end;

procedure TWatchFocus.StoreLastFocus;
begin
  if FLastControl<>nil then FStoreControl:=FLastControl;
end;

procedure TWatchFocus.RestoreLastFocus;
begin
  if FStoreControl<>nil then
    if FStoreControl.Visible then
      if FStoreControl.Enabled then FStoreControl.SetFocus;
end;

constructor TWatchFocus.Create(AOwner:TComponent);
begin
  inherited Create(AOwner);
  FActControl :=nil;
  FLastControl :=nil;
  FStoreControl:=nil;
  Screen.OnActiveControlChange:=CollectFocus
end;

destructor TWatchFocus.Destroy;
begin
  Screen.OnActiveControlChange:=nil;
  inherited Destroy
end;

initialization { ------------------------------------------------------------ }

  WatchFocus:=TWatchFocus.Create(nil);

finalization { -------------------------------------------------------------- }

  WatchFocus.Free;
  WatchFocus:=nil;

end.
Die Klasse wird nur mir uses eingebunden und z.B. so verwendet:

Delphi-Quellcode:
procedure TfoImportScan.buHelpClick(Sender:TObject);
begin
  WatchFocus.StoreLastFocus;
  // call help
  WatchFocus.RestoreLastFocus;
end;
Tja, da stehe ich nun ratlos an der Grenze meiner Kenntnisse und hoffe auf eure Hilfe...

omata 16. Aug 2008 17:51

Re: Screen.OnActiveControlChange - gibt es Alternative?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier mal ein Vorschlag...

Edit: Wichtig, habe noch etwas verändert!

taaktaak 16. Aug 2008 18:06

Re: Screen.OnActiveControlChange - gibt es Alternative?
 
Aaaaaaaaaaha
:shock: :shock: :shock:
könntest du mir den Code mal im "Venezia" erklären???
(Bist eingeladen)

omata 16. Aug 2008 18:10

Re: Screen.OnActiveControlChange - gibt es Alternative?
 
Was ist daran unverständlich?

taaktaak 16. Aug 2008 18:15

Re: Screen.OnActiveControlChange - gibt es Alternative?
 
Nach kurzem draufschauen so ziemlich alles. Aber zunächst einmal vielen Dank für deinen Aufwand. Ich werde es mir mal in Ruhe anschauen :hi:

// edit
Nach erstem Versuch den Code zu verstehen, mit den Worten eines Stümpers:
Der Thread nutzt auch Screen.ActiveControlChange und "verbiegt" das Event regelmäßig auf TWatchFocus. Sobald das Ergebnis übergeben ist, wird das Event wieder "zurückgebogen". Nun, auf jeden Fall ist es mir gelungen eine Prozedur "RestoreLastFocus" einzubauen und damit meine (aktuelle) Aufgabenstellung zu befriedigen. Die weitergehenden Möglichkeiten der History können später genutzt werden. Bis dahin genügt es mir, das ganze als "Blackbox" zu nutzen.

// edit2
Damit die Liste nicht irgendwann mal überläuft habe ich der Unit nun noch eine festlegbare Obergrenze der Listengröße spendiert.

omata - noch einmal meinen herzlichen Dank!


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:53 Uhr.

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