一、基础知识简介:

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类似的数据感知控件)的更多相关文章

  1. 如何用Apache POI操作Excel文件-----如何在已有的Excel文件中插入一行新的数据?

    在POI的第一节入门中,我们提供了两个简单的例子,一个是如何用Apache POI新建一个工作薄,另外一个例子是,如果用Apache POI新建一个工作表.那么在这个章节里面,我将会给大家演示一下,如 ...

  2. 使用Apache POI操作Excel文件---在已有的Excel文件中插入一行新的数据

    package org.test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundEx ...

  3. 从文件中读取yuv和h264数据

    1.从文件中读取h264数据 参考ffmpeg avc.c写的从文件中一帧帧读取h.264数据的demo #include <stdio.h> #include <stdlib.h& ...

  4. linux下向一个文件中的某行插入数据的做法

    sed -i 'ni\x' test.file        表示向test.file文件里的第n行的前面添加x内容sed -i 'na\x' test.file       表示向test.file ...

  5. 使用jmeter往指定文件中插入一定数量的数据

    有一个需求,新建一批账号,把获取的账号相关信息存入文本文件,当文本文件保存的数据达到一定的数量,就自动停止新建账号. 分析下需求: 1.把账号信息保存到文件,需要使用bean shell脚本(bean ...

  6. java web 通过前台输入的数据(name-value)保存到后台 xml文件中

    一:项目需求,前端有一个页面,页面中可以手动输入一些参数数据,通过点击前端的按钮,使输入的数据保存到后台生成的.xml文件中 二:我在前端使用的是easyui的propertygrid,这个能通过da ...

  7. 使用jmeter往指定文件中插入一定数量的数据(转)

    有一个需求,新建一批账号,把获取的账号相关信息存入文本文件,当文本文件保存的数据达到一定的数量,就自动停止新建账号. 分析下需求: 1.把账号信息保存到文件,需要使用bean shell脚本(bean ...

  8. Jmeter beanshell把数据写入csv文件中,最后清除csv数据

    有时候我们需要使用jmeter去结合csv文件去做一些简单的数据驱动处理: 例如把数据库数据黏贴到csv文件中或者把网页上的数据填入到csv文件中: 直接我一般是用手自己黏贴复制过csv文件中,比较麻 ...

  9. Elasticsearch准实时索引实现(数据写入到es分片并存储到文件中的过程)

    溢写到文件系统缓存 当数据写入到ES分片时,会首先写入到内存中,然后通过内存的buffer生成一个segment,并刷到文件系统缓存中,数据可以被检索(注意不是直接刷到磁盘) ES中默认1秒,refr ...

随机推荐

  1. golang for循环里面创建协程问题的研究

    原本想在一个for里面创建10个协程,这些协程顺序拿到for的递增变量,把这10个递增变量都打印出来.但事与愿违,于是做实验,查书,思考,写出以下记录. golang里,在for循环里面起协程,如下代 ...

  2. 引用ZXing生成二维码

    1.生成二维码 ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口. Zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码.本文引用 ...

  3. 如何在同一个Excel里,对两个很相似的工作簿比对出不同之处

    如何在同一个Excel里,对两个很相似的工作簿比对出不同之处

  4. 20154327 Exp5 MSF基础应用

    基础问题回答 用自己的话解释什么是exploit,payload,encode. exploit漏洞利用,一般出现漏洞后,根据一些大佬们给出的POC尝试去进行漏洞利用. payload攻击负载,是我们 ...

  5. 北京Uber优步司机奖励政策(1月12日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  6. 成都Uber优步司机奖励政策(2月1日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  7. CC3200-LAUNCHXL仿真器驱动异常(未完成)

    1. 测试中发现,跳线帽J2和J3连接的情况下,驱动不正常如图2,不连接的情况下,驱动正常,VCC_LDO_3V3给仿真器FT2232供电,VCC_BRD这个电源很奇怪,用途不清晰,VBAT_CC是给 ...

  8. 笔记:ndk-stack和addr2line

    笔记:关于ndk开发调试时,获取崩溃堆栈方法 1. 使用ndk-stack 直接获取c/c++崩溃代码的文件名和行号 adb shell logcat | ndk-stack -sym $PROJEC ...

  9. c# enum 解析

    解析定义的枚举 public enum OrderPaymentStatus { /// <summary> /// 未支付 /// </summary> [Descripti ...

  10. java 浅复制 深复制

    1.浅复制 只是复制引用,对引用的操作会影响之前复制的对象. 2.深复制 复制一个完全独立的对象,复制对象与被复制对象相互之间不影响. 只是概念性东西....