delphi最新版教程(DELPHI基础教程:Delphi自定义部件开发(二)[1])
![delphi最新版教程(DELPHI基础教程:Delphi自定义部件开发(二)[1])](/static/images/content_image/autumn-1913485_1920.jpg)
本文目录
DELPHI基础教程:Delphi自定义部件开发(二)[1]
Delphi部件编程
创建属性
属性(Property)是部件中最特殊的部分 主要因为部件用户在设计时可以看见和操作它们 并且在交互过程中能立即得到返回结果 属性也很重要 因为如果将它们设计好后 将使用户更容易地使用 自己维护起来也很容易
为了使你在部件中更好地使用属性 本部分将介绍下列内容
● 为什么要创建属性
● 属性的种类
● 公布(publishing)继承的属性
● 定义部件属性
● 编写属性器
为什么要创建属性
属性提供非常重要的好处 最明显的好处是属性在设计时能出现在Object Inspector窗口中 这将简化编程工作 因为你只需读用户所赋的值 而不要处理构造对象的参数
从部件使用者的观点看 属性象变量 用户可以给属性赋值或读值 就好象属性是对象的域
从部件编写者的观点看属性比对象的域有更强的功能
⑴ 用户可以在设计时设置属性
这是非常重要的 因为不象方法 只能在运行时访问 属性使用户在运行程序之前就能定制部件 通常你的部件不应包含很多的方法 它们的功能可以通过属性来实现
⑵ 属性能隐藏详细的实现细节
⑶ 属性能引起简单地赋值之外的响应 如触发事件
⑷ 用于属性的实现方法可以是虚拟方法 这样看似简单的属性在不同的部件中 将实现不同的功能
属性的类型
属性可以是函数能返回的任何类型 因为属性的实现可以使用函数 所有的Pascal类型 兼容性规则都适用属性 为属性选择类型的最重要的方面是不同的类型出现在Object Inspector窗口中的方式不同 Object Inspector将按不同的类型决定其出现的方式
你也能在注册部件时描述不同的属性器
下表列出属性出现在Object Inspector窗口中的方式
表 属性出现在Object Inspector窗口中的方式
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
属性类型 处 理 方 式
───────────────────────────────────────
简单类型 Numeric Character和 String属性出现在Object Inspector中 用户可以直接
枚举类型 枚举类型的属性显示值的方式定义在代码中 选择时将出现下拉式列表框 显示所有的可能取值
集合类型 集合类型出现在Object Inspector窗口中时正如一个集合 展开后 用户通过将集合元素设为True或False来选择
对象类型 作为对象的属性本身有属性器 如果对象有自己的published属性 用户在Object Inspector中通过展开对象属性列 可以独立它们 对象类型的属性必须从TPersistent继承
数组类型 数组属性必须有它们自己的属性器 Object Inspector没有内嵌对数组属性的支持
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
公布继承的属性
所有部件都从祖先类型继承属性 当你从已有部件继承时 新部件将继承祖先类型的所有属性 如果你继承的是抽象类 则继承的属性是protected或public 但不是published 如想使用户访问protected或public属性 可以将该属性重定义为published 如果你使用inControl继承 它继承了Ctl D属性 但是protected的 因此用户在设计和运行时不能访问Ctl D 通过在新部件中将Ctl D重声明为published 就改变了Ctl D的访问级别 下面的代码演示如何将Ctl D声明为published 使之在设计时可被访问
type
TSampleComponent=class(inControl)
published
property Ctl D;
end;
定义部件属性
⑴ 属性的声明
声明部件的属性 你要描述
● 属性名
● 属性的类型
● 读和设置属性值的方法
至少 部件属性应当定义在部件对象声明的public部分 这样可以在运行时很方便地从外部访问 为了能在设计时属性 应当将属性在published部分声明 这样属性能自动显示在Object Inspector窗口中 下面是典型的属性声明
type
TYourComponent=class(TComponent)
…
private
FCount: Integer { 内部存储域 }
function GetCount: Integer; { 读方法 }
procedure SetCount(ACount: Integer) { 写方法 }
pubilic
property Count: Integer read GetCount write SetCount;
end;
⑵ 内部数据存储
关于如何存储属性的数据值 Delphi没有特别的规定 通常Delphi部件遵循下列规定
● 属性数据存储在对象的数据域处
● 属性对象域的标识符以F开头 例如定义在TControl中的属性FWidth
● 属性数据的对象域应声明在private部分
后代部件只应使用继承的属性自身 而不能直接访问内部的数据存储
⑶ 直接访问
使属性数据可用的最简单的办法是直接访问 属性声明的read 和write部分描述了怎样不通过调用访问方法来给内部数据域赋值 但一般都用read进行直接访问 而用write进行方法访问 以改变部件的状态
下面的部件声明演示了怎样在属性定义的read 和write部分都采用直接访问
type
TYourComponent=class(TComponent)
…
private { 内部存储是私有 }
FReadOnly: Boolean; { 声明保存属性值的域 }
published { 使属性在设计时可用 }
property ReadOnly: Boolean read FReadOnly write FReadOnly;
end;
⑷ 访问方法
属性的声明语法允许属性声明的read和write部分用访问方法取代对象私有数据域 不管属性是如何实现它的read 和write部分 方法实现应当是private 后代部件只能使用继承的属性访问
① 读方法
属性的读方法是不带参数的函数 并且返回同属性相同类型的值 通常读函数的名字是 Get 后加属性名 例如 属性Count的读方法是GetCount 不带参数的唯一例外是数组属性 如果你不定义read方法 则属性是只写的
② 写方法
属性的写方法总是只带一个参数的过程 参数可以是引用或值 通常过程名是 Set 加属性名 例如 属性Count的写方法名是SetCount 参数的值采用设置属性的新值 因此 写方法需要执行在内部存储数据中写的操作
如果没有声明写方法 那么属性是只读的
通常在设置新值前要检测新值是否与当前值不同
下面是一个简单的整数属性Count的写方法
procedure TMyComponent SetCount( value: Integer)
begin
if value 《》FCount then
begin
FCount := Value;
update;
end;
end;
⑸ 缺省属性值
当声明一个属性 能有选择地声明属性的缺省值 部件属性的缺省值是部件构造方法中的属性值集 例如 当从Component Palette选择某部件置于窗体中时 Delphi通过调用部件构造方法创建部件 并决定部件属性初始值
Delphi使用声明缺省值决定是否将属性值存在DFM文件中 如果不描述缺省值 Delphi将总是保存该属性值 声明缺省值的方法是在属性声明后加default指令 再跟缺省值
当重声明一个属性时 能够描述没有缺省值的属性 如果继承的属性已有一个 则设立没有缺省值的属性的方法是在属性声明后加nodefault指令 如果是第一次声明属性 则没有必要加nodefault指令 因为没有default指令即表示如此
lishixinzhi/Article/program/Delphi/201311/25117DELPHI基础教程:Delphi客户服务器应用开发(三)[3]
GetDatabaseNames方法
声明 procedure GetDatabaseNames(List: TStrings)
GetDatabaseNames方法清除List的内容并将所有BDE别名和应用程序定义的别名的名字写入List
GetDriverNames方法
声明 procedure GetDriverNames(List: TStrings)
GetDriverNames方法清除List中的内容 并将BDE当前安装的驱动程序名写入List
GetDriverParams方法
声明 procedure GetDriverParams(const DriverName: String; List: TStrings)
GetDriverParams方法消除List中的内容 并将名为DriveName驱动程序缺省参数写入List
GetTableNames方法
声明 procedure GetTableNames(const DatabaseName Pattern: Strings;
Extensions SystemTable: Boolean; List: TStrings)
GetTableNames方法消除List中的内容 并将名为DatabaseName的数据库中的所有表的名字写入List Pattern参数将限制表名 对于SQL服务器 将SystemeTables设为True将获取系统表和用户表 对非SQL数据库 将Extensions设为True将在表名中包含扩展名
处理Client/Server事务控制
使用隐式控制和显示控制的数据库应用中有两种方法管理事务控制
● 运用TDatabase部件的属性和方法进行显式控制
● 运用TQuery部件的传递式SQL控制事务
Delphi还支持Paradox和dBASE表的局部事务处理
事务控制概述
当用Delphi创建数据库应用时 Delphi提供了用为所有数据库访问的事务控制
事务是这样一组操作 在被提交前 它们对一个或多个数据库的操作 必须全部执行成功 如果其中一个操作失败 则所有操作失败 即事务具有原子性
即使发生硬件失败 事务也要保证数据库一致性 当允许多用户并发访问时 事务还要维持数据完整性
例如 一个应用程序可能更新ORDERS表以指明接受购买某一项目的定单 那么也要更新INNENTORY表以反映库存的减少 如果在第一个更新之后 第二个更新之前发生硬件错误 数据库就会处于不一致状态 因为库存情况没有反映定单情况 在事务控制下 两个表达式将在同一时间提交 如果其中一个表达式失败 则被返转(Rolled Back)
使用隐式控制
在缺省情况下 Delphi通过BDE为应用程序提供隐式事务控制 当应用程序处于隐式事务控制时Delphi为DataSet中的写每个记录进行隐式事务控制 它提交每一个独立的写操作 如Post和Append Record
使用隐式事务控制是容易的 它保证最小的记录更新冲突和数据库的一致性视图 另一方面 因为写入数据库的数据的每一行都要进行事务控制 所以隐式事务控制将导致网络过忙和应用程序性能下降
如果采用显式事务控制 就能选择最有效的时机来开始 提交和终止事务 特别是在开发多用户环境下的客户应用程序运行访问远程SQL服务器 就更应该采用显式控制
使用显式事务控制
有两种协作又独立的方式可运用于Delphi数据库应用的事务控制
● 使用TDatabase部件的方法和属性
● 使用TQuery部件中的传递式SQL 这种方式只有在Delphi Client/Server Suite版中才有效 SQL Links将SQL表达式直接传给过程SQL或ODBC服务器
使用TDatabase部件的方法和属性的好处是提供了清晰的 轻便的 与特定数据库或服务器无关的应用能力
使用传递式SQL的主要好处在于可以运用特定服务器的先进事务管理能力
使用TDatabase的方法和属性
下表中列出了TDatabase部件中用于事务管理的方法和属性以及它们的使用方法
表 TDatabase用于事务显式控制的方法表
━━━━━━━━━━━━━━━━━━━━━━━━
方法或属性 作 用
────────────────────────
Commit 提交数据的修改并终止事务
Rollback 取消数据的修改并终止事务
StartTransaction 开始一个事务
TransIsolation 表述事务的独立性级别
━━━━━━━━━━━━━━━━━━━━━━━━
StartTransaction Commit和Rollback是供应用程序在运行时调用开始事务 控制事务并且保存或放弃所做数据修改的方法
TransIsolation是TDatabase部件的用于控制作用于相同表的不同事务之间如何交互的属性
⑴ 开始一个事务
当你开始一个事务时 后来的所有读写数据库的表达式都发生在那次事务的环境中 每个表达式都是其中一部分 任何表达式所做的修改 要么成功地提交给数据库 要么每一个修改都被取消 考虑一个在ATM上的银行传输问题 当顾客决定将钱从存款帐户转到支付帐户时 在银行数据库记录上必须发生两个修改
● 存款帐户必须记入借方
● 支付帐户必须记入贷方
如果出于某种原因 其中的一个操作不能被完成 那么任何一个操作都不应该发生 因为这些操作是相关的 它们应该发生在同一个事务中
为了开始Delphi应用程序中的一个事务 需要调用TDatabase部件中的StartTransaction方法
DatabaseInterBase StartTransaction;
此后的所有数据操作都发生在最近一个事务的环境中 直到该次事务通过调用Commit或Rollback显式地终止为止
那么 应当将事务保持多久呢?理想状态下 只要需要 多久都行 事务的活跃状态越长 同时访问数据库的用户越多 在你的事务的生命其中 更多的并发 同时的事务开始和终止 于是当试图提交修改时 与其它事务冲突的可能性更大
⑵ 提交一个事务
为了做永久性修改 事务必须使用TDatabase部件的Commit方法提交 执行提交表达式将保存数据库的修改并终止事务 例如 下列表达式将终止在上例中开始的事务
DatabaseInterBase Commit
Commit的调用应当置于try…except表达式中 如果一个事务不能成功提交 你就能处理错误 并重试操作
⑶ 返转一个事务
为了取消数据库修改 必须用Rollback方法返转一个事务 Rollback 复原一个事务的修改 并终止事务 例如 下列表达式将返转一个事务
DatabaseInterBase Rollback;
Rollback通常发生在
● 异常处理代码
● 按钮或菜单事件代码 如用户点按了Cancel按钮
⑷ 使用TransIsolation属性
TransIsolation属性描述TDatabase部件事务的独立级别 事务的独立级别决定了事务与其它作用于相同表的事务是如何相互作用的 在改变或设置TransIsolation 的值之前 应当相当熟悉Delphi中的事务和事务管理
TransIsolation的缺省值是tiReadCommitted 下表中总结了TransIsolation的可能值并描述了它们的含义
表 TransIsolation属性值的含义
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
独立级别 含 义
──────────────────────────────────────
tiDirtyRead 允许读由其它同时事务写入数据库的未提交的修改 未提交的修改不是永久性的 可能在任何时候被复原 在这个级别你的事务与其它事务所做的修改具有最低独立度
tiReadCommitted 只允许读由其它同时事务提交的数据库修改 这是缺省的独立级别
iRepeatableRead 允许单个的数据库读事务无法看见其它同时事务对相同数据做的修改 这个独立级别保证了你的事务一次读一个记录 记录的视图不会改变 在这个级别你的事务与其它事务做的修改完全独立
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
各种数据库服务器不同程度地支持这些独立级别 有的根本不支持 如果请求的隔离级别不被服务器支持 Delphi将采用更高的独立级别 各种服务器支持的独立级别请参见表
如果应用程序使用ODBC与服务器交互 ODBC驱动程序必须支持独立级别
使用传递式SQL
为了能使用传递式SQL控制事物 必须
● 使用Delphi Client/Server Suite
● 安装正确的SQL Links驱动程序
● 正确配置网络协议
● 访问远程服务器上数据库的能力
● 用BDE配置工具将SQLPASSTHROUGH MODE设置为NOT SHARED
通过传递式SQL 你可以使用TQuery TStoredProc 或TUpdateSQL部件直接发送一个SQL事务控制表达式给远程数据库服务器 BDE本身并不处理SQL表达式 采用传递式SQL可使用户直接获得SQL服务器提供了事务控制优点 尤其是当那些控制是非标准的时
SQL PASS THROUGHMODE 描述BDE和传递式SQL是否共享相同的数据库联接 在大多数情况下 SQLPASSTHROUGHMODE被设置SHARED AUTOMIT 然而 如果你想将SQL事务控制传递给服务器 你就必须用BDE配置工具 将BDE的SQLPASSTHROUGHMODE 设置为NOT SHARED 此外 还必须为传递SQL事务控制表达式的TQuery部件建立独立的TDatabase 部件
使用本地事务
BDE还支持Paradox和dBASE上的本地事务 从代码角度而言 在本地事务和远程数据库服务器的事务之间没有什么差别
当作用于本地数据库表的事务开始时 更新操作被记录在日志中 每个日志记录包含旧的记录缓冲区 当事务处于活跃状态 更新的记录被锁定 直到事务被提交或返转 在返转过程中 旧的记录被应用于将更新的记录恢复到原先的状态
使用存储过程
TStoredProc部件概述
存储过程是以数据库服务器为基础的接受输入参数 并将结果返回给应用程序的一段程序 TStoredProc部件操作远程服务器上的数据库中的存储过程 存储过程是一连串表达式的集合 作为服务器的一部分存储 存储过程在服务器上执行一系列重复性的与数据库相关的任务 并将结果传给客户应用程序 如Delphi数据库应用程序
TStaredProc部件使Delphi数据库应用程序能执行服务器上的存储过程
通常 作用于数据库表中大量记录并且使用统计或数学函数的操作都是存储过程的首选对象 通过将这些重复计算任务转移到服务器 可以提高数据库应用程序的性能
● 充分利用服务器的处理能力和速度
● 减少网络传输的数量
例如 考虑一个需要计算单个值的应用程序 在大批记录中的标准差值 如果在Delphi应用程序中执行这项功能就必须从服务器中得到所有在计算中用到的记录 这必将导致网络拥塞 因为应用程序所需的只是代表标准差的最终返回值 因此 由服务器上的存储过程来读数据 执行计算和将值传给应用程序将更有效
lishixinzhi/Article/program/Delphi/201311/25131![delphi最新版教程(DELPHI基础教程:Delphi自定义部件开发(二)[1])](/static/images/content_image/heart-1192662_1920.jpg)
更多文章:
数据库管理系统和数据库系统分别侧重(数据库,数据库管理系统,数据库系统,这三个分别是什么意思并举个实例)
2026年9月7日 17:00
springmvc的依赖(springMVC的注入方式有哪几种,这与springMVC依赖)
2026年9月7日 14:00
display flex 自动换行(overflow-y:hidden;overflow-x:auto;无效解决方法)
2026年9月7日 11:00
timestamp without time zone(Postgresql中to_date()函数使用问题)
2026年9月7日 09:40






