六、控件手拉手�D�D控件关联的实现
控件的关联在
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
对应的数据集中的记录的条数。
本文出自 “CowNew开源团队” 博客,转载请与作者联系!