虚函数的特点就是执行的时候会下降到子类去执行同名覆盖函数 good

var
t: TBitBtn;
begin
t:=TBitBtn.Create(nil);
t.Name:='BitBtn100';
t.parent :=Self; // 这里下断点
end;

一路跟踪就会发现到TWinControl.UpdateShowing函数,它发现当前控件尚未有句柄,因此会调用CreateHandle,然后就有了这些虚函数的系列旅程,会执行子类覆盖函数:

TBitBtn.CreateHandle; // 在TWinControl.UpdateShowing里调用CreateHandle的时候,会下降到这里来
TButton.CreateWnd;    // 在TWinControl.CreateHandle里调用CreateWnd的时候,会下降到这里来
TBitBtn.CreateParams  // 在TWinControl.CreateWnd里调用CreateParams的时候,会下降到这里来

但是子类通常不会放弃父类已经提供的功能,全都是在父类函数执行前或者执行后的结果上增加一小部分特性,形成三明治风格。

干脆,我们看看TBitBtn增加些什么东西:

procedure TBitBtn.CreateHandle; var
State: TButtonState;
begin
if Enabled then // 增加按钮的状态
State := bsUp
else
State := bsDisabled;
inherited CreateHandle; // 三明治风格
TButtonGlyph(FGlyph).CreateButtonGlyph(State); // 增加按钮的图像
end;

procedure TButton.CreateWnd;
begin
inherited CreateWnd;
FActive := FDefault; // 增加判断是否处于激活状态
end;

procedure TBitBtn.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do Style := Style or BS_OWNERDRAW; // 增加自绘状态
end;

可以手动执行跟踪一遍,加深印象~

posted @ 2014-09-14 04:41  findumars  Views(565)  Comments(0)    收藏  举报