一、基础知识简介:
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;
1、在创建新包dpk或者选择已经存在的包之后,点击【Ok】之后会出现安装【dpk文件对话框】,按其中的【Compile】就可以检查你编写的代码是否存在错误,但不能检测逻辑错误。
2、【Project】—>【Build XXX】也能检测代码中的错误。但是直接打开Pas文件,这个按钮不可用。可以先点击打开其所在的dpk,然后打开pas文件, 但不能检测逻辑错误.
3、安装完自定义控件后,在自定义控件的Pas中修改代码,会直接影响到调用他的程序中,所以可以直接在自定义控件的Pas文件中设置断点,进入调试, 可以检测逻辑错误;
4、在自定义控件的Pas文件中,添加的新属性、事件。在应用程序中能通过代码直接调用,但是在对象监控器【Object Inspector】中不会显示,只能重新加载自定义控件,才能显示。
第一种方法:
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,和它所处的包。
好的代码像粥一样,都是用时间熬出来的
转自:https://www.cnblogs.com/jijm123/p/10195511.htmlDelphi 制作自定义数据感知控件并装入包(dpk文件)中(与DBText类似的数据感知控件) - 癫狂编程 - 博客园