汇编 | Java | C# | Delphi | C/C++ |

DELPHI基础教程 第十九章 Delphi自定义部件开发(三)

第十九章 Delphi自定义部件开发(三) 织梦好,好织梦

3. 创建新的消息处理方法 内容来自dedecms

因为Delphi只为大多数普通Windows消息提供了处理方法,所以当你定义自己的消息时,就要创建新的消息处理方法。

内容来自dedecms

 用户自定义消息的过程包括两个方面: 织梦好,好织梦

  定义自己的消息

织梦内容管理系统

声明新的消息处理方法 内容来自dedecms

 

内容来自dedecms

定义自己的消息 内容来自dedecms

许多标准部件为了内部使用定义了消息。定义消息的最一般的动因是广播信息和状态改变的通知。

dedecms.com

  定义消息过程分两步:

copyright dedecms

  ● 声明消息标识符 内容来自dedecms

声明消息记录类型

织梦好,好织梦

 

织梦好,好织梦

声明消息标识

内容来自dedecms

消息标识是整型大小的常量。Windows保存了小于1024的消息用于自己使用,因此当声明自己的消息时,你应当大于1024 copyright dedecms

  常量WM_USER代表用于自定义消息的开始数字。当定义消息标准时,你应当基于WM_USER

内容来自dedecms

  某些标准Windows控制使用用户自定义范围的消息,包括ListBoxComboBoxEditBoxButton。如果从上述部件中继承了一个部件,在定义新的消息时,应当检查一下Message单元是否有消息用于该控制。 copyright dedecms

  定义消息的方法如下:

dedecms.com

  copyright dedecms

  Const

织梦内容管理系统

WM_MYFIRSTMESSAGE=WM_USER+0; dedecms.com

WM_MYSECONDMESSAGE=WM_USER+1;

dedecms.com

  本文来自织梦

声明消息记录类型

dedecms.com

  如果你想给予自定义消息的参数有含义的名字,就要为该消息声明消息记录类型。消息记录是传给消息处理方法的参数的类型。如果不使用消息参数或者想使用旧风格参数,可以使用缺省的消息记录。 dedecms.com

  声明消息记录类型要遵循下列规则 织梦内容管理系统

以消息名命名消息记录类型,以T打头 织梦内容管理系统

将记录中第一个域命名为Msg,类型为TMsgPraram 本文来自织梦

将接着的两个字节定义为word 以响应word大小的参数

织梦好,好织梦

将接着的四个字节与long参数匹配 织梦内容管理系统

将最后的域命名为Result,类型为Longint

织梦好,好织梦

  织梦好,好织梦

下面是TWMMouse的定义 织梦内容管理系统

  织梦好,好织梦

type

织梦好,好织梦

TWMMouse=record

copyright dedecms

Msg: TMsgParam; { 第一个是消息ID }

织梦好,好织梦

Keys: Word; { wParam } 内容来自dedecms

case Integer of { 定义lParam的两种方式 } 本文来自织梦

o: (

织梦好,好织梦

Xpos: Integer; { 或者以xy座标 }

织梦好,好织梦

Ypos: Integer);

织梦内容管理系统

1: (

织梦内容管理系统

Pos : TPoint; { 或者作为单个点 } 内容来自dedecms

Result: Longint; ) { 最后是Result }

织梦好,好织梦

end;

copyright dedecms

  织梦内容管理系统

TWMMouse使用变长记录定义了相同参数的不同名字集。 本文来自织梦

  ⑵ 声明新的消息处理方法 织梦好,好织梦

  有两类环境需要你定义新的消息处理方法:

织梦内容管理系统

  ● 自定义新部件需要处理没有被标准部件处理的Windows消息

织梦好,好织梦

已定义了自定义部件使用的新消息 copyright dedecms

  copyright dedecms

声明消息处理方法的办法如下:

内容来自dedecms

在部件声明中的protected部分声明方法 织梦内容管理系统

将方法做成过程 织梦内容管理系统

以要处理的消息名命名方法 但不带下划线

copyright dedecms

传递一个命名为Messagevar参数,类型为消息记录类型

织梦内容管理系统

编写用于该部件的特别处理代码

copyright dedecms

调用继承的消息方法

内容来自dedecms

  copyright dedecms

下面是用于用户自定义消息CM_CHANGECOLOR的消息处理代码:

织梦好,好织梦

 

copyright dedecms

type 织梦内容管理系统

TMyComponent=class(TControl) 本文来自织梦

