【问题标题】:How can I force a component on a TFrame to have it's own event handler?如何强制 TFrame 上的组件拥有自己的事件处理程序?
【发布时间】:2012-04-19 17:42:36
【问题描述】:

我很难让 Delphi 2006 将事件处理程序分配给 TFrame 上独立的组件。

假设我有一个框架 TComboFrame,其中包含一个 TCombo Combo1,我在主窗体的多个位置使用它。

当我将 TComboFrame MyFrame1 的实例放到我的主窗体上时,我想分配一个 组合的事件处理程序,我通过单击里面的 TCombo 来完成 我放在表单上的框架MyFrame1,然后双击空白 OnChange 对象检查器事件选项卡中的字段。

通常会创建一个名称如下的新处理程序:

procedure TMainForm.MyFrame1Combo1Change(Sender: TObject);

并且事件处理程序名称源自祖先 TComboFrame (Combo1) 上的组件名称和我放置在表单上的实例名称 (MyFrame1) - 即对于该实例是唯一的TComboFrame。那我可以 对我放置在主框架上的其他框架实例执行此操作 表单,它们每个都有自己的事件处理程序。

如果我想要一个为框架的所有实例触发的事件处理程序, 我会打开祖先框架本身并在那里做。

这是我对它应该如何工作的理解,但有些东西 哪里出错了。在我的主要框架的几个实例中 表单,有的有自己的事件处理器,有的有共同的事件处理器,

procedure TDMainForm.ComboFrame1Combo1Change(Sender: TObject);

我尝试过的任何方法都没有破坏 Delphi 似乎拥有的这个幻像链接 这个由多个框架共享的公共事件处理程序。

我该如何修复这种状态,首先是什么原因造成的?

** 更新 1 **

在阅读回复和一些实验后,我发现我可以通过以下过程修复有问题的组件:

1) 删除框架的所有事件处理程序。
2) 删除框架,记住它的名字。
3) 复制另一个已知正常的事件(即拥有自己的“个人”事件名称)。
4) 将那个粘贴到您删除的那个位置。
5) 恢复原名。
6) 创建您的事件处理程序。

...至少,它至少对我有用一次...

** 更新 2 **

另一种解决方法似乎是在对象检查器中双击空事件字段时改写它创建的事件处理程序名称,并使用一个新的唯一名称,然后再次双击该名称。 Delphi 然后创建一个具有唯一名称的空处理程序。

【问题讨论】:

    标签: delphi event-handling delphi-2006 tframe


    【解决方案1】:

    我会在框架中编写另一个事件,并在我想要另一个 OnChange 事件时设置它,如下所示:

    type
      TFrame2 = class(TFrame)
        ComboBox1: TComboBox;
        procedure ComboBox1Change(Sender: TObject);
      private
        FMyChangeEvent: TNotifyEvent;
      public
        property MyChangeEvent: TNotifyEvent read FMyChangeEvent write FMyChangeEvent
      end;
    
    implementation
    
    {$R *.dfm}
    
    procedure TFrame2.ComboBox1Change(Sender: TObject);
    begin
      //Your default combo behavior here
      if Assigned(FMyChangeEvent) then
        FMyChangeEvent(Self);
    end;
    

    我需要在 OnChange 行为中添加一些内容:

    type
      TForm1 = class(TForm)
        MyLittleFrame: TFrame2;
      private
        procedure MyOwnCustomLittleOnChangeBehavior(Sender: TObject);
      public
        constructor Create(AOwner: TComponent); override;
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    constructor TForm1.Create(AOwner: TComponent);
    begin
      inherited;
      MyLittleFrame.MyChangeEvent :=  MyOwnCustomLittleOnChangeBehavior;
    end;
    
    procedure TForm1.MyOwnCustomLittleOnChangeBehavior(Sender: TObject);
    begin
      ShowMessage('42');
    end;
    

    我通常这样做是因为我不相信在 DFM 中设置事件的 delphi 方式,很容易在不注意的情况下删除整个事件。

    【讨论】:

      【解决方案2】:

      只需单击要断开链接的TCombo,在对象检查器中清除其OnClick 事件处理程序分配,然后双击该事件以生成新的事件处理程序。当然,如果生成的事件处理程序名称已经存在,它会被重新使用,但至少 Object Inspector 会在生成事件时重新评估所有的对象名称。

      当然,这不是一种非常面向对象的方法。法比奥建议的是更好的选择。虽然我建议将TFrame 事件声明为published 而不是public,这样您就可以像任何其他事件一样在设计时分配它。

      【讨论】:

      • 我也不喜欢已发布的事件,如果您需要删除它们,只会在运行时出错。因此,如果可能的话,我希望避免声明已发布的事件。如果它是您要共享的最终用户组件并希望他们在对象检查器中设置事件,那就太好了。
      • 谢谢@Remy。还是没有骰子。我仍然得到一个名称基于祖先名称而不是单个组件的处理程序,然后该帧的所有其他事件以及“损坏”的帧的所有其他实例都会发生这种情况。我的源中的任何地方都不存在事件处理程序名称。有关更多信息,请参阅 OP 附录。
      【解决方案3】:

      我无法在 Delphi6 或 Delphi 2009 中重新创建这种行为。在我看来,有很多框架(并且可能会更改它们的名称添加和删除)你已经愚弄/迷惑了 Delphi 的命名约定,它默认使用它来链接事件和帧的名称与之前的名称相同。

      因此,双击事件处理程序只会将您置于与由先前删除(或重命名)的框架创建的事件处理程序同名的事件处理程序(但删除框架不会删除旧的事件处理程序。IYSWIM :)

      因此,我的回答是,你把框架名称和事件处理程序名称弄得一团糟!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-12
        • 2012-12-20
        • 2019-11-07
        相关资源
        最近更新 更多