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...