copyright dedecms

protected dedecms.com

procedure CMChangeColor(var Message:TMessage);

dedecms.com

message CM_CHANGECOLOR; 织梦好,好织梦

end: 本文来自织梦

  织梦好,好织梦

procedure TMyComponent.CMChangeColor(var Message: TMessage);

dedecms.com

begin 内容来自dedecms

color := Message lParam; copyright dedecms

inherited;

内容来自dedecms

end; 内容来自dedecms

  dedecms.com

19.2.2.4 注册部件 织梦内容管理系统

  内容来自dedecms

  编写部件及其属性、方法和事件只是部件创建过程的一部分。尽管部件具有这些特征就可用,但部件真正功能强大的是在设计时操作它们的能力。

织梦好,好织梦

  使部件在设计时可用需要经过如下几步: 织梦内容管理系统

  ● Delphi注册部件

内容来自dedecms

增加选择板位图

dedecms.com

提供有关属性和事件的帮助 copyright dedecms

存贮和读取属性 织梦好,好织梦

  内容来自dedecms

1. Delphi注册部件

dedecms.com

为了让Delphi识别自定义部件,并将它们放置于Component Palette上,你必须注册每一个部件。 织梦好,好织梦

注册一个部件要在部件所在单元里加入Register方法,这包括两个方面的内容: 本文来自织梦

声明注册过程 copyright dedecms

实现注册过程 dedecms.com

 

织梦内容管理系统

一旦安装了注册过程,就可以将部件安装在选择板上。

本文来自织梦

  注册过程要在部件所在单元中写一个过程,该过程必须以Register命名。Register必须出现在库单元的interface部分,这样Delphi就能定位它。在Register过程中,可以为每个部件调用过程RegisterComponents 本文来自织梦

下面的代码演示了建立和注册部件的概略方法: 本文来自织梦

 

织梦好,好织梦

unit MyBtns; copyright dedecms

  copyright dedecms

interface

织梦好,好织梦

 

copyright dedecms

type

本文来自织梦

{ 声明自定义部件 }

织梦好,好织梦

procedure Register; 本文来自织梦

  本文来自织梦

Implementation 织梦内容管理系统

 

织梦好,好织梦

procedure Register;

织梦内容管理系统

begin

织梦好,好织梦

{ 注册部件 }

copyright dedecms

end;

内容来自dedecms

 

dedecms.com

end. 织梦内容管理系统

  内容来自dedecms

Register过程中,必须注册每一个要加入Component Palette的部件,如果库单元包含若干部件,就要将它们一次性注册。

copyright dedecms

  注册一个部件时,为部件调用RegisterComponents过程。RegisterComponents告诉Delphi两件有关所注册的部件的事:

dedecms.com

要注册部件所在的Component Palette的页名 本文来自织梦

要安装的部件的名字 织梦好,好织梦

  织梦内容管理系统

选择板的页名是个字符串。如果你所给名字的页不存在,Delphi就用该名字创建新的页。 织梦内容管理系统

下面的Register过程注册了一个名为TMyComponent的部件,并将其放在名为“Miscellaneous”的Component Palette页上。

copyright dedecms

  dedecms.com

procedure Register;

织梦好,好织梦

begin

dedecms.com

RegisterComponents('Miscellaneous', [TFirst, TSecond]);

dedecms.com

end; 织梦内容管理系统

  织梦好,好织梦

也可以在相同的页上,或者在不同的页上,一次注册多个部件:

dedecms.com

  内容来自dedecms

procedure Register; dedecms.com

begin

本文来自织梦

RegisterComponents('Miscellaneous', [TFirst, TSecond]); 内容来自dedecms

RegisterComponents('Assorted', [TThird]); 本文来自织梦

end;

织梦好,好织梦

 

本文来自织梦

2. 增加Component Palette上的位图

内容来自dedecms

每个部件都需要一个位图来在Component Palette上代表它。如果安装时没有描述自己的位图,则Delphi会自动套用缺省位图。 copyright dedecms

  因为选择板位图只有在设计时需要,所以没有必要将它们编译进库单元。而是将它们提供在与库单名相同的Windows资源文件中,扩展名为.DCR。用Delphi的位图编辑器来生成资源文件,每个位图边长24个象素。 copyright dedecms

  为每个要安装的库单元提供一个选择板位图文件,在每个文件中为每个要注册的部件提供一个位图。位图图象名与部件名相同,将文件放在与库单元相同的目录中,这样在安装部件时Dephi就能发现位图。

