当他的表单或应用程序收到并失去焦点时,如何通知我的自定义控件?

时间:2015-06-17 14:49:45

标签: delphi focus delphi-2009

我希望我的控件只有在它的父窗体(不是面板或其他东西,只是此控件的主窗体)接收并失去焦点时才会收到不同的通知。无论焦点是从应用程序的其他形式切换还是在我的应用程序和其他应用程序之间切换,都必须在两种情况下都收到。可能吗?我希望在表单未激活时暂停控件的某些更新,并在激活表单时恢复更新。

编辑:换句话说,控件必须抓住(TForm.OnActivate + TApplication.OnActivate)和(TForm.OnDeactivate + TApplication.OnDeactivate

Edit2:如果两者都不可能,至少我可以让控件从TApplication捕获事件。它比TForm更重要。

1 个答案:

答案 0 :(得分:3)

  

我希望在表单未激活时暂停控件的某些更新,并在激活表单时恢复更新。

如果这些更新是连续完成的,或者是由计时器或操作触发,那么您可以完成以下操作:

type
  TMyControl = class(TControl)
  private
    procedure PerformUpdate;
  end;

procedure TMyControl.PerformUpdate;
begin
  if Application.Active and HasParent and GetParentForm(Self).Active then
    //...
  else
    //...
end;
  

...至少如果我可以让控件从应用程序中捕获事件

使用TApplication.OnActivate组件抓取TApplication.OnDeactivateTApplicationEvents非常简单:

uses
  Vcl.AppEvnts;

type
  TMyControl = class(TControl)
  private
    FActive: Boolean;
    FAppEvents: TApplicationEvents;
    procedure ApplicationActiveChanged(Sender: TObject);
  public
    constructor Create(AOwner: TComponent); override;
  end;

procedure TMyControl.ApplicationActiveChanged(Sender: TObject);
begin
  FActive := Application.Active;
end;

constructor TMyControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FAppEvents := TApplicationEvents.Create(Self);
  FAppEvents.OnActivate := ApplicationActiveChanged;
  FAppEvents.OnDeactivate := ApplicationActiveChanged;
end;
  

......比形式

更重要

可以在Application.OnIdle中捕获(de)激活父母表格。所有这些结合起来可能会产生这样的结果:

type
  TMyControl = class(TControl)
  private
    FActive: Boolean;
    FAppEvents: TApplicationEvents;
    FParentForm: TCustomForm;
    procedure ApplicationActiveChanged(Sender: TObject);
    procedure ApplicationIdle(Sender: TObject; var Done: Boolean);
    procedure UpdateActive;
  protected
    procedure SetParent(AParent: TWinControl); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

procedure TMyControl.ApplicationActiveChanged(Sender: TObject);
begin
  UpdateActive;
end;

procedure TMyControl.ApplicationIdle(Sender: TObject; var Done: Boolean);
begin
  UpdateActive;
  Done := True;
end;

constructor TMyControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FAppEvents := TApplicationEvents.Create(Self);
  FAppEvents.OnActivate := ApplicationActiveChanged;
  FAppEvents.OnDeactivate := ApplicationActiveChanged;
end;

procedure TMyControl.SetParent(AParent: TWinControl);
begin
  inherited SetParent(AParent);
  FParentForm := GetParentForm(Self);
end;

procedure TMyControl.UpdateActive;
var
  SaveActive: Boolean;
begin
  SaveActive := FActive;
  FActive := Application.Active and (FParentForm <> nil) and FParentForm.Active;
  if Application.Active then
    FAppEvents.OnIdle := ApplicationIdle
  else
    FAppEvents.OnIdle := nil;
  if FActive <> SaveActive then
    Invalidate;
end;

因为使用Application.OnIdle是一种非常严格的方法,所以不必像上面那样使用它,只需在必要时分配它,并通过缓存GetParentForm等函数结果来加速其实现。