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;
可以手动执行跟踪一遍,加深印象~