织梦好,好织梦

  例如,如果你在ToolBox单元中创建一个名为TMyControl的部件,就需要建立名为TOOLBOX.DCR的资源文件,文件中包含名为TMyControl的位图。 织梦内容管理系统

  3. 提供有关属性和事件的帮助

织梦好,好织梦

当在窗体中选择一个部件或在Object Inspector中选择事件或属性时,能够按F1得到有关这一项的帮助。如果创建了相应的Help文件的话,自定义部件的用户能得到有关你的部件的相应的文档。 织梦内容管理系统

  因为Delph使用了特殊的Help引擎支持跨多个Help文件处理主题搜索,所以你能提供关于自定义部件的小的Help文件,用户不需要额外的步骤就能找到你的文档。你的Help成了Delphi Help系统的一部分。 copyright dedecms

  要给用户提供帮助,要理解下列两方面:

内容来自dedecms

Delphi怎样处理HELP请求

copyright dedecms

HELP插入Delphi

织梦内容管理系统

  dedecms.com

Delphi怎样处理HELP请求 dedecms.com

Delphi基于关键词查询HELP请求。就是说,当用户在窗体设计窗口的已选部件上按F1键时,Delpdi将部件的名字转换成一个关键词,然后调用Windows Help引擎查找那个关键词的帮助主题。关键词是Windows Help系统的标准部分。实际上 WinHelp使用Help中的关键词产生Search对话框中的列表。因为用于上下文敏感搜索中的关键词不是实际供用户读的,所以要输入关键词的替代词。

织梦内容管理系统

例如,一个查找名为TSomething的部件的详细信息的用户可能打开WinHelpSearch对话框并输入TSomething。但不会使用用于窗体设计窗口的上下文查找的替代形式class-TSomething。因此,这个特殊的关键词Class-TSomething对用户是不可见的,以免弄乱了搜索列表。

内容来自dedecms

  ⑵ Help插入Delphi 织梦内容管理系统

Delphi提供了创建和插入Windows Help文件的工具,包括Windows Help编译器HC.EXE。为自定义部件建立Help文件的机制与建立任何Help文件没什么不同,但需要遵循一些约定以与库中其它Help兼容。 dedecms.com

  保持兼容性的方法如下: 内容来自dedecms

  ● 建立Help文件 本文来自织梦

增加特殊的注脚

dedecms.com

建立关键词文件 copyright dedecms

插入Help索引

织梦内容管理系统

  dedecms.com

当你为自定义部件建立完Help,有下列几个文件: dedecms.com

编译过的Help(.HLP)文件 dedecms.com

Help关键词(.KWF)文件

本文来自织梦

一个或多个Help源文件(.RTF) 内容来自dedecms

Help工程文件(.HLJ)

dedecms.com

  内容来自dedecms

编译过的Help文件和关键词文件应当与库单元在同一目录。

本文来自织梦

  ① 建立Help文件 dedecms.com

你可以使用任何的工具创建Windows Help文件。Delphi的多文件搜索引擎,可以包含任何数目的Help文件的要素。在编译的Help文件之外,你应当拥有RTF源文件,这样才能生成关键词文件。

本文来自织梦

  为使自定义部件的Help同库中其它部件一起工作,要遵循下列约定: 织梦好,好织梦

  ● 每个部件有占一页的帮助

本文来自织梦

部件帮助页应当给出部件目的的简单描述,然后列出最终用户可用的属性、事件和方法的描述。应用开发者通过在窗体上选择部件并按F1访问这一页。

copyright dedecms

  部件帮助页应当有一个用于关键词搜索的“K”脚注,脚注中包含部件名。例如,TMemo的关键词脚注读作"TMemo Component"

dedecms.com

部件增加和修改的每一个属性,事件和方法应当有一页帮助 内容来自dedecms

  属性、事件或方法的帮助页应当指出该项用于哪个部件,显示声明语法和描述它的使用方法。

内容来自dedecms

  属性、事件或方法的帮助页应当有一个用于关键词搜索的“K”脚注,该脚注中包含该项的名字和种类。例如,属性Top的关键词脚注为“Top property”。 织梦内容管理系统

  Help文件的每一页也需要用于多文件索引搜索的特殊脚注。 织梦内容管理系统

  ② 增加特殊脚注 织梦好,好织梦

