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

dum*_*uch 6 delphi delphi-2007

这是关于Delphi和VCL.

我有几个框架可以用于多种形式,通常是在代码中创建并添加到表单中.表单可能包含其中几个框架.当包含它的表单被取消激活时,我需要在这些帧中执行一些代码,并在激活它时将其反转.

TMyFrame.FormActivated;
TMyFrame.FormDeactivated
Run Code Online (Sandbox Code Playgroud)

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

procedure TMyForm.OnActivate(_Sender: TObject);
begin
  FFrame1.FormActivated;
  FFrame2.FormActivated;
end;
Run Code Online (Sandbox Code Playgroud)

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

  • 我必须在包含这些帧的实例的每个表单中实现它
  • 表单必须知道某些帧需要此调用(紧耦合)
  • 帧需要发布在这些事件中调用的两个方法.我宁愿不公开这些方法.

另一种选择是从帧的构造函数中设置FormActivate/FormDeactivate事件.但这意味着在这些事件中不能执行其他代码,如果在同一表单上有多个这样的帧,它将无法工作.

是否有任何其他选项适用于包含其中几个框架的任何表单?

如果这很重要,我需要Delphi 2007.

Ond*_*lle 7

(假设VCL)框架应以某种方式拦截父窗体的激活/停用事件.有很多可能的方法可以做到这一点(设置父窗体OnActivate/ OnDeactivate事件,使用或子类化)但是你必须强制执行,如果多个框架实例对同一个窗体实例执行此操作,则删除钩子的顺序必须与插入相反钩子.此外,在重新创建窗口句柄时,您将遇到正确处理案例的问题.SetWindowLong(GWL_WNDPROC)WindowProc

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

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;
Run Code Online (Sandbox Code Playgroud)

和这样的东西作为项目中所有框架的祖先:

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;
Run Code Online (Sandbox Code Playgroud)

这样的耦合是相当宽松,它仍然可以让你覆盖默认TMyFrame通过重写行为CM_ACTIVATECM_DEACTIVATE消息处理程序中需要特殊处理的后裔.

注意事项:

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


Uwe*_*abe 6

不知道这是否可行,但几年前我遇到了类似的问题,并通过某种形式/框架继承来解决它.有一个基本框架类声明这些方法虚拟和一个表单类捕获事件并迭代调用适当的框架方法的所有子框架.派生的帧根据需要覆盖这些方法.这减少了与基类的耦合.

在后来的重构中,这被改为由框架实现的接口,完全消除了窗体和框架类之间的耦合.

  • 我对有关接口方法的更多细节感兴趣:表单如何调用方法?它是否为其所有组件调用Supports(component,ISomeInterface,InterfaceVar)? (2认同)