还记得在第二章的时候,我用到了procedure CreateParams(var Params: TCreateParams);这个函数的吧!为什么我会使用这个函数来实现那个对齐的问题呢!现在就来追根底的来看看!这个过程其实是在构建窗口的时候会调用的,当然我说的这个是针对TWincontrol继承过来的组件说的,从TGraphicontrol等继承过来的是没有这个的。这个函数的产生也是Windows组件库所特有的,如果列为看官有Windows编程的基础,那么这个就很容易理解了,记得,在Windows编程的时,注册这个窗口类之前,我们都会为一个窗口类指定一系列的参数,而这个CreateParams函数就是产生在这个注册过程之前,目的是用来为创建过程指定参数。
在讲CreateParams的来源之前,我们必须简略说说组件由生成到显示在用户面前的这个过程。这是个灰常纠结的问题,纠结到我不晓得怎么去说(当然纠结的主要原因还是本人的水平有限,下面大家就简单看看吧,解说可能有错,欢迎指正)。由于组件都是依托于Form之上的,所以组件要显示出来最首要的是要组件所依托的容器显示出来,那么最首要,我们需要看看Form的创建然后显示出来的过程。至于窗口的创建过程可以参考一下黄叉叉的博客,在这里我在给他的细化一下,便于我们的工作的展开!这个细化应该是在他那个说明的第5步之前,也就是他说的
此处说明一下:
|
对 TWinControl 的 Handle 属性的读取会触发 TWinControl . GetHandle;
|
|
可以察看 Property Handle; 的声明。 |
|
|
5 、第四步中对 Handle 进行读取,触发下述序列:(TWinControl) |
|
Handle->GetHandle->HandleNeeded |
|
这个HandleNeeded是在什么时候第一次调用的,其实他不是在GetHandle的时候第一次调用的,而是在窗口显示出来之前,也就是Visible变化的过程中第一次调用的,而这个Visible的变化,是在Delphi读取Form资源文件的属性了之后触发(这个属性读取过程,可以参考Delphi 的持续机制浅探)。我们看看Visible这个属性变化所触发的过程,这个属性定义在TControl中,属性变化对应的过程为
procedure TControl.SetVisible(Value: Boolean);
begin
if FVisible <> Value then
begin
VisibleChanging;
FVisible : = Value;
Perform(CM_VISIBLECHANGED, Ord(Value), 0 );
RequestAlign;
end ;
end ;
procedure TWinControl.CMVisibleChanged( var Message: TMessage);
begin
if not FVisible and (Parent <> nil ) then RemoveFocus(False);
if not (csDesigning in ComponentState) or
(csNoDesignVisible in ControlStyle) then UpdateControlState;
end ;
procedure TWinControl.UpdateShowing;
var
ShowControl: Boolean;
I: Integer;
begin
ShowControl : = (FVisible and ( not (csDesigning in ComponentState) or not (csDesignerHide in ControlState)) or
((csDesigning in ComponentState) and not (csDesignerHide in ControlState)) and
not (csNoDesignVisible in ControlStyle)) and
not (csReadingState in ControlState) and not (csDestroying in ComponentState);
if ShowControl then
begin //这个时候如果是第一次显示,FHandle为0,就会调用CreateHandle来创建一个窗口句柄了,也就是说
//在这个时候才真真实实的创建Windows的标准控件!
if FHandle = 0 then CreateHandle;
if FWinControls <> nil then
for I : = 0 to FWinControls.Count - 1 do
TWinControl(FWinControls[I]).UpdateShowing;//之后会更新属于这个控件容器的所有子控件显示
end ;
if FHandle <> 0 then
if FShowing <> ShowControl then
begin
FShowing : = ShowControl;
try
SetPerformingShowingChanged(Self);
try
Perform(CM_SHOWINGCHANGED, 0 , 0 );
finally
ClearPerformingShowingChanged(Self);
end ;
except
FShowing : = not ShowControl;
raise ;
end ;
end ;
end ;
procedure TWinControl.CMRecreateWnd( var Message: TMessage);
var
WasFocused: Boolean;
begin
WasFocused : = Focused;//先保存控件是否是焦点状态
UpdateRecreatingFlag(True);//这个函数,我就不贴他的代码了,从他的代码中,我们可以看出来,这个函数
//的目的是为所有的子控件打上重建的标记
try
DestroyHandle;//释放句柄,同时释放所有子控件的句柄
UpdateControlState;//更新控件状态,这个函数上面已经分析,会建立句柄,同时子控件句柄。
finally
UpdateRecreatingFlag(False);//重建状态完成
end ;
if WasFocused and (FHandle <> 0 ) then
Windows.SetFocus(FHandle);//如果重建成功,并且原先有焦点,就恢复原先的焦点状态
end ;
至此为止,组件的生成过程就讲解完毕,欢迎专家指正!