delphi - 当拥有框架的表单被激活/停用时,是否有一种简单的方法来调用框架中的方法?

标签 delphi delphi-2007

这是关于 Delphi 和 VCL 的内容。

我有几个可以在多种表单中使用的框架,通常是在代码中创建并添加到表单中。一个表单可能包含多个这样的框架。当包含它的表单被停用时,我需要在这些帧中执行一些代码,并在它被激活时反转它。

TMyFrame.FormActivated;
TMyFrame.FormDeactivated

一种解决方案是在那些调用框架方法的表单中拥有 FormActivate/FormDeactivate 事件处理程序。

procedure TMyForm.OnActivate(_Sender: TObject);
begin
  FFrame1.FormActivated;
  FFrame2.FormActivated;
end;

这就是我目前的实现方式,但这有几个缺点:

  • 我必须在包含这些框架实例的每种表单中实现此功能
  • 表单必须知道某些框架需要此调用(紧密耦合)
  • 框架需要发布两个在这些事件中调用的方法。我不想公开这些方法。

另一个选项是从框架的构造函数中设置 FormActivate/FormDeactivate 事件。但这意味着在这些事件中无法执行其他代码,并且如果同一表单上有多个此类框架,则该代码将无法工作。

还有其他选项适用于包含多个此类框架的任何表单吗?

如果这很重要,我需要 Delphi 2007 的这个。

最佳答案

(假设 VCL)框架应该以某种方式拦截父窗体的激活/停用事件。有很多可能的方法可以做到这一点(设置父窗体的 OnActivate/OnDeactivate 事件,使用 SetWindowLong (GWL_WNDPROC) WindowProc 进行子类化),但是如果多个框架实例对同一形式实例,取出钩子(Hook)的顺序必须与插入钩子(Hook)的顺序相反。此外,当重新创建窗口句柄时,您还会遇到正确处理情况的问题。

更简单的方法可能是使用这样的东西作为项目中所有表单的祖先:

TMyForm = class(TForm)
  procedure Activate; override;
  procedure Deactivate; override;
end;

procedure TMyForm.Activate;
begin
  inherited Activate;
  NotifyControls(CM_ACTIVATE);
end;

procedure TMyForm.Deactivate;
begin
  inherited Deactivate;
  NotifyControls(CM_DEACTIVATE);
end;

像这样作为项目中所有框架的祖先:

TMyFrame = class(TFrame)
  procedure CMActivate(var Msg: TCMActivate); message CM_ACTIVATE;
  procedure CMDeactivate(var Msg: TCMDeactivate); message CM_DEACTIVATE;
end;

procedure TMyFrame.CMActivate(var Msg: TCMActivate);
begin
  // parent form activated
end;

procedure TMyFrame.CMDeactivate(var Msg: TCMDeactivate);
begin
  // parent form deactivated
end;

这样耦合就相当松散,并且仍然允许您覆盖默认的 TMyFrame通过覆盖 CM_ACTIVATE 的行为或CM_DEACTIVATE后代中需要特殊处理的消息处理程序。

注意事项:

  1. 这尚未经过测试 - 这只是一个快速建议,作为起点。您还可以声明并使用您自己的自定义消息而不是 CM_ACTIVATE/CM_DEACTIVATE ,以避免对 VCL 的其余部分产生任何干扰。
  2. NotifyControls通知所有控件 - 不仅是帧 - 但普通控件会忽略/不处理 CM_ACTIVATE/CM_DEACTIVATE默认情况下会发送消息,所以这应该不是问题。您还可以实现自己的 NotifyFrames方法。

关于delphi - 当拥有框架的表单被激活/停用时,是否有一种简单的方法来调用框架中的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37614144/

相关文章:

delphi - 您可以覆盖对自定义 TForm/Dialog 的 MessageDlg 调用吗?

sql-server - 为什么 Delphi 控制台应用程序需要表单才能使 TSQLConnection 工作?

c# - 在 Delphi 2007 中使用 SDK BSOD 但在 C# 中工作的应用程序

Delphi 2007支持Windows 2008 R2吗?

delphi - OnKeyPress 事件中如何转换 Ctrl + 快捷键?

德尔福型类型转换

Delphi:如何以相反的顺序删除子类?

delphi:var 参数上的不可访问值

delphi - 打印二维码报告时列表索引越界错误

delphi - 将 TInterfacedObject 转换为接口(interface)