• TEdit的创建与显示过程


    -------------------------- 分析TEdit的创建与显示过程 --------------------------
    TCustomEdit = class(TWinControl) 分析TEdit的创建与显示过程(注意,它不是由TCustomControl派生而来):
    TCustomEdit.Create 虽然执行inherited Create(AOwner);但除此之外只是初始化,什么都看不出来。只能研究它的父类调用了哪些虚函数,比如它覆盖了这些函数:
    procedure CreateParams(var Params: TCreateParams); override;
    procedure CreateWindowHandle(const Params: TCreateParams); override;
    procedure CreateWnd; override;

    分析:

    TWinControl.CreateParams 调用 Parent.GetHandle(但是这是条件语句,不一定执行,而且创建的也是父控件的句柄,不是创建当前控件的句柄,一般情况下不是创建当前窗口的入口)
    TWinControl.GetHandle 调用 HandleNeeded;
    TWinControl.HandleNeeded; 调用 Parent.HandleNeeded; 和 CreateHandle; (如有还没有创建的话,所以这么多函数之间不会形成一个悖论)
    TWinControl.CreateHandle; 调用 CreateWnd,并记录 SetProp,并 SetWindowPos (VCL创建窗口的真正入口,但程序员经常以CreateParams作为入口创建窗口)
    TWinControl.CreateWnd(它有一个局部变量Params); 调用CreateParams,管注册,指定lpfnWndProc后调用API RegisterClass 最后调用 CreateWindowHandle(Params)和SetWindowLong

    TWinControl.CreateWindowHandle 管创建,简单调用API CreateWindowEx
    TWinControl.RecreateWnd; 简单调用 Perform(CM_RECREATEWND, 0, 0);


    测试语句:
    procedure TForm1.Button1Click(Sender: TObject);
    var
    t: TEdit;
    begin
    t:=TEdit.Create(self); // 第一个断点
    t.Name:='myedit';
    t.Top:=50;
    t.Left:=100;
    t.Parent:=self; // 第二个断点
    //t.Visible:=True;
    end;
    并且在上面给上面一堆TWinControls的函数下断点


    发现1:执行到第一个断点后,再点击执行到下一个断点,居然会跳到第二个断点,而不是TWinControls那些函数的断点,这说明在t.parent:=self之前,根本就没有创建实际句柄(只创建了TEdit实例,内部WindowHandle依然为空,Delphi只在它真正需要的时候才创建相关Windows内核对象,这一点可以通过调试的时候观察t.WindowHandle得到结论),更谈不上显示。
    发现2:在一堆TWinControl.CreateXXX函数里,发现第二个断点会首先执行TWinControl.CreateHandle; 这说明这个函数才是真正的入口。

    那么TWinControl.CreateHandle;是如何被执行到的呢?整个过程依次执行:
    procedure TWinControl.SetParent(AParent: TWinControl); 调用 TControl.SetParent
    procedure TWinControl.InsertControl(AControl: TControl);
    procedure TWinControl.UpdateControlState;
    procedure TWinControl.UpdateShowing; 这个函数很特殊,内有递归:

    TWinControl(FWinControls[I]).UpdateShowing; // 递归
    TWinControl.UpdateShowing; 在这里终于发现 if WindowHandle = 0 then CreateHandle; 而且经过若干次递归(排除已经被创建和显示的,比如界面上还有一个Button1和Label1,其中Label1不是TWinControl,这里不会管它)后会执行CreateHandle;。
    CreateHandle会调用CreateWnd,但却是TCustomEdit.CreateWnd; 后者调用inherited CreateWnd; 后面还有若干次调用虚拟函数,但总的来说问题不大。以后再补充。

    -------------------------- 分析TEdit的创建与显示过程 --------------------------
    TCustomEdit = class(TWinControl) 分析TEdit的创建与显示过程(注意,它不是由TCustomControl派生而来):
    TCustomEdit.Create 只是初始化,什么都看不出来。只能研究它的父类调用了哪些虚函数。最后发现是myEdit.parent:=Self;的时候才真正创建并显示
    procedure CreateParams(var Params: TCreateParams); override;
    procedure CreateWindowHandle(const Params: TCreateParams); override;
    procedure CreateWnd; override;

    TWinControl.CreateParams 调用 Parent.GetHandle
    TWinControl.GetHandle 调用 HandleNeeded;
    TWinControl.HandleNeeded; 调用 Parent.HandleNeeded; 和 CreateHandle;
    TWinControl.CreateHandle; 调用 CreateWnd,并记录 SetProp,并 SetWindowPos
    TWinControl.CreateWindowHandle 管创建,简单调用API CreateWindowEx

    TWinControl.CreateWnd; 调用CreateParams,管注册,指定lpfnWndProc后调用API RegisterClass 比较复杂
    TWinControl.RecreateWnd; 简单调用 Perform(CM_RECREATEWND, 0, 0);

  • 相关阅读:
    cocos日记
    Android 开发经验
    vbs自学备份
    C# 如何在winform中嵌入Excel,内嵌Excel,word
    win7 64位在线编辑dsoframer控件的安装和使用配置
    C# 正则表达式 最全的验证类
    在 Range 对象中,Min (14)必须小于或等于 max (-1)。
    winform Form窗体和UserControl用户空间嵌入Panel容器并填充
    C# Winform防止闪频和再次运行
    Base64编码解码
  • 原文地址:https://www.cnblogs.com/findumars/p/3667031.html
Copyright © 2020-2023  润新知