Delphi需要特殊的搜索关键词以区别用于部件的帮助页和其它项目。你应当为每一项提供标准的关键词搜索项。但你也需要用于Delphi的特殊脚注。 dedecms.com

  要为来自Object Inspector窗口或代码编辑器F1的搜索增加关键词,就得为Help文件帮助页增加"B"脚注。

织梦好,好织梦

  “B”脚注与用于标准WinHelp关键词搜索的“K”脚注很相象,但它们只用于Delphi搜索引擎。下表列出怎样为每种部件帮助页建立“B”脚注:

dedecms.com

  本文来自织梦

19.7 部件帮助页搜索注脚

本文来自织梦

   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

dedecms.com

帮助页类型 "B"脚注内容 dedecms.com

   ──────────────────────────────────

copyright dedecms

主部件页 'class_'+部件类型名 class_TMemd

dedecms.com

一般属性或事件页 'prop_'+属性名 prop_WordWrap

织梦好,好织梦

'event_'+事件名 event_OnChange

织梦内容管理系统

部件特有的属性 'prop_'+部件类型名 prop_TMemoWordWrap

织梦好,好织梦

或事件页 +属性名 内容来自dedecms

'event_'+部件类型名 event_TMemoOnChange

织梦内容管理系统

+事件名

织梦内容管理系统

   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ copyright dedecms

  织梦内容管理系统

  区别一般帮助页和部件特有的帮助页是很重要的。一般帮助页应用于所有部件上的特定属性和事件。例如Left属性是所有部件中的标识。因此,它用字符串Prop-Left进行搜索。而Borde-style依赖于所属的部件,因此,BorderStyle属性拥有自己的帮助页。例如,TEditBorderStyle属性的帮助页,搜索字符串为Prop_TEditBorderStyle

内容来自dedecms

  ③ 建立关键词文件

copyright dedecms

  建立和编译了Help文件,并且增加了脚注之后,还要生成独立的关键词文件,这样Delphi才能将它们插入主题搜索的索引。 织梦好,好织梦

  从Help资源文件RTF创建关键词文件的方法如下: dedecms.com

DOS提示行下,进入包含RTF文件的目录 织梦内容管理系统

运行关键词文件产生程序——KWGEN.EXE,后跟Help工程文件,如KWGEN SPECIAL.HPJ。当KWGEN运行完毕后,就有了与Help工程文件相同的关键词文件,但以.KWF为扩展名

织梦内容管理系统

将关键词文件放在编译完的库单元和Help文件相同的目录

内容来自dedecms

当你在Component Palette上安装部件时,希望关键词插入Delphi Help系统的搜索索引。

copyright dedecms

 

dedecms.com

插入Help索引 本文来自织梦

以自定义部件建立关键词文件后,要将关键词插入DelphiHelp索引。 内容来自dedecms

  将关键词文件插入Detphi Help索引的方法如下: 织梦好,好织梦

将关键词文件放在与编译完的库单元和Heph文件相同的目录中 内容来自dedecms

运行HELPINST程序 本文来自织梦

  织梦好,好织梦

HELPINST运行完后,DelphiHelp索引文件(.HDX)包含自定义部件帮助页的关键词。

织梦内容管理系统

存储和装入属性

织梦好,好织梦

Delphi将窗体及其拥有的部件存储在窗体文件(.DFM)中,DFM文件用二进制表示窗体的属性和它的部件。当Delphi用户将自定义部件加入窗体中时,自定义部件应当具有存储它们的属性的能力。同样,当被调入Delphi或应用程序时,部件必须能从DFM文件中恢复它们。 内容来自dedecms

  在大多数时候,不需要做任何使部件读写DFM文件的事。存储和装入都是继承的祖先部件的行为的一部分。然而在某些情况下,你可能想改变部件存储和装入时初始化的方法。因此,应当理解下述的机制: 织梦内容管理系统

存储和装入机制

内容来自dedecms

描述缺省值

织梦好,好织梦

决定存储什么 dedecms.com

装入后的初始化 织梦内容管理系统

 

dedecms.com

存储和装入机制

本文来自织梦

当应用开发者设计窗体时,Delphi将窗体的描述存储在DFM文件中。当用户运行程序时,它读取这些描述。 本文来自织梦

  窗体的描述包含了一系列的窗体属性和窗体中部件的相似描述。每一个部件,包括窗体本身,负责存储和装入自身的描述。

