TMyComponent = class (TComponent)
private
FDataSource: TDataSource;
procedure SetDataSource(Value: TDataSource);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
published
property DataSource: TDataSource read FDataSource write SetDataSource;
end;
procedure TMyComponent.SetDataSource(Value: TDataSource);
begin
if Value <> FDataSource then
begin
FDataSource := Value;
// 告诉参考组件说,当它被移除时记得通知我一声。
if FDataSource <> nil then FDataSource.FreeNotification(Self)
end;
end;
procedure TMyComponent.Notification(AComponent: TComponent; Operation:TOperation);
begin
inherited Notification(AComponent, Operation);
// 如果被移除的正是参考组件,把FDataSource字段清除。
if (Operation = opRemove) and (AComponent = FDataSource) then
FDataSource := nil
end;
5.3 什么是组件讯息?
组件讯息是什么?它十分类似Windows的窗口讯息,只有一点不同:组件讯息只适用于 VCL 组件;而窗口讯息可以用在系统内所有具有 window handle 的控件或窗口。如果你有一个具有 Font 属性的组件(例如TLabel组件),当我们更改它的 Font 属性时并没有送出窗口讯息(译注:TLabel 组件不是窗口控件,根本也没有窗口 Handle可以让我们传送窗口讯息),但是控件仍然知道字型改变了所以要重画自己,为什么?因为我们有组件讯息。
组件讯息不可以由虚拟方法来处理,这可能是设计 VCL 时的考量,大概是因为不想让虚拟方法表格(Virtual Method Table)过于庞大的原因。
『Secrets of Delphi 2.0』这本书对于所有的组件讯息有十分详尽的解说。
接下来我们列出一些比较常见的组件讯息及它们的作用。标示着『Notification Only』 的讯息表示送出这个讯息只是为了通知组件某件消息而己,并不传入任何参数而且也不需要传回值。
CM_ACTIVATE (Notification Only)
当表格成为焦点窗口时会传给本身这个讯息。
CM_CTL3DCHANGED (Notification Only)
当控件的Ctl3D属性更改时会传给本身这个讯息。
CM_DESIGNHITTEST 参数:TCMDesignHitTest 传回值:0或1
在设计时期当鼠标移到组件上头时,整合环境会送给此组件这个讯息。此讯息的目的用来决定组件在设计时期是否要处理鼠标讯息。如果传回值是 1,整合环境就让组件自行处理鼠标讯息;若传回值是 0,则整合环境会帮你处理鼠标讯息。如果传回值永远是 1,那么组件的快速功能选单则永远不会出现;如果组件不处理这个讯息或永远传回 0,那此组件在设计时期将无法对鼠标讯息做任何反应。
CM_FONTCHANGED (Notification Only)
控件的字型改变后送给本身此讯息。
CM_FONTCHANGE (Notification Only)
当控件收到WM_FONTCHANGE窗口讯息时会送给本身这个讯息。
CM_PARENTCTL3DCHANGED (Notification Only)
当组件父控件的Ctl3D属性改变或设定新的父控件时会收到此讯息。
CM_PARENTCOLORCHANGED (Notification Only)
当组件父控件的 Color 属性改变或设定新的父控件时会收到此讯息。
CM_PARENTFONTCHANGED (Notification Only)
当组件父控件的Font属性改变或设定新的父控件时会收到此讯息。
CM_PARENTSHOWHINTCHANGED (Notification Only)
当组件父控件的ShowHint属性改变或设定新的父控件时会收到此讯息。
CM_WININICHANGE 参数:TWMWinIniChange 传回值:无
当控件收到WM_WININICHANGE窗口讯息时会送给本身这个讯息。
5.4 我的组件得到输入焦点后仍不能接受键盘讯息,为什么?
如果你的组件有 DragMode 属性而且将它设成 dmAutomatic 时,很有可能让你的组件以为它正被拖曳但实际上并没有的情况。在 Controls 单元中有一个区域变量 DragControl 指 向目前正被拖曳的组件。你遇到的情况很可能就是明明没有拖曳的动作但是DragControl 变量却指向你的组件。在 TWinControl 的 WndProc 方法中,当 DragControl 变量指向组件本身时,会忽略所有键盘讯息,这就是原因了!
--------------------------------------------------------------------------------
第六部分 其它信息
6.1 有哪些书介绍或讲解如何撰写组件?
有关撰写组件的『标准』参考书籍:
『Developing Delphi Components』 作者:Ray Konopka 出版:Coriolis Group
下面这本书并不专注于组件写作,但里面提到许多组件撰写者不可不知的信息:
『Secrets of Delphi 2』 作者:Ray Lischner 出版:Waite Group
另外一本组件撰写的好书,它有许多在『Developing Delphi Components』里找不到的信息:
『Programming Delphi Custom Components』 作者:Fred Bulback 出版:M&T Books
6.2 有哪些Web站台可以取得撰写组件的信息?
全世界最大的 Delphi Web 站台『Delphi SuperPage』
(译注:亚洲地区使用者可以就近到位于日本的 Mirror Site )
我在下面这些站台中找到许多组件的原始程序代码:
Temple of Delphi
Delphi Free Stuff
(译注:『Your Delphi Programming Resource』整理组件也十分用心! )
(译注:台湾地区目前维持最好的 Delphi 站台是『32 Bit Delphi 深度历险』及其 Mirror Site)
你也可以使用一些搜寻引擎来寻找有关 Delphi 的站台:
Yahoo
Alta Vista
(译注:Excite 搜寻引擎也别错过啰!)
--------------------------------------------------------------------------------
第七部分 组件的储存与加载
7.1 如何将包含其它对象的对象一起存入 DFM 檔?
我试过许多方法,包括改写组件的 DefineProperties及 WriteComponents方法,但都还是失败了。所以我只能说要解决这个问题的话只有使用 Delphi 原本的方法一途。
将包含其它对象的对象一起储存起来的步骤大致如下:
确定你要储存的所有对象都是从 TComponent 类别衍生下来的。
将所有需要储存的变量宣告在 published 区段。
在组件的 Register 程序中呼叫 RegisterComponents程序来注册所有你要储存起来的类别。
每个拥有子控件的类别必须改写 GetChildren 方法以储存每个子控件。(在 Delphi 1.0 中你必须改写 WriteComponents 方法并且为每个子控件呼叫 WriteComponent方法)。
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




