| 域名空间 下载中心 社区论坛 信息公告 my小屋 |
![]() |
联系我们 设为首页 加入收藏 |
|
首页 | 新闻资讯 | 编程开发 | 网页设计 | 图形图象 | 网络媒体 | 网站模板 | 数 据 库 | 投稿 论坛 | 操作系统 | 系统优化 | 网络安全 | 黑客技术 | 硬件学堂 | 硬件报价 | 服 务 器 | 地图 专题 | 应用软件 | 聊天通讯 | q q 专栏 | 建站经验 | 在线工具 | 站长club | 注 册 表 | 旧版 社会 | 游戏娱乐 | 设计欣赏 | 疑难解答 | 社区论坛 | 网络赚钱 | 网站地图 | 广告服务 | 服务 |
| 新版上线![旧版] | |||||
注:打开慢时请稍等
|
3. 创建新的消息处理方法因为delphi只为大多数普通 用户自定义消息的过程包括两个方面: ● ●
⑴ 许多标准部件为了内部使用定义了消息。定义消息的最一般的动因是广播信息和状态改变的通知。 定义消息过程分两步: ● 声明消息标识符 ●
① 消息标识是整型大小的常量。 常量wm_user代表用于自定义消息的开始数字。当定义消息标准时,你应当基于 某些标准windows控制使用用户自定义范围的消息,包括 定义消息的方法如下:
const wm_myfirstmessage=wm_user+0; wm_mysecondmessage=wm_user+1;
② 如果你想给予自定义消息的参数有含义的名字,就要为该消息声明消息记录类型。消息记录是传给消息处理方法的参数的类型。如果不使用消息参数或者想使用旧风格参数,可以使用缺省的消息记录。 声明消息记录类型要遵循下列规则 ● ● ● ● ●
下面是twmmouse的定义
type twmmouse=record msg: tmsgparam; { 第一个是消息 keys: word; { wparam } case integer of { 定义 o: ( xpos: integer; { 或者以 ypos: integer); 1: ( pos : tpoint; { 或者作为单个点 result: longint; ) { 最后是 end;
twmmouse使用变长记录定义了相同参数的不同名字集。 ⑵ 声明新的消息处理方法 有两类环境需要你定义新的消息处理方法: ● 自定义新部件需要处理没有被标准部件处理的 ●
声明消息处理方法的办法如下: ● ● ● ● ● ●
下面是用于用户自定义消息
type tmycomponent=class(tcontrol) … protected procedure cmchangecolor(var message:tmessage); message cm_changecolor; end:
procedure tmycomponent.cmchangecolor(var message: tmessage); begin color := message lparam; inherited; end;
19.2.2.4 注册部件
编写部件及其属性、方法和事件只是部件创建过程的一部分。尽管部件具有这些特征就可用,但部件真正功能强大的是在设计时操作它们的能力。 使部件在设计时可用需要经过如下几步: ● 用 ● ● ●
1. 用delphi注册部件 为了让delphi识别自定义部件,并将它们放置于 注册一个部件要在部件所在单元里加入 ● ●
一旦安装了注册过程,就可以将部件安装在选择板上。 注册过程要在部件所在单元中写一个过程,该过程必须以 下面的代码演示了建立和注册部件的概略方法:
unit mybtns;
interface
type … procedure register;
implementation
procedure register; begin … end;
end.
在register 注册一个部件时,为部件调用registercomponents ● ●
选择板的页名是个字符串。如果你所给名字的页不存在, 下面的register过程注册了一个名为
procedure register; begin registercomponents('miscellaneous', [tfirst, tsecond]); end;
也可以在相同的页上,或者在不同的页上,一次注册多个部件:
procedure register; begin registercomponents('miscellaneous', [tfirst, tsecond]); registercomponents('assorted', [tthird]); end;
2. 增加component palette上的位图 每个部件都需要一个位图来在 因为选择板位图只有在设计时需要,所以没有必要将它们编译进库单元。而是将它们提供在与库单名相同的 为每个要安装的库单元提供一个选择板位图文件,在每个文件中为每个要注册的部件提供一个位图。位图图象名与部件名相同,将文件放在与库单元相同的目录中,这样在安装部件时 例如,如果你在toolbox 3. 提供有关属性和事件的帮助 当在窗体中选择一个部件或在 因为delph使用了特殊的help 要给用户提供帮助,要理解下列两方面: ● ●
⑴ delphi基于关键词查询 例如,一个查找名为 ⑵ 将 delphi提供了创建和插入 保持兼容性的方法如下: ● 建立 ● ● ●
当你为自定义部件建立完 ● ● ● ●
编译过的help文件和关键词文件应当与库单元在同一目录。 ① 建立 你可以使用任何的工具创建 为使自定义部件的help ● 每个部件有占一页的帮助 部件帮助页应当给出部件目的的简单描述,然后列出最终用户可用的属性、事件和方法的描述。应用开发者通过在窗体上选择部件并按 部件帮助页应当有一个用于关键词搜索的“K”脚注,脚注中包含部件名。例如, ● 属性、事件或方法的帮助页应当指出该项用于哪个部件,显示声明语法和描述它的使用方法。 属性、事件或方法的帮助页应当有一个用于关键词搜索的“K”脚注,该脚注中包含该项的名字和种类。例如,属性 help文件的每一页也需要用于多文件索引搜索的特殊脚注。 ② 增加特殊脚注 delphi需要特殊的搜索关键词以区别用于部件的帮助页和其它项目。你应当为每一项提供标准的关键词搜索项。但你也需要用于 要为来自object inspector “b”脚注与用于标准winhelp
表19.7部件帮助页搜索注脚 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 帮助页类型 ────────────────────────────────── 主部件页 一般属性或事件页 'event_'+事件名 部件特有的属性 或事件页 'event_'+部件类型名 +事件名 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
区别一般帮助页和部件特有的帮助页是很重要的。一般帮助页应用于所有部件上的特定属性和事件。例如 ③ 建立关键词文件 建立和编译了help 从help资源文件rtf创建关键词文件的方法如下: ● ● ● 当你在component palette上安装部件时,希望关键词插入
④ 以自定义部件建立关键词文件后,要将关键词插入 将关键词文件插入detphi help ● ●
helpinst运行完后, ⑶ delphi将窗体及其拥有的部件存储在窗体文件 在大多数时候,不需要做任何使部件读写dfm文件的事。存储和装入都是继承的祖先部件的行为的一部分。然而在某些情况下,你可能想改变部件存储和装入时初始化的方法。因此,应当理解下述的机制: ● ● ● ●
① 当应用开发者设计窗体时, 窗体的描述包含了一系列的窗体属性和窗体中部件的相似描述。每一个部件,包括窗体本身,负责存储和装入自身的描述。 在缺省情况下,当存储时,部件将所有public和 这种缺省机制,满足了大多数部件的需要,而又不需部件编写者的任何工作。然而自己定义存储和装入过程以适合自定义部件需要的方法也有几种。 ② 描述缺省值。 delphi部件只存储那些属性值不同于缺省值的属性。如果你不描述, 一个属性的值没被构造函数设置,则被假设为零值。为了描述一个缺省值,在属性声明后面加 你也能在重声明属性时描述缺省值。实际上,重声明属性的一个原因是指定不同的缺省值。只描述缺省值,那么在对象创建时并不会自动地给属性赋值,还需要在部件的 下面的代码用align
type tstatusbar=class(tpanel) public constructor create(aowner: tcomponent); override; { 覆盖以设置新值 published property align default albottom; { 重新声明缺省值 end;
constructor tstatusbar.create(aowner: tcomponent); begin inherited create(aowner); { 执行继承的初始化过程 align := albottom; { 为 end;
③ 用户也可以控制 控制delphi是否存储属性的方法是在属性声明后面加
type tsamplecompiment = class(tcomponent) protected function storeit: boolean; public { 正常情况下在不存 property important: integer stored true; { 总是存储 } published { 正常情况下保存 property unimportant: integer stored false; { 不存 } property sometimes: integer stored storeit; { 存储依赖于函数值 } end;
④ 在部件从存储的描述中读取所有的属性后,它调用名为 在部件载入属性时初始化它,要覆盖loaded方法。 在loaded方法中,要做的第一件事是调用继承的 下面的代码来自于tdatabase
procedure tdatabase.loaded begin inherited loaded; { 总是先调用继承的方法 modified; { 设置内部标志 try if fstreamedconnected then open; { 重建联接 except if csdesigning in componentstate then { 在设计时 } application.handleexception(self) { 让 else raise; { 否则 end; end;
19.3 delphi部件编程实例
19.3.1 创建数据库相关的日历控制-
当处理数据库联接时,将控制和数据直接相联是很重要的。就是说,应用程序可以建立控制与数据库之间的链。 数据相关有若干等级。最简单的是只读数据相关或数据浏览,以及反映数据库当前状态的能力。比较复杂的是数据相关的编辑,也即用户可以在控制上操作数据库中的数据。 在本部分中将示例最简单的情况,即创建联接数据库的单个字段的只读控制。本例中将使用 创建数据相关的日历控制包括下列几步: ● ● ● ●
19.3.1. 1创建和注册部件
每个部件的创建都从相同的方式开始,在本例中将遵循下列过程: ● ● ●
下面就是创建的代码:
unit dbcal;
interface
uses sysutils, wintypes, winproc, messages, classes, graphics, controls, forms, grids, calendar; type tdbcalendar=class(tcalendar) end;
procedure register;
implementation
procedure register; begin registercomponents(samples, end;
end.
19.3.1.2 使控制只读
因为这个数据日历以只读方式响应数据,所以用户不能在控制中改变数据并指望它们反映到数据库中。 使日历只读包含下列两步: ● ●
1. 增加只读属性 给日历控制增加只读选项是直接过程。通过增加属性,可以提供在设计时使控制只读的方法,当属性值被设为 ⑴
type tdbcalendar=class(tclendar) private freadonly: boolean; public constructor create (aowner: tcomponent); override; published property readonly: boolean read freadonly write freadonly default true; end;
constructor tdbcalendar.create(aowner: tcomponent); begin inherited create(aowner); freadonly := true; end;
⑵
function tdbcalendar.selectcell(acol, arow: longint): boolean; begin if freadonly then result := false else result := inherited selectcell(acol, end;
还要在tdbcalendar的声明中声明 如果现在将 2. 允许所需的更新 只读日历使用 可以给日历增加一个
type tdbcalendar=class(tcalendar) private fupdating: boolean; protected function selectcell(acol, arow: longint); boolean; override; public procedure updatecalendar; override; end;
function tdbcalendar.selectcell(acol, arow: longint): boolean; begin if (not fupdating) and freadonly then result := false { 如果更新则允许选择 else result := inherited selectcell(acol, arow); { 否则调用继承的方法 } end;
procedure updatecalendar; begin fupdating := true; { 将标志设为允许更新 try inherited updatecalendar; { 象通常一样更新 finally fupdating := false; { 总是清除标志 end; end;
现在日历仍旧不允许用户修改,但当改变日期属性时能正确反映改变;目前已有了一个真正只读控制,下一步是增加数据浏览能力。
3. 增加数据联接 控制和数据库的联接是由一个名为datalink 一个数据相关控制拥有datalink 要建立作为拥有对象的datalink ● 声明对象域 ● 声明访问属性 ● 初始化
⑴ 声明对象域 每个部件要为其拥有对象声明一个对象域。因此,日历对象 日历部件中datalink
type tdbcalendar = class(tsamplecalendar) private fdatalink: tfielddatalink; … end;
⑵ 声明访问属性 每一个数据相关控制有一个datasource 下面是datasource和datafield
type tdbcalendar = class(tsamplecalendar) private { 属性的实现方法是 function getdatafield: string; { 返回数据库字段的名字 function getdatasource: tdatasource; { 返回数据源 procedure setdatafield(const value: string); { 给数据库字段名赋值 } procedure setdatasource(value: tdatasource); { 给数据源赋值 } published { 使属性在设计时可用 property datafield: string read getdatafield write setdatafield; property datasource: tdatasource read getdatasource write setdatasource; end;
……
function tdbcalendar.getdatafield: string; begin result := fdatalink.fieldname; end;
function tdbcalendar.getdatasource: tdatasource; begin result := fdatalink.datasource; end;
procedure tdbcalendar.setdatafield(const value: string); begin fdatalink.fieldname := value; end;
procedure tdbcalendar.setdatasource(value: tdatasource); begin fdatalink.datasource := value; end;
现在,就建立了日历和datalink ⑶ 初始化 在数据相关控制在其存在的期间要不停地访问
type tdbcalendar=class(tcalendar) public constructor create(aowna: tcomponent); override; destructor destroy; override; end;
constructor tdbcalendar create (aowner: tcomponent); begin inherited create(aowner); freadonly := true; fdatalink := tfielddatalink.create; end;
destructor tdbcalendar destroy; begin fdatalink.free; inherited destroy; end;
现在,部件已拥有完整的
19.3.1.4 响应数据变化
一旦控制拥有了数据联接(datalink) datalink 要在数据改变时更新数据,就需要给datalink对象的 下面声明了datachange
type tdbcalendar=class(tcalendar) private procedure datachange(sender: tobject); end;
constructor tdbcalendar create(aowner:tcomponent); begin inherited create(aowner); freadonly := true; fdatalink := tfielddatalink.create; fdatalink.ondatachange := datachange; end;
destructor tdbcalendar.destroy; begin fdatalink.ondatachange := nil; fdatalink.free; inherited destroy end;
procedure tdbcalendar.datachange(sender: tobject); begin if fdatalink.filed=nil then calendardate := 0; else calendardate := fdatalink.field.asdate; end; ; 编辑:黑鹰 [发送给好友] [打印本页] [关闭窗口] [返回顶部] 上一篇:第十九章 delphi自定义部件开发(二) 下一篇:第十九章 delphi自定义部件开发(四) 转载请注明来源:www.iyit.net 特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。 |
| 最新更新 | 热点排行 | 推荐新闻 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 友情链接 | ||||||
| 设置首 页 - 版权声明 - 广告服务 - 关于我们 - 联系我们 - 友情连接 |
| |||||||