织梦好,好织梦

  在缺省情况下,当存储时,部件将所有publicpublished属性的不同于缺省值的值以声明的顺序写入。当装入时,部件首先构造自己,并将所有属性设为缺省值;然后,读存储的、非缺省的属性值。 copyright dedecms

  这种缺省机制,满足了大多数部件的需要,而又不需部件编写者的任何工作。然而自己定义存储和装入过程以适合自定义部件需要的方法也有几种。

本文来自织梦

  ② 描述缺省值。 dedecms.com

  Delphi部件只存储那些属性值不同于缺省值的属性。如果你不描述,Delphi假设属性没有缺省值,这意味着部件总是存储属性。 织梦好,好织梦

  一个属性的值没被构造函数设置,则被假设为零值。为了描述一个缺省值,在属性声明后面加default指令和新的缺省值。 本文来自织梦

  你也能在重声明属性时描述缺省值。实际上,重声明属性的一个原因是指定不同的缺省值。只描述缺省值,那么在对象创建时并不会自动地给属性赋值,还需要在部件的Create方法中赋所需的值。

本文来自织梦

  下面的代码用Align属性演示了描述缺省值的过程.

织梦好,好织梦

  copyright dedecms

type 织梦好,好织梦

TStatusBar=class(TPanel)

copyright dedecms

public

织梦内容管理系统

constructor Create(Aowner: TComponent); override; { 覆盖以设置新值 } dedecms.com

published 本文来自织梦

property Align default alBottom; { 重新声明缺省值 } 织梦内容管理系统

end; 织梦好,好织梦

 

本文来自织梦

constructor TStatusBar.Create(Aowner: TComponent); 织梦内容管理系统

begin

织梦好,好织梦

inherited Create(Aowner); { 执行继承的初始化过程 }

copyright dedecms

Align := alBottom; { Align赋新的缺省值 }

dedecms.com

end; 内容来自dedecms

  copyright dedecms

决定存储什么 内容来自dedecms

用户也可以控制Delphi是否存储部件的每一个属性。缺省情况下,在对象的published部分声明的所有属性都被存储。然而,可以选择不存储所给的属性,或者设计一个函数在运行时决定是否存储属性。 dedecms.com

  控制Delphi是否存储属性的方法是在属性声明后面加stored指令,后跟TrueFalse,或者是布尔方法名。你可以给任何属性的声明或重声明加stored表达式。下面的代码显示了部件声明三种新属性。一个属性是总是要存储,一个是不存,第三个则决定于布尔方法的值: 织梦内容管理系统

  本文来自织梦

type

内容来自dedecms

TSampleCompiment = class(TComponent) dedecms.com

protected

本文来自织梦

function storeIt: Boolean;

dedecms.com

public { 正常情况下在不存 } 内容来自dedecms

property Important: Integer stored True; { 总是存储 }

织梦好,好织梦

published { 正常情况下保存 }

织梦内容管理系统

property UnImportant: Integer stored False; { 不存 } 织梦好,好织梦

property Sometimes: Integer stored StoreIt; { 存储依赖于函数值 } 织梦内容管理系统

end; dedecms.com

 

本文来自织梦

载入后的初始化

织梦好,好织梦

在部件从存储的描述中读取所有的属性后,它调用名为Loaded的虚方法,这提供了按需要执行任何初始化的机会。调用Loaded是在窗体和它的控制显示之前,因此,不需要担心初始化会带来屏幕闪烁。 织梦好,好织梦

  在部件载入属性时初始化它,要覆盖Loaded方法。 dedecms.com

  在Loaded方法中,要做的第一件事是调用继承的Loaded方法。这使得在你的部件执行初始化之前,任何继承的属性都已初始化。 本文来自织梦

  下面的代码来自于TDatabase部件。在装入后,TDatabase试图重建在它存储时已打开的连接,并描述在连接发生异常时如何处理。

织梦内容管理系统

 

本文来自织梦

  procedure TDatabase.Loaded dedecms.com

begin

内容来自dedecms

inherited Loaded; { 总是先调用继承的方法 }

内容来自dedecms

Modified; { 设置内部标志 } 织梦内容管理系统

try

内容来自dedecms

if FStreamedConnected then Open; { 重建联接 }

dedecms.com

except

copyright dedecms

if csDesigning in ComponentState then { 在设计时 } 内容来自dedecms

Application.HandleException(self) { Delphi处理异常 }

织梦内容管理系统

else raise; { } 织梦好,好织梦

end; dedecms.com

end; 织梦内容管理系统

  内容来自dedecms

 

本文来自织梦

19.3 Delphi部件编程实例

织梦内容管理系统

  dedecms.com

