★★★★★★★★谈谈我对VCL源码分析方法的一点体会,欢迎大家进来看看,并发表自己的心得和看法!★★★★★★★★

Billy_Chen28 2003-11-12 09:24:59

最近一段时间似乎流行源码分析:)我也来谈谈在过去一段时间里对VCL源码的分析方法方面的一点体会,本文将不探讨VCL类库的构架和设计模式方面的东本,只是以我们常见的控件属性/方法的实现过程作简单的说明,希望对初学者有所帮助

VCL分析方法
例:TButton.Caption属性的由来
(本文仅以此献给DELPHI初学者)
用过一段时间DELPHI的朋友,都会对VCL源码感兴趣。本人也常常在各大论坛见到一些网友研究讨论过关于VCL源码的贴子。不过,很多网友很努力的想看懂,可最后还是半途而废,因为他们总是理不出个头绪、看得云里雾里。笔者我也有看源码的习惯,没事的时候就点点鼠标右键,总是希望得到一些侥幸的收获和开发技巧。
不过万事都得先有个基本前题,就像人上学的过程一样(这里指正常人)要按部就班的来,一般不可能小学一毕业就直接去念大学,除非他(她)是个天才或经过特别培训。所以各位GGJJDDMM,看VCL源码也是有个基本前题的,首先你得熟悉WIN32 API/SDK,如果你说不知道的话,可以参考书籍《Programming Windows》(中文名《WINDOWS 程序设计》)。其次是你应当对Object Pascal比较熟悉,或者你曾经对DELPHI的组件进行过扩展(做过组件开发),那么我相信你对Object Pascal已经熟悉。不熟也不要紧,DELPHI的在线帮助就有对Object Pascal的讲述,如果英文太差也不要紧,网上也有很多热心网友翻译过来的中文帮助和语言参考书。
呵呵,本人写技术文章就像在写散文:)
言归正传,我们这篇文章的主题是对VCL源码的分析,分析当然有一个分析方法的问题,总不能随便打开一个源程序,逮着一个函数就分析一个函数吧:)所以我们也应该有选择,有目的的分析。
想想我们每天编码时都会遇到的属性有哪些?呵呵,NAME,CAPTION,VISIBLE,还有一些控件的TEXT(如EDIT1.TEXT)。那么我们就以控件的CAPTION来分析吧。
当然不是每个控件都有CAPTION属性的,我们这里就用TButton类的Caption属性进行分析。
打开每天我们都会使用的DELPHI,在FORM窗体上放一个按钮,得到一个Button1的按钮控件,按F12打天源程序,有没有找到这段代码呢:
Button1: TButton;
对了,在TButton上点击鼠标右键,在弹出的上下文菜单中选择第一项Find Declaration,找到TButton类的定义,如下所示:
TButton = class(TButtonControl)
private
FDefault: Boolean;
FCancel: Boolean;
FActive: Boolean;
FModalResult: TModalResult;
procedure SetDefault(Value: Boolean);
。。。。。。

原来TButton继承于TButtonControl类,呵呵:)
在左边的对象窗口(Exploring Unit.pas窗口)中找到TButton的CAPTION属性,如下图:

双击CAPTION属性,找到定义CAPTION属性的源码,大家可能发现什么都没有,只有一个
property Caption;
呵呵,写过组件的朋友都知道,按理Caption属性应该有读/写文本的方法啊?在哪里去了呢,呵呵,这里没有出现,当然应该在它的父类里了(这里只是申明Caption出来的地方),我们顺着刚才的方法继续在TButtonControl,发现也没有,最终我们在TControl类里找到了这个CAPTION,至于为什么是protected成员,我就不多说了:
protected
procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); dynamic;
procedure AdjustSize; dynamic;
procedure AssignTo(Dest: TPersistent); override;
procedure BeginAutoDrag; dynamic;
function CanResize(var NewWidth, NewHeight: Integer): Boolean; virtual;
function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; virtual;
procedure Changed;
procedure ChangeScale(M, D: Integer); dynamic;
。。。。。。
property Caption: TCaption read GetText write SetText stored IsCaptionStored;
看看GetText、SetText就是操作文本属性的函数了,我们找到GetText、SetText定义如下:
function GetText: TCaption;
procedure SetText(const Value: TCaption);
还有TCaption,它的定义居然是一个自定义类型:
TCaption = type string;
说明GetText返回值和SetText的调用参数本来也就是一个string型的:)

下面我们来看看GetText源码:
function TControl.GetText: TCaption;
var
Len: Integer;
begin
Len := GetTextLen;//得到文本长度
SetString(Result, PChar(nil), Len);// 设置Result返回以Len指定的长度
if Len <> 0 then GetTextBuf(Pointer(Result), Len + 1);//长度不为空,Result得到文本数据
end;

