加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 检测聚焦控制变化的灵活方法

发布时间:2020-12-15 04:32:14 所属栏目:大数据 来源:网络整理
导读:我需要编写一个组件,它将在其他组件中注册,并检测其中一个注册组件是否获得焦点. 例如,对于我的组件TFocusObserver,我正在注册三个对象. FocusObserver.Register(MyMemo);FocusObserver.Register(MyButton);FocusObserver.Register(MyEdit); 现在,如果其中一
我需要编写一个组件,它将在其他组件中注册,并检测其中一个注册组件是否获得焦点.

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

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

现在,如果其中一个组件获得焦点,那么FocusObserver会启动一些通知事件.

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

这是我将从多播事件中受益的时间 – 它将立即解决我的问题.

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

>以某种方式扩展TScreen,这样它将为我提供一个更多的活动.
>引入一个中间对象,它将连接到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.

第二种方法:

注册Control时,将其替换为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;

听起来怎么样?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读