此份文件的目的为何?
这份文件的目的是为了解答有关撰写 Delphi组件时常见或文件上找不到的问题我曾经花了一段很长的时间来了解探索 TDataLink 类别这让我觉得应该将撰写组件时常遇到的问题及经验心得写下来分享给大家不过我并不能保证写在这份文件里头的解答完全正确如果你对其中的任何问题有更好的解决方法或认为有什么信息适合放在这份文件里的话请告知作者有任何错误或缺漏也欢迎指正
除了再加上更多的问题及解答外我试着再补充两个部分
进阶程序设计师喜爱的工具这也许跟组件设计没有直接的关系但至少它们跟 Delphi有关系
值得参考的文件刊物由于空间的关系这份文件不能放置太多的范例程序因此参考其它文件是十分需要的这不是一份教材式的文件我不会做太多条理式的说明但会试着将最具有参考价值的文献列出
如果你有任何意见或建议欢迎来信告诉我
第二部份 整合环境
在整合环境中如何找出组件所产生的问题?
我发现唯一能找出问题的方法只有
在 Delphi 整合环境的 Tools|Options 对话框的 Library 页中将『Compile with debug info』选项打勾
选 Component|Rebuild Library 重新编译组件库
从 Turbo Debugger 中执行 Delphi
选File|Change Dir移至包含组件程序代码的目录下
如果你的组件发生GPF时就可以检视堆栈然后得知到底是哪些发生问题了
如何检视 Delphi 所产生的汇编语言码?
Glen Boyd 的回答
开启登录编辑程序(REGEDITEXE)接着到『HKEY_CURRENT_USER\Software\Borland\Delphi\\Debugging』下新增一个字符串机码『EnableCPU』将它的字符串值设为『』此后Delphi整合环境的View选单下就会多一个『CPU』选项它会开启一个窗口来检视目前程序指令的内存及汇编语言你可以在侦错时利用单步追蹤或其它方法来观察它
我可以在执行时期动态建立组件但在设计时期就会发生错误为什么?
你的组件必须继承自TComponent类别或其衍生类别
你的组件建构函式及灭构函式宣告必须看起来像这样
constructor Create(AOwner: TComponent); override;
destructor Destroy; override ;
所有在published区段宣告的字段型态必须是ordinalsingledoubleextended compcurrencystringsmall set(译注指元素编号不超过这个范围的集合平常的集合可容许的范围为)method pointer或class其中一种如果你宣告了其它型态的字段Delphi编译器并不会检查出错误然而当你使用这个组件时依然会得到一个GPF
如果你想让TMyComponent组件可以在设计时期操作注意下面的宣告会引发十分严重的问题
type TComplex = record
RealPart: Double;
ComplexPart: Double;
end;
class TMyComponent = Class(TComponent)
private
F: TComplex;
published
property P: TComplex read F write F;
end;
如何撰写一个无法放置到表格上的组件?
Ray Lischner 的回答
如果你不想让使用者将组件拉曳至表格上的话使用 RegisterNoIcon 及 RegisterClass 程序来注册组件
在程序代码编辑器中快速切换程序区段最简单的方法是什么?
Ray Konopka 的回答
在探索 VCL 原始程序代码时强烈建议你最好熟悉程序代码编辑器里的书签功能使用方法很简单CtrlShiftNN 是从 至 的数字用来设定一个书签此后就可以使用 CtrlN 来跳跃至书签处(译注使用这项功能真的可以节省你许多来回卷动程序及找寻函式的时间别迟疑了快学吧!)
如何使我的组件在按下鼠标右键时出现快速功能选单?
你必须要建立一个组件编辑器组件编辑器决定了组件在设计时期时对鼠标键的反应及动作你可以为组件定义它自己的快速功能选单
建立组件编辑器的步骤大致如下
从 TComponentEditor 类别继承一个新的类别
改写类别的 GetVerbCountGetVerb及 ExecuteVerb方法
在 Register 程序中使用 RegisterComponentEditor 程序来注册此组件编辑器
有关组件编辑器这个主题在『Developing Delphi Components』这本书中有详尽的解说及信息
为什么组件在设计时期会出现『I/O 』的错误?
你可能在组件中使用了Writeln这个程序
为什么组件编辑器不会将组件属性的变动储存起来?
我发现有时自制的组件编辑器不会将组件属性储存起来设计时期一切正常但是储存起来再重新读入后就有问题了
原因是你很可能忘了在组件编辑器中呼叫此方法
DesignerModified;
如此一来Delphi才会知道你的组件编辑器更改过属性值了
第三部分在组件中使用其它组件
如何在组件中加入滚动条组件并让它在设计时期能动作?
你的滚动条组件类别必须处理 CM_DESIGNHITTEST 组件讯息才行
TMyScrollBar = class (TScrollBar)
procedure CMDesignHitTest
(var Message: TCMDesignHitTest); message CM_DESIGNHITTEST;
end;
procedure TMyScrollBarCMDesignHitTest( var Message: TCMDesignHitTest);
begin
MessageResult := ;
end;
你的组件必须以以下方法建立滚动条
TMyScrollBarCreate(nil);
而不是
TMyScrollBarCreate(Self);
如何建立Windows式样的滚动条?
你必须设定滚动条的页面大小你可以用以下的程序代码来做
procedure SetPageSize(ScrollBar: TScrollBar; PageSize: Integer);
var
ScrollInfo: TScrollInfo;
begin
ScrollInfocbSize := Sizeof (ScrollInfo);
ScrollInfofMask := SIF_PAGE;
ScrollInfonPage := PageSize;
SetScrollInfo (ScrollBarHandle SB_CTL ScrollInfo True);
end;
要取得目前页面大小可用如下方法
function GetpageSize (ScrollBar: TScrollBar): Integer;
var
ScrollInfo: TScrollInfo;
begin
if HandleAllocated then
begin
ScrollInfocbSize := SizeOf (ScrollInfo);
ScrollInfofMask := SIF_PAGE;
GetScrollInfo (ScrollBarHandle SB_CTL ScrollInfo);
Result := ScrollInfonPage;
end;
end;
第四部分 Bound Controls
哪里可以找得到有关 TDataLink 类别的说明文件?
我可以大胆地说全世界有关 TDataLink 的说明文件只有一份就在这儿
属性 (Property) 介绍
property Active: Boolean(只读)
当此 DataLink 连结至一个已开启的 DataSource 时会传回 True当 Active 状态改变时会 触发ActiveChanged方法
property ActiveRecord: Integer(可擦写)
用来设定或取得 DataLink 缓沖区中目前所指向的记录代码代码的范围是 BufferCount 使用它来设定记录代码时必须小心不要超过这个范围否则可能导致不可预期的错误
property BufferCount: Integer(可擦写)
DataLink 拥有一个资料缓沖区而 BufferCount 属性即用来设定或取得缓沖区大小缓沖区大小决定了一个dataset同时可以显视的资料记录笔数对大部分的资料感知组件来说BufferCount 的值是 但对 TDataGrid 来说BufferCount 代表它的可视列数目
property DataSet: TDataSet(只读)
传回此 DataLink 所连结的 DataSet其实就是 DataSourceDataSet
property DataSource: TDataSource(可擦写)
传回此DataLink所连结的DataSource
property DataSourceFixed: Boolean(可擦写)
这个属性可用来防止 DataSource 属性被更改如果此属性设为 True当我们试着改变 DataSource 属性时会引发一个例外
property Editing: Boolean(只读)
如果 DataLink 正处于编辑状态则传回 True
property ReadOnly: Boolean(可擦写)
设定 DataLink 是否为只读状态这个属性并不会影响所连结的 DataSet在只读状态下这个 DataLink 无法进入编辑状态
property RecordCount: Integer(只读)
传回DataSet的资料记录数目
方法 (Method) 介绍
function Edit: Boolean;
让所连结的DataSet进入编辑状态传回值 成功传回 True 失败传回 False
procedure UpdateRecord;
我们不直接呼叫这个方法它是提供其它程序来呼叫的这个方法只有设定一个旗帜然后呼叫 UpdateData 方法
虚拟方法 ( Virtual Method )
要让 TDataLink 对象与组件沟通必须改写下列这些方法
procedure ActiveChanged
当连结的 DataSource 开启状态改变时会呼叫此方法使用 Active 属性可以得知目前是否为开启状态
procedure CheckBrowseMode
数据库有任何改变之后都会先呼叫这个方法
procedure DataSetChanged;
当下列任一事件发生时都会呼叫此方法
移至DataSet的开头
移至DataSet的结尾
在DataSet中插入或新增资料
删除DataSet的资料
取消DataSet的编辑
更新记录
如果不想改写这个方法只要在其中呼叫