如果不明白GetTextBuf的用法,看看如下的代码:
procedure TForm1.Button1Click(Sender: TObject);
var
Buffer: PChar;
Size: Byte;
begin
Size := Edit1.GetTextLen; //得到EDIT1的文本长
Inc(Size);
GetMem(Buffer, Size); //创建EDIT1文本长度大小的缓存空间
Edit1.GetTextBuf(Buffer,Size); //由缓存得到文本,Buffer里的值就是Edit1.Text
Edit2.Text := StrPas(Buffer); //Buffer转换为PASCAL字符类型数据
FreeMem(Buffer, Size); //释放内存
end;
以上程序的行为同以下程序相当:
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit2.Text := Edit1.Text;
end;

回到GetText函数,其中GetTextLen的作用是得到文本长度,GetTextBuf得到文本数据。
SetText就更简单了,定义如下:
procedure TControl.SetText(const Value: TCaption);
begin
if GetText <> Value then SetTextBuf(PChar(Value));
end;
意思是如果设定的Value与原来的不同,则重新设置缓存文本。


...全文
211 245 打赏 收藏 转发到动态 举报
写回复
用AI写文章
245 条回复
切换为时间正序
请发表友善的回复…
发表回复
Seahilly 2003-11-29
  • 打赏
  • 举报
回复
好贴,收藏。
linzhisong 2003-11-29
  • 打赏
  • 举报
回复
汗,勉强看懂,

还得努力努力,再努力!


ly_liuyang 2003-11-28
  • 打赏
  • 举报
回复
热闹,这么多人研究VCL消息机制

不过看到就头疼,我认为去VCL研究没有什么价值的,又不是自己做编译器,开发FrameWork
即使VCL不够完善,你也没有办法修改的
了解一下,知道是怎么一回事就算数了

我写过一大队VCL组件,从没有深入研究VCL机制,正如Delphi所说的TObject是内置对象,没办法的了解真正的核心,Borland可不会公开编译器的技术和代码的

http://lysoft,7u7,net
haohaisen 2003-11-28
  • 打赏
  • 举报
回复
很有帮助
myling 2003-11-28
  • 打赏
  • 举报
回复
呵呵,已经变成水贴了
cpilq 2003-11-28
  • 打赏
  • 举报
回复
不错!顶啊!
ptzld 2003-11-28
  • 打赏
  • 举报
回复
分一多人就多
无奈灌水!
灌水无奈!
codehunter008 2003-11-27
  • 打赏
  • 举报
回复
好帖啊,学习!
da_yu 2003-11-27
  • 打赏
  • 举报
回复
up
findcsdn 2003-11-27
  • 打赏
  • 举报
回复
好贴呀!一下子解决了我好多的疑惑哦。
总结一下收获:
1。终于搞明白了vcl的消息机制和window的消息机制是两个并不完全相同的东西,当然这也就是为什么tobject就设置dispatch的原因。对于使用[消息-函数]表的方法派发消息应该很快的,因为对于几个百个消息的列表来说,七八个时钟周期内就可以完成查找派发了,应该很高效的。

2。加强了virtual的理解,大致搞清楚了虚拟函数的处理机制。每个类都配有独立的各个虚拟函数地址的对应表,调用虚拟函数的时候不需要查找祖先类的虚拟函数表,就可以确定函数的地址,也就是说如果虚拟函数没有重载,那么表中存储的是祖先类的函数地址,如果函数被重载了那么表中存储的就是新的函数地址。这些虚拟函数一经定义,那么在任何派生类的虚拟函数表中的偏移地址应该是固定的,永远不会变。

这是我的理解,如果错了,请高人指点。

saien 2003-11-25
  • 打赏
  • 举报
回复
cqzyf 2003-11-25
  • 打赏
  • 举报
回复
好,顶
anydeng 2003-11-24
  • 打赏
  • 举报
回复
不错,确实不错。我看VCL原代码简直就是一头雾水,哎,还得多向你们学习呀。顶…………
猛禽 2003-11-24
  • 打赏
  • 举报
回复
TO:cjc861(老七)
在WIN平台下开发不包装API包装什么?
问题在于VCL的思想很好,至少同样是包装,VCL比MFC好得多。
yxzzjg 2003-11-24
  • 打赏
  • 举报
回复
mark
tiger19760407 2003-11-24
  • 打赏
  • 举报
回复
好,学习!
tomboy0 2003-11-24
  • 打赏
  • 举报
回复
好贴,留个记号!来学习
wilcox1937 2003-11-24
  • 打赏
  • 举报
回复
很有帮助,赞
subsky 2003-11-24
  • 打赏
  • 举报
回复
?
reallike 2003-11-24
  • 打赏
  • 举报
回复
短歌兄还是玩排序吧。:〉
加载更多回复(225)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