zoukankan      html  css  js  c++  java
  • 自定义控件-控件关联

    控件的关联在Delphi中也是很常见的,我们可以设定一个控件的某个属性指向另一个控件。比如我们在窗体上放上 Tedit,TpopupMenu两个控件,然后设定Tedit的PopupMenu属性为TpopupMenu控件,运行后在Tedit点击右键就会弹出刚才设定的那个TpopupMenu菜单,也就是说Tedit,TpopupMenu联手完成了任务。再比如TDBEdit控件的DataSource 属性就可以指向一个TdataSource控件,这样就可以在TDBEdit控件中显示TdataSource输出的某个字段的值了。
      下面我们将写一个简单的实现控件关联的控件。这个控件派生于Tedit,它可以与一个Tlabel控件关联,在控件的编辑框中输入文字时,与它关联的Tlabel控件的文字将随着它而变化。代码如下:
    unit MyEdit;
    interface
    uses
      SysUtils, Classes, Controls, StdCtrls;
    type
      TMyEdit = class(TEdit)
      private
        FLinkLabel: TLabel;
        procedure FSetLinkLabel(AValue: TLabel);
      protected
        procedure Notification(AComponent: TComponent;Operation: TOperation);
              override;
        procedure Change;override;
      public
      published
        property LinkLabel: TLabel read FLinkLabel write FSetLinkLabel;
      end;

    procedure Register;

    implementation
    procedure Register;
    begin
      RegisterComponents('Linco', [TMyEdit]);
    end;
    procedure TMyEdit.Change;
    begin
      inherited;
      if LinkLabel <> nil then
        LinkLabel.Caption := Text;
    end;

    procedure TMyEdit.FSetLinkLabel(AValue: TLabel);
    begin
      FLinkLabel := AValue;
      if AValue <> nil then
        FLinkLabel.FreeNotification(self);
    end;

    procedure TMyEdit.Notification(AComponent: TComponent;
      Operation: TOperation);
    begin
      inherited;
      if (Operation = opRemove) and (AComponent = LinkLabel) then
        LinkLabel := nil;
    end;
    end.
    代码解释:
    (1)、我们只要将控件的任意一个属性的类型设定为另外一个控件的类名称,那么我们就可以在控件的Object Inspector中将这个属性指向那个控件(或那个控件的派生控件)的一个实例。比如本例中我们增加了LinkLabel属性,它的类型为 Tlabel,所以我们就可以把LinkLabel属性指向一个标签控件。
    (2)、请注意FsetLinkLabel中的这段代码:
    if AValue <> nil then
    FLinkLabel.FreeNotification(self);
    如果我们将控件关联属性指向了一个控件,可是后来又将被指向的控件删除了,那么我们的控件关联属性是不会自动删除的,这样就会造成控件关联属性指向的控件不存在的现象。我们必须自动感知被关联控件的删除并重新设定控件关联属性为不指向任何控件,这样就避免了错误的发生。
    FLinkLabel.FreeNotification(self); 的作用就是这样的。它调用控件的FreeNotification方法(在Tcomponent中定义)向被指向的控件注册一个“消息”,当被指向控件被删除时,会向所有向他注册的控件发送一个它被删除的消息,此时向他注册的控件就会触发Notification方法,这样我们就可以自动感知被指向控件的状态了。这是设计模式中Observer(观察者)模式的典型应用。
    既然向他注册的控件就会触发Notification方法,我们就覆盖父类的Notification方法,写出如下的代码:
      if (Operation = opRemove) and (AComponent = LinkLabel) then
        LinkLabel := nil;
    这句话的意思是:如果控件被删除并且被删除的控件(因为我们的控件可能向多个控件注册了消息)是LinkLabel,那么我们就设定LinkLabel属性不指向任何控件。
    (3)覆盖父类的Change调度方法。在此方法里为连接的LinkLabel的Caption赋值就达到我们的目的了。
    思考题:
    1、做一个Label控件,给它增加一个DataSource属性,该属性可以指向一个TdataSource类型的控件,它有一个GetRecordCount方法。当调用此方法时,就在Label控件中显示这个DataSource对应的数据集中的记录的条数。

  • 相关阅读:
    (数据结构)十分钟搞定时间复杂度(算法的时间复杂度)
    深入学习二叉树
    我对工作的认识
    mysql系列纠错;
    关于普通指针转换为智能指针的一些问题
    vscode The VS Code Server failed to start
    git 分支管理
    git change_id的理解
    git 指令速查
    c++ make_shared()函数理解 (待整理)
  • 原文地址:https://www.cnblogs.com/h2zZhou/p/4991781.html
Copyright © 2011-2022 走看看