19.3.1 创建数据库相关的日历控制-TDBCalendar 织梦内容管理系统

  织梦内容管理系统

  当处理数据库联接时,将控制和数据直接相联是很重要的。就是说,应用程序可以建立控制与数据库之间的链。Delphi包括了数据相关的标签、编辑框、列表框和栅格。用户可以使自己的控制与数据相关。 dedecms.com

  数据相关有若干等级。最简单的是只读数据相关或数据浏览,以及反映数据库当前状态的能力。比较复杂的是数据相关的编辑,也即用户可以在控制上操作数据库中的数据。

内容来自dedecms

  在本部分中将示例最简单的情况,即创建联接数据库的单个字段的只读控制。本例中将使用Component PaletteSamples页中的TCalendar部件。 本文来自织梦

创建数据相关的日历控制包括下列几步:

copyright dedecms

创建和注册部件 内容来自dedecms

使控制只读 织梦内容管理系统

增加数据联接(Data Link) 内容来自dedecms

响应数据改变

织梦好,好织梦

 

内容来自dedecms

19.3.1. 1创建和注册部件 织梦好,好织梦

 

织梦好,好织梦

每个部件的创建都从相同的方式开始,在本例中将遵循下列过程:

织梦内容管理系统

将部件库单元命名为DBCal dedecms.com

TCalendar继承一个新部件,名为TDBCalendar 织梦好,好织梦

Component PaletteSamples页中注册TDBCalendar 织梦好,好织梦

  织梦好,好织梦

下面就是创建的代码: 织梦好,好织梦

 

dedecms.com

unit DBCal;

内容来自dedecms

  织梦好,好织梦

interface dedecms.com

 

copyright dedecms

uses SysUtils, WinTypes, WinProc, Messages, Classes, Graphics, Controls,

织梦内容管理系统

Forms, Grids, Calendar;

内容来自dedecms

type

织梦好,好织梦

TDBCalendar=class(TCalendar) copyright dedecms

end; 织梦好,好织梦

 

内容来自dedecms

procedure Register; dedecms.com

 

copyright dedecms

implementation

织梦内容管理系统

  dedecms.com

procedure Register;

dedecms.com

begin

copyright dedecms

RegisterComponents(Samples[TDBabendar]); copyright dedecms

end;

织梦内容管理系统

 

本文来自织梦

end. 本文来自织梦

 

织梦好,好织梦

19.3.1.2 使控制只读 内容来自dedecms

  本文来自织梦

因为这个数据日历以只读方式响应数据,所以用户不能在控制中改变数据并指望它们反映到数据库中。 织梦内容管理系统

使日历只读包含下列两步: 织梦内容管理系统

增加只读属性 织梦内容管理系统

允许所需的更新 dedecms.com

 

织梦内容管理系统

1. 增加只读属性 本文来自织梦

给日历控制增加只读选项是直接过程。通过增加属性,可以提供在设计时使控制只读的方法,当属性值被设为True,将使控制中所有元素不可被选。

织梦内容管理系统

增加属性声明和保存值的private域: 本文来自织梦

 

dedecms.com

type 本文来自织梦

TDBCalendar=class(TClendar) copyright dedecms

private copyright dedecms

FReadOnly: Boolean;

dedecms.com

public

织梦好,好织梦

constructor Create (Aowner: TComponent); override;

dedecms.com

published 本文来自织梦

property ReadOnly: Boolean read FReadOnly write FReadOnly default True;

copyright dedecms

end;

本文来自织梦

  本文来自织梦

constructor TDBCalendar.Create(Aowner: TComponent); 织梦内容管理系统

begin 本文来自织梦

inherited Create(AOwner); 织梦内容管理系统

FReadOnly := True; copyright dedecms

end; 内容来自dedecms

  本文来自织梦

覆盖SelectCell方法,使得当控制是只读时,不允许选择: 织梦好,好织梦

  内容来自dedecms

function TDBCalendar.SelectCell(ACol, Arow: Longint): Boolean;

本文来自织梦

begin

内容来自dedecms

if FReadOnly then dedecms.com

Result := False

内容来自dedecms

else 内容来自dedecms

Result := inherited SelectCell(AcolARow); 内容来自dedecms

end; 织梦好,好织梦

 

dedecms.com

还要在TDBcalendar的声明中声明SelectCell

内容来自dedecms

如果现在将Calendar加入窗体,会发现部件完全忽略鼠标和击键事件,而且当改变日期时,也不能改变选择的位置。下面将使控制响应更新。 织梦内容管理系统

