Delphi 制作自定义数据感知控件并装入包(dpk文件)中(与DBText类似的数据感知控件)
一、基础知识简介:
1、包的命名介绍:
包的命名没有规则,但是建议遵守包的命名约定:包的命名与包的版本相关,包的名称前面几个字符通常表示作者或公司名,也可以是控件的一个描述词,后面紧跟的Std表示运行期包,Dsgn表示设计期包,然后是版本号。如:MyDataEditStd60,MyDataEditDsgn60。
2、对象浏览器【Object Inspector】中一个属性感知一类控件的原理:
控件属性的感知只不过是将它的一个属性声明为将要感知的控件类而已,例如要感知Image控件,则:property MyImage:TImage read GetImage write SetImage;这样之后,窗体中的所有的TImage类型的控件,它都能感知到。
3、数据感知控件与其他相关控件进行交互的方法:
数据感知控件通过DataLink对象与DataSource进行交互,所以为控件增加数据感知能力需要创建一个TDataLink(或其派生类)对象作为控件的成员,并为控件创建公开的DataField和DataSource属性;然后需响应TDataLink对象的OnDataChange和OnUpdateData事件。
我们用到了一个重要的类TFieldDataLink。它是控件内部的数据联接对象,从TDataLink继承下来,它的作用是与TDataSource组件相互通信,连接单个字段进行数据提取。我们将要处理这个对象的OnDataChange事件,这样,当字段或记录有所改变时就会得到通知,进行相应的数据处理。
4、当其中一个控件被删除或者断开时,通知其他控件的通知函数:
感知组件需要和DataSource数据源控件和DataSet数据集控件相组合才能实现数据库数据的读写,那么当删除其中一个时,如果其他两个控件不知道,就会出现异常,甚至导致死机。那么我们怎样才能做到通知其他组件呢?Value.FreeNotification(Self)就是做这个工作的!FreeNotification(self)将会把我们的组件置入其通知对象列表中,被撤消时,它会依次调用通知对象列表中所有对象的Notification方法。每个数据控件都有一个Notification方法,当某一控件从窗体上移走时,DELPHI的IDE调用该方法通知其它控件。
二、制作数据感知控件的具体步骤:
本文以制作一个类似于DBEdit的控件为例。
1、 创建组件,并安装在新包中。
1>、首先使用组件向导从TEdit(StdCtrls)下继承下来,命名TMyDataBaseEdit,单元名为MyDataBaseEdit.pas,
2>、安装在一个新的包文件中,起名为MyDataEditStd60.Dpk。 (此种不需要dpr工程)
(【Delphi 编写Pas文件类型的组件】 中的 【二、制作一个简单的组件基本步骤】 有介绍)
2、 添加属性。
1>、声明一个内部数据连接对象:TfieldDataLink,用于与TDataSource进行通信。
在Private中添加代码: FDataLink: TFieldDataLink; // Uses DBCtrls;
2>、添加数据源感知属性:DataSource 和字段感知属性:DataField ;其值就显示Text中,处理事件是DataChange
和UpdateData。
只需在Pubished域添加以下代码:
property DataSource: TDataSource read GetDataSource write SetDataSource;// Uses DB:
property DataField: string read GetDataField write SetDataField;
3>、按下【shift +ctrl+ C】组合键完成属性的自动结构化功能,
private域自动添加四个函数:
procedure SetDataSource(const Value: TDataSource);
function GetDataSource: TDataSource;
procedure SetDataField(const Value: string);
function GetDataField: string;
4>、上面四个函数的实现方法:
function TMyDataBaseEdit.GetDataSource: TDataSource;
begin
Result := FDataLink.DataSource;
end;
procedure TMyDataBaseEdit.SetDataSource(const Value: TDataSource);
begin
if not(FDataLink.DataSourceFixed and (csLoading in ComponentState)) then
begin
FDataLink.DataSource := Value;
end;
if Value <> nil then
begin
// 将会把我们的组件置入其通知对象列表中,被撤消时,它会依次调用通知对象列表
// 中所有对象的Notification方法,
Value.FreeNotification(Self);
end;
end;
function TMyDataBaseEdit.GetDataField: string;
begin
Result := FDataLink.FieldName;
end;
procedure TMyDataBaseEdit.SetDataField(const Value: string);
begin
FDataLink.FieldName := value;
end;
3、 添加方法:
1>、实现通知函数(必须的)。
当某一控件从窗体上移走时,DELPHI的IDE调用该方法通知其它控件。这样,当关联的参考控件被删除时,控件就会得到消息,来处理事件,防止异常的发生,否则将会导致Delphi开发环境的不稳定甚至死机。
在protected中添加代码:
procedure Notification(AComponent: TComponent;Operation: TOperation);override;
添加实现的代码:
procedure TMyDataBaseEdit.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
// 当与控件相连的TdataSource控件被删除时将控件的DataSource属性置为空
if (Operation = opRemove) and (FDataLink <> nil) and (AComponent = DataSource) then
DataSource := nil;
end;
2>、实现数据处理过程
当DataSet的记录改变(如在DBGrid中滑动滚轮的浏览记录)时触发OnDataChange事件,DataChange作为该事件的事件处理句柄。
在Private中添加代码:
procedure DataChange(Sender: TObject);
添加实现的代码:
procedure TMyDataBaseEdit.DataChange(Sender: TObject);
begin
//若控件连接了的DataSet,则数据集变动时控件显示当前记录的相应字段值
if FDataLink.Field <> nil then
begin
Text := FDataLink.Field.Text;
end;
end;
3>、实现数据更新过程:
更新DataSet前将触发OnUpdateData事件,UpdateData将作为该事件的事件处理句柄;
在Private中添加代码:
procedure UpdateData(Sender: TObject);
添加实现的代码:
procedure TMyDataBaseEdit.UpdateData(Sender: TObject);
begin
// 用控件中的Text更新到相应的字段
FDataLink.Field.Text := Text;
end;
4>、实现控件失去焦点时的消息处理函数:
当控件失去焦点时触发CM_EXIT消息
在private中添加代码:
procedure CMExit(var Message: TCMExit);Message CM_Exit;
添加实现的代码:
procedure TMyDataBaseEdit.CMExit(var Message: TCMExit);
begin
try
// 控件失去焦点时更新DataSet,这将触发OnUpdateData事件
FDataLink.UpdateRecord;
except
setFocus;
//这里是将发生的异常显现出来。因为用了try except end后就不会显示出异常和错误。
raise;
end;
DoExit;
end;
5>、重新编写构造函数:
在构造函数中创建DataLink对象,连接OnDataChange、OnUpdateData事件处理句柄。
在public中添加代码:
constructor Create(AOwner: TComponent);Override;
添加实现的代码:
constructor TMyDataBaseEdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner); //必须加上这句话;
//创建DataLink对象,连接OnDataChange、OnUpdateData事件处理句柄
FDataLink := TFieldDataLink.Create;
FDataLink.OnDataChange := DataChange;
FDataLink.OnUpdateData := UpdateData;
end;
6>、重新编写析构函数:
在析构函数中销毁DataLink对象,并释放对OnDataChange、OnUpdateData事件的连接。确保使用完之后销毁FDataLink的实例,释放空间,无论是写组件还是写程序我们都要严格注意声明的对象,一定要在使用完之后释放!
在public中添加代码:
destructor Destroy;override;
添加实现的代码:
destructor TMyDataBaseEdit.Destroy;
begin
FDataLink.OnDataChange := nil;
FDataLink.OnUpdateData := nil;
FreeAndNil(FDataLink);
Inherited ;
end;
三、DPK文件类型(包)的调试
1、在创建新包dpk或者选择已经存在的包之后,点击【Ok】之后会出现安装【dpk文件对话框】,按其中的【Compile】就可以检查你编写的代码是否存在错误,但不能检测逻辑错误。
2、【Project】—>【Build XXX】也能检测代码中的错误。但是直接打开Pas文件,这个按钮不可用。可以先点击打开其所在的dpk,然后打开pas文件, 但不能检测逻辑错误.
3、安装完自定义控件后,在自定义控件的Pas中修改代码,会直接影响到调用他的程序中,所以可以直接在自定义控件的Pas文件中设置断点,进入调试, 可以检测逻辑错误;
4、在自定义控件的Pas文件中,添加的新属性、事件。在应用程序中能通过代码直接调用,但是在对象监控器【Object Inspector】中不会显示,只能重新加载自定义控件,才能显示。
四、安装dpk文件类型的组件:
第一种方法:
1、【File】-> 【Open Project】命令,然后在对话框中选择文件类型为【*.dpk;*.dpkw】的文件;
2、然后【打开】,会出现【dpk文件对话框】,点击【Compile】—>【Install】,进行安装.。
第二种方法:
1、直接在dpk文件上双击,就会出现【dpk文件对话框】,点击【Compile】—>【Install】,进行安装.。
五、删除控件:
1、【Component】—>【Install Packages】,出现一个对话框。
2、然后在【Designs Packages】 中找到当前包相对应的同名bpl文件。
3、然后【Edit】->【Yes】,打开【dpk文件对话框】,然后选择对应的文件,点击【Remove】删除。
然后再编译安装。
(也可以直接找到相应的DPK文件,双击进入【dpk文件对话框】,一般默认在lib下)
查看组件所属的包:
在【组件面板】上相应的组件上【右击】—>【Properties】,然后打开对话框,可以在【Palette】中,右侧栏中看【Components】中看到name,和它所处的包。
Delphi 制作自定义数据感知控件并装入包(dpk文件)中(与DBText类似的数据感知控件)的更多相关文章
- 如何用Apache POI操作Excel文件-----如何在已有的Excel文件中插入一行新的数据?
在POI的第一节入门中,我们提供了两个简单的例子,一个是如何用Apache POI新建一个工作薄,另外一个例子是,如果用Apache POI新建一个工作表.那么在这个章节里面,我将会给大家演示一下,如 ...
- 使用Apache POI操作Excel文件---在已有的Excel文件中插入一行新的数据
package org.test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundEx ...
- 从文件中读取yuv和h264数据
1.从文件中读取h264数据 参考ffmpeg avc.c写的从文件中一帧帧读取h.264数据的demo #include <stdio.h> #include <stdlib.h& ...
- linux下向一个文件中的某行插入数据的做法
sed -i 'ni\x' test.file 表示向test.file文件里的第n行的前面添加x内容sed -i 'na\x' test.file 表示向test.file ...
- 使用jmeter往指定文件中插入一定数量的数据
有一个需求,新建一批账号,把获取的账号相关信息存入文本文件,当文本文件保存的数据达到一定的数量,就自动停止新建账号. 分析下需求: 1.把账号信息保存到文件,需要使用bean shell脚本(bean ...
- java web 通过前台输入的数据(name-value)保存到后台 xml文件中
一:项目需求,前端有一个页面,页面中可以手动输入一些参数数据,通过点击前端的按钮,使输入的数据保存到后台生成的.xml文件中 二:我在前端使用的是easyui的propertygrid,这个能通过da ...
- 使用jmeter往指定文件中插入一定数量的数据(转)
有一个需求,新建一批账号,把获取的账号相关信息存入文本文件,当文本文件保存的数据达到一定的数量,就自动停止新建账号. 分析下需求: 1.把账号信息保存到文件,需要使用bean shell脚本(bean ...
- Jmeter beanshell把数据写入csv文件中,最后清除csv数据
有时候我们需要使用jmeter去结合csv文件去做一些简单的数据驱动处理: 例如把数据库数据黏贴到csv文件中或者把网页上的数据填入到csv文件中: 直接我一般是用手自己黏贴复制过csv文件中,比较麻 ...
- Elasticsearch准实时索引实现(数据写入到es分片并存储到文件中的过程)
溢写到文件系统缓存 当数据写入到ES分片时,会首先写入到内存中,然后通过内存的buffer生成一个segment,并刷到文件系统缓存中,数据可以被检索(注意不是直接刷到磁盘) ES中默认1秒,refr ...
随机推荐
- 【原创】Odoo开发文档学习之:构建接口扩展(Building Interface Extensions)(边Google翻译边学习)
构建接口扩展(Building Interface Extensions) 本指南是关于为Odoo的web客户创建模块. 要创建有Odoo的网站,请参见建立网站;要添加业务功能或扩展Odoo的现有业务 ...
- 北京Uber优步司机奖励政策(2月2日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- html中iframe根据子页面内容动态修改高度
JavaScript var browserVersion = window.navigator.userAgent.toUpperCase(); var isOpera = browserVersi ...
- 6 线程threading
1.第1种方式:threading模块 1)单线程执行 #-*- coding:utf-8 -*- import time def main(): print("我错了...") ...
- CakePHP 总结
1. 处理任何保存或获取数据的操作最好都写在模型(Model)中.这个概念通常被称为fat model. 2. 返回上一条插入记录的ID, $this->Example->getInser ...
- “网易有钱”sketch使用分享
本文来自网易云社区 写在开头,关于ps与sketch之间的优劣网上已经有很多分享,大家有兴趣可以百度,其中对否我们在这里不予评价.在移动互联网时代每个app从几十到上百张页面,如果用ps绘制一个个页面 ...
- Ruby 基础教程1-6
1.循环实现方法 循环语句 (while;for; loop,until) 循环方法(times,each) 2.for for 变量 in 对象 主体 ...
- WEB安全--高级sql注入,爆错注入,布尔盲注,时间盲注
1.爆错注入 什么情况想能使用报错注入------------页面返回连接错误信息 常用函数 updatexml()if...floorextractvalue updatexml(,concat() ...
- 创建一个socket服务实时统计在线人数
主要是两个文件,一个是后端文件,一个是前端文件: 后端文件:有人登录了,就通知所有的正在访问的页面,把总人数+1:反之-1: 前端文件:有人登录了,通知后端,页面关闭了,通知后端,同时接收后端派发来的 ...
- * 197. Permutation Index【LintCode by java】
Description Given a permutation which contains no repeated number, find its index in all the permuta ...