gpt4 book ai didi

delphi - 检测焦点控制变化的灵活方法

转载 作者:行者123 更新时间:2023-12-03 14:58:53 25 4
gpt4 key购买 nike

我需要编写一个组件,它将在其他组件中注册,并检测注册的组件之一是否获得焦点。

例如,对于我的组件 TFocusObserver,我正在注册三个对象。

FocusObserver.Register(MyMemo);
FocusObserver.Register(MyButton);
FocusObserver.Register(MyEdit);

现在,如果其中一个组件获得焦点,则 FocusObserver 就会触发一些通知事件。

我正在寻找如何检测焦点变化,并发现 TScreen.OnActiveControlChange 正是我所需要的。所以我的组件可以连接到这个事件。问题是可能存在多个 TFocusObserver,或者将来其他人可能想要使用 OnActiveControlChange

这是我将从多播事件中受益的时候 - 它会立即解决我的问题。

我在想如何解决这个问题,目前有两个想法:

  1. 以某种方式扩展TScreen,这样它就可以为我提供多一个事件。
  2. 引入一个中间对象,它将连接到 OnActiveControlChange 并为其他对象公开一个多播事件。

在简要查看源代码后,我不清楚如何使用第一个想法来解决它,而第二个想法的缺点是有人可以简单地将另一个方法分配给 OnActiveControlChange 并且所有内容都会落下分开。

非常感谢您的一些建议。

最佳答案

如果您的 focusObserver 类可以是 TWinControl 的后代,那么您可以这样做:

TFocusObserver = class( TWinControl )

procedure CMFocusChanged(var Message: TCMFocusChanged); message CM_FOCUSCHANGED;
end;

procedure TFocusObserver.CMFocusChanged(var Message: TCMFocusChanged);
var
LControl: TWinControl;

begin
LControl := TWinControl(Message.Sender);

if LControl <> nil then
begin
form1.Caption := lControl.Name;
end;
end;

这里的主要思想是观看CM_FOCUSCHANGED

第二种方法:

注册控件时,您将替换它的WindowProc。这是一个小代码片段:

TRegisteredComp = class
private
fControl: TControl;
fowndproc: TWndMethod;
procedure HookWndProc(var Message: TMessage);
public
constructor Create( c: TControl );
destructor Destroy; override;
end;

TFocusObserver = class
private
l: TList;
public
constructor Create;
destructor Destroy; override;
procedure reg( c: TControl );

end;

正在实现:

constructor TFocusObserver.Create;
begin
l := TList.Create;
end;

destructor TFocusObserver.Destroy;
var i: integer;
begin
for i := 0 to l.Count - 1 do
TRegisteredComp(l[i]).Free;
l.Free;
inherited;
end;

procedure TFocusObserver.reg( c: TControl );
var
rc: TRegisteredComp;
begin
rc := TRegisteredComp.Create( c );
l.Add( rc );
end;

constructor TRegisteredComp.Create(c: TControl);
begin
fControl := c;
fowndproc := c.WindowProc;
c.WindowProc := HookWndProc;
end;

destructor TRegisteredComp.Destroy;
begin
fControl.WindowProc := fowndproc;
inherited;
end;

procedure TRegisteredComp.HookWndProc(var Message: TMessage);
begin
if ( Message.Msg = CM_FOCUSCHANGED ) and
( TControl(Message.LParam) = fControl ) then
form1.ListBox1.Items.Add( 'focused: ' + fControl.Name );

fowndproc( Message );
end;

不仅仅是注册您想要观看的控件,例如:

procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
fo := TFocusObserver.Create;
for i := 0 to ControlCount - 1 do
fo.reg( Controls[i] );
end;

听起来怎么样?

关于delphi - 检测焦点控制变化的灵活方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11188692/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com