2. 允许所需的更新

织梦好,好织梦

只读日历使用SelectCell方法实现各种改变,包括设置RowCol的值。当日期改变时,UpdateCalendar方法设置RowCol的值,但因为SelectCell不允许你改变,即使日期改变了,选择仍留在原处。

内容来自dedecms

可以给日历增加一个Boolean标志,当标志为True时允许改变: dedecms.com

 

本文来自织梦

type copyright dedecms

TDBCalendar=class(TCalendar)

内容来自dedecms

private

本文来自织梦

Fupdating: Boolean; dedecms.com

protected 织梦好,好织梦

function SelectCell(Acol, Arow: Longint); Boolean; override;

织梦内容管理系统

public 织梦内容管理系统

procedure UpdateCalendar; override; 本文来自织梦

end; dedecms.com

 

织梦好,好织梦

function TDBCalendar.SelectCell(ACol, ARow: Longint): Boolean;

dedecms.com

begin 织梦内容管理系统

if (not FUpdating) and FReadOnly then

内容来自dedecms

Result := False { 如果更新则允许选择 }

copyright dedecms

else

本文来自织梦

Result := inherited SelectCell(ACol, ARow); { 否则调用继承的方法 } 内容来自dedecms

end;

内容来自dedecms

 

织梦好,好织梦

procedure UpdateCalendar;

copyright dedecms

begin 织梦好,好织梦

FUpdating := True; { 将标志设为允许更新 }

织梦好,好织梦

try

dedecms.com

inherited UpdateCalendar; { 象通常一样更新 } 织梦内容管理系统

finally

copyright dedecms

FUpdating := False; { 总是清除标志 }

内容来自dedecms

end;

dedecms.com

end;

织梦好,好织梦

 

织梦好,好织梦

  现在日历仍旧不允许用户修改,但当改变日期属性时能正确反映改变;目前已有了一个真正只读控制,下一步是增加数据浏览能力。 dedecms.com

 

copyright dedecms

  3. 增加数据联接 本文来自织梦

  控制和数据库的联接是由一个名为DataLink的对象处理。Delphi提供了几种类型的Datalink。将控制与数据库单个域相联的DataLink对象是TFieldDatalinkDelphi也提供了与整个表相联的DataLink

本文来自织梦

  一个数据相关控制拥有DataLink对象,就是说,控制负责创建和析构DataLink

本文来自织梦

  要建立作为拥有对象的Datalink,要执行下列三步: 织梦内容管理系统

  ● 声明对象域 织梦好,好织梦

  ● 声明访问属性

织梦好,好织梦

  ● 初始化DataLink

织梦好,好织梦

  本文来自织梦

  ⑴ 声明对象域 织梦内容管理系统

  每个部件要为其拥有对象声明一个对象域。因此,日历对象DataLink 声明TFieldDataLink类型的域。 copyright dedecms

  日历部件中DataLink的声明如下:

内容来自dedecms

 

copyright dedecms

type 织梦好,好织梦

TDBCalendar = class(TSampleCalendar)

织梦内容管理系统

private 织梦内容管理系统

FDataLink: TFieldDataLink; 内容来自dedecms

本文来自织梦

end;

dedecms.com

  本文来自织梦

  ⑵ 声明访问属性

本文来自织梦

  每一个数据相关控制有一个DataSource属性,该属性描述应用程序给控制提供数据的数据源。而且,访问单个域的数据库还需要一个DataField 属性描述数据源中的域。 本文来自织梦

  下面是DataSourceDataField的声明和它们的实现方法: 织梦内容管理系统

 

copyright dedecms

type 本文来自织梦

TDBCalendar = class(TSampleCalendar) 本文来自织梦

private { 属性的实现方法是 }

copyright dedecms

function GetDataField: string; { 返回数据库字段的名字 } 内容来自dedecms

function GetDataSource: TDataSource; { 返回数据源(Data source)的引用 }

copyright dedecms

procedure SetDataField(const Value: string); { 给数据库字段名赋值 }

本文来自织梦

procedure SetDataSource(Value: TDataSource); { 给数据源赋值 }

内容来自dedecms

published { 使属性在设计时可用 }

内容来自dedecms

property DataField: string read GetDataField write SetDataField;

dedecms.com

property DataSource: TDataSource read GetDataSource write SetDataSource; 内容来自dedecms

end; copyright dedecms

 

织梦好,好织梦

……

织梦内容管理系统

 

