【问题标题】:Attach or Hook an event of all components附加或挂钩所有组件的事件
【发布时间】:2013-12-03 10:37:38
【问题描述】:

我有一个小问题。 我需要创建一个组件来捕获特定类型组件的一些事件,这些事件独立于它们的数量。 示例:我需要在每次调用事件 TIBDatabase 时激活活动组件(Palette Interbase),然后在我的运行事件代码的组件激活时自动配置组件的一些属性。 是自动执行此操作吗?示例:当我将组件放在表单上时,他会自动与事件建立联系?? 非常感谢。

注意:我无法重现 (How can I dynamically inject code into event handlers in Delphi?) 的示例

已编辑:

我正在尝试使用“Ritsaert Hornstra”的示例。接受答案的示例我必须扫描所有组件。

该示例仅在我激活要监视的事件组件时才有效。 示例:当我重现链接的示例时,“TIBQuery”组件具有“AfterOpen”事件不起作用。但是,如果我在组件实例运行中的该事件中添加任何内容。 他不是自动做的。 我正在使用 Delphi XE3。

编辑 2:

嗨,克雷格·杨。 今天,我有几个系统在积极生产中。 我想做的是实现系统开发时没有完成的安全日志。 这将是 Hercules 的第 13 次人工操作。 我需要做什么。 一个组件,当 adiconado 在数据模块中挂钩/附加 InterBase 数据库组件的一些事件时。 我只需要一个工作示例来完成剩下的工作。我只想知道谁做了什么,做了什么变量系统:g_s_user,g_s_date,g_s_sql。 由于几乎所有组件都连接到 TDataset,因此我打算这样做并实现该组件。

我还没有准备好代码,因为我仍然不知道该怎么做!

谢谢。

【问题讨论】:

  • 由于您提供的链接的已接受答案非常有效,并且您的答案看起来像是问题的副本。您可能会展示您尝试过的方法和无效的方法。
  • 您到底尝试了什么?另外,看看TApplicationEvents 的实现。
  • 这些超级通用的、自动魔法的、灵丹妙药的解决方案正是让您在创建极其复杂、非常死板而又时遇到严重麻烦的原因脆弱的 系统。我建议您更具体地定义您要实现的目标,并针对特定问题提出特定的解决方案。例如。您可以定义自己的组件来使用,而不是使用标准的 IB 组件。您可以使用工厂在运行时创建组件;确保它们从一开始就正确配置。最合适的解决方案取决于您的问题的具体情况

标签: delphi events hook


【解决方案1】:

在 Delphi 中以编程方式添加事件处理程序并不难。例如,假设您想添加一个事件处理程序来响应BeforeDelete 事件。你这样做:

interface

type
  TMyDatasetHook = class
  protected
    TargetDataset: TDataset;
    PreviousBeforeDelete: TDataSetNotifyEvent;
    procedure DatasetBeforeDelete(aSender: TObject);
    procedure CleanupHooks(aDataset: TDataset);
    procedure SetupHooks(aDataset: TDataset);
  public
    constructor Create(aDataset: TDataset);
    destructor Destroy; override;
  end; 

implementation

constructor TMyDatasetHook.Create(aDataset: TDataset);
begin
  TargetDataset := aDataset;
  SetupHooks(TargetDataset);
end;

destructor TMyDatasetHook.Destroy;
begin
  CleanUpDataset(TargetDataset);
  inherited;
end;

procedure TMyDatasetHook.DatasetBeforeDelete(aSender: TObject);
begin
  // Here goes your code to handler BeforeDelete
  if Assigned(PreviousBeforeDelete) then
    PreviousBeforeDelete(aSender); // Here we call the existing handler
end;

procedure TMyDatasetHook.CleanupHooks(aDataset: TDataset);
begin
  aDataset.BeforeDelete := PreviousBeforeDelete;
end;

procedure TMyDatasetHook.SetupHooks(aDataset: TDataset);
begin
  PreviousBeforeDelete := aDataset.BeforeDelete; // Here we save the existing handler
  aDataset.BeforeDelete := DatasetBeforeDelete;
end;

您现在需要做的是实例化该类,将目标数据集传递给它的构造函数

 var
   myDatasetHook: TMyDatasetHook;
 begin
   myDatasetHook := TMyDatasetHook.Create(someTargetDataset);
 end;

您现在需要调整上述课程以满足您的特定需求。

【讨论】:

    【解决方案2】:

    亚历克斯

    谢谢你的回复。 我实际上已经解决了这个问题。它不漂亮。但它奏效了。 很高兴知道有像您这样的人愿意帮助并做出建设性的 cmets。不像我们高贵的朋友克雷格。除了没有帮助我的问题变得消极。 如果我来 stackoverflow 是因为我真的很难做到。想象一下解释我想要什么。但没关系。我非常感谢所有以某种方式帮助我解决问题的人。 关于你 AlexSC,我将发布我所做的事情: PS:我会冒昧地用例子来增强我的代码好吗?

    unit Sample;
    
    interface
    
    uses
      System.SysUtils, System.Classes, Dialogs, IBDatabase, Data.DB, System.Win.Registry, Winapi.Windows;
    
    type
      TSample = class(TComponent)
      private
        FBanco: TIBDatabase;
        FDataSet: TDataSet;
        L_FBeforeScroll: TDataSetNotifyEvent;
        L_FBeforeRefresh: TDataSetNotifyEvent;
        Procedure OnRefresh(DataSet: TDataSet);
        Procedure OnScroll(DataSet: TDataSet);
        Procedure SetBanco(Value: TIBDatabase);
      public
        { Public declarations }
        constructor Create(AOwner : TComponent); override;
        destructor Destroy;override;
      published
        { Published declarations }
        property  Database: TIBDatabase read FBanco write SetBanco;
      end;
    
    procedure Register;
    
    implementation
    
    procedure Register;
    begin
      RegisterComponents('DataXML', [TSample]);
    end;
    
    constructor TSample.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
    end;
    
    destructor TSample.Destroy;
    begin
      inherited;
    end;
    
    procedure TSample.OnRefresh(DataSet: TDataSet);
    begin
      if Assigned(L_FBeforeRefresh) then
        L_FBeforeRefresh(FDataSet);
    end;
    
    procedure TSample.OnScroll(DataSet: TDataSet);
    begin
      if Assigned(L_FBeforeScroll) then
        L_FBeforeScroll(FDataSet);
    end;
    
    procedure TSample.SetBanco(Value: TIBDatabase);
    begin
      FBanco := Value;
      FDataSet := FBanco.DataSets[0];
      L_FBeforeScroll := FDataSet.BeforeScroll;
      L_FBeforeRefresh := FDataSet.BeforeScroll;
      FDataSet.BeforeScroll:=OnScroll;
      FDataSet.BeforeScroll:=OnRefresh;
    end;
    
    end.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-16
      • 2013-04-01
      • 1970-01-01
      • 2016-09-22
      • 1970-01-01
      • 2011-03-01
      • 1970-01-01
      • 2015-06-05
      相关资源
      最近更新 更多