我希望我的控件仅在父窗体(不是面板或其他内容,只是此控件的主窗体)接收并失去焦点时接收不同的通知。无论焦点是从另一种形式的应用程序切换还是在我的应用程序和其他应用程序之间切换,对于这两种情况都必须接收它。可能吗?我想在他的窗体未处于活动状态时暂停控件的某些更新,并在窗体激活时恢复更新。
编辑:换句话说,控件必须捕获 ( TForm.OnActivate
+ TApplication.OnActivate
) 和 ( TForm.OnDeactivate
+ TApplication.OnDeactivate
)
Edit2:如果两者兼而有之,至少如果我可以让控件从应用程序捕获事件。它比来自 TForm 的那些更重要。
我想在他的窗体未处于活动状态时暂停控件的某些更新,并在窗体激活时恢复更新。
如果这些更新是连续完成的,或者是由计时器或操作触发的,那么您可以完成:
type
TMyControl = class(TControl)
private
procedure PerformUpdate;
end;
procedure TMyControl.PerformUpdate;
begin
if Application.Active and HasParent and GetParentForm(Self).Active then
//...
else
//...
end;
。至少如果我可以让控件从应用程序中捕获事件
使用TApplicationEvents
组件捕获TApplication.OnActivate
和TApplication.OnDeactivate
非常容易:
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
中完成。所有这些结合起来可能会导致这样的事情:
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
)来加速它的实现。