本文来自织梦

function TDBCalendar.GetDataField: string; 本文来自织梦

begin 内容来自dedecms

Result := FDataLink.FieldName; 织梦内容管理系统

end;

copyright dedecms

  织梦内容管理系统

function TDBCalendar.GetDataSource: TDataSource; 本文来自织梦

begin

copyright dedecms

Result := FDataLink.DataSource;

本文来自织梦

end; 织梦好,好织梦

  织梦好,好织梦

procedure TDBCalendar.SetDataField(const Value: string);

本文来自织梦

begin

copyright dedecms

FDataLink.FieldName := Value;

本文来自织梦

end; 内容来自dedecms

  内容来自dedecms

procedure TDBCalendar.SetDataSource(Value: TDataSource);

dedecms.com

begin dedecms.com

FDataLink.DataSource := Value; copyright dedecms

end; 织梦内容管理系统

  本文来自织梦

  现在,就建立了日历和DataLink的链,此外还有一个更重要的步骤。你必须在日历构建时创建DataLink对象,在日历析构时,撤消DataLink对象。

织梦好,好织梦

  ⑶ 初始化DataLink 织梦内容管理系统

  在数据相关控制在其存在的期间要不停地访问DataLink对象,因此,必须在其构建函数中创建DataLink创建并且在析构时,撤消DataLink对象,因此要覆盖日历的CreateDestroy方法。 本文来自织梦

  织梦好,好织梦

type

织梦内容管理系统

TDBCalendar=class(TCalendar) 本文来自织梦

public

本文来自织梦

constructor Create(Aowna: TComponent); override;

dedecms.com

destructor Destroy; override;

本文来自织梦

end;

织梦内容管理系统

  dedecms.com

constructor TDBCalendar Create (Aowner: TComponent); copyright dedecms

begin 内容来自dedecms

inherited Create(AOwner);

织梦好,好织梦

FReadOnly := True; copyright dedecms

FDataLink := TFieldDataLink.Create;

copyright dedecms

end; copyright dedecms

 

内容来自dedecms

destructor TDBCalendar Destroy;

copyright dedecms

begin

dedecms.com

FDataLink.Free; 织梦内容管理系统

inherited Destroy; 织梦好,好织梦

end; copyright dedecms

 

copyright dedecms

现在,部件已拥有完整的DataLink,但部件还不知从相联的域中读取什么数据。

copyright dedecms

 

织梦好,好织梦

19.3.1.4 响应数据变化

内容来自dedecms

 

织梦内容管理系统

  一旦控制拥有了数据联接(DataLink)和描述数据源和数据域的属性。就需在数据记录改变时响应域中数据的变化。 本文来自织梦

  DataLink对象都有个名为OnDataChange的事件。当数据源指示数据发生变化时,DataLink对象调用任何OnDataChange所联接的事件处理过程。 本文来自织梦

  要在数据改变时更新数据,就需要给DataLink对象的OnDataChange事件增加事件处理过程。

织梦好,好织梦

  下面声明了DataChange方法,并将其赋给DataLink对象的OnDataChange事件: 内容来自dedecms

 

内容来自dedecms

type

织梦好,好织梦

TDBCalendar=class(TCalendar)

织梦内容管理系统

private dedecms.com

procedure Datachange(Sender: TObject); dedecms.com

end;

dedecms.com

 

本文来自织梦

constructor TDBCalendar Create(AOwner:TComponent);

织梦好,好织梦

begin copyright dedecms

inherited Create(AOwner);

内容来自dedecms

FReadOnly := True;

织梦好,好织梦

FDataLink := TFieldDataLink.Create;

本文来自织梦

FDataLink.OnDataChange := DataChange; 内容来自dedecms

end; 内容来自dedecms

  copyright dedecms

destructor TDBcalendar.Destroy; 织梦好,好织梦

begin

copyright dedecms

FDataLink.OnDataChange := nil; 本文来自织梦

FDataLink.Free; 内容来自dedecms

inherited Destroy dedecms.com

end;

dedecms.com

  copyright dedecms

procedure TDBCalendar.DataChange(Sender: TObject); dedecms.com

begin copyright dedecms

if FDataLink.Filed=nil then 织梦内容管理系统

CalendarDate := 0; 本文来自织梦

else

织梦好,好织梦

CalendarDate := FDataLink.Field.AsDate;

织梦好,好织梦

end;

本文来自织梦

;

织梦好,好织梦

精彩推荐
热点内容
最近更新