求助:有谁知道Delphi中窗口的创建过程,此“窗口”不仅仅指 TForm 类型, 还包括一般的窗口控件,如TButton,TEdit等等,希望有能够十分详细的运作 过程,比如说CreatParams,CreateWindowHandle等等函数的调用情况,可能 调试过 Delphi VCL 源代码这个问题才能解决此问题,我很想知道。谢谢!
你的问题只需要从对象的概念来理解也就好了呀! 其实在Delphi中,所有的VCL不就是一个个对象么? 它有图形外观也是因为它能够响应消息呀!(WM_Pain消息) 基本而言,一个VCL组件创建过程没有什么特殊的,只是将其所有的数据成员 初始化而已(这里的数据成员包括一些消息处理,不过在Delphi中消息处理是 由Delphi内置的功能完成的,通过message关键字) 至于这个初始化数据成员的顺序,也就是一般意义上的先创建自身的,然后再初始化 子类的(其实应该是每一个子类都是先初始化父类对象成员inherited Create,然后 再初始化自己的成员)。 其余操作都是由消息来完成的如一个控件的外观是由WM_PAINT消息驱动的,此消息 在窗口需要重画时发送出来(如果是Windows处理的消息,只有TWinControl才能得到 而在Delphi中的TGraphControl,类似的消息是由Delphi来处理的,当初这样处理 是为了节约资源,当年可用窗口句柄数量不像现在这样没有节制,如果多了,可以促使 Windows死掉的) 总之一句话,创建过程中初始化成员数据的过程,我是指在Create方法中(所以我在 Form的Create中一身不作很多事情,而是在FormShow中做一些事情),而在释放过程 中释放这些资源,其它事情都是消息驱动的,无论这些消息是来自Windows,Delphi 更或者是应用程序自身 闲着也是闲着,多写了几句,不好意思,如果哪位用了自动回复,收到的信希望不太 大。
DELPHI中的窗口分为重叠型窗口,弹出式窗口与子窗口,WINDOW系统库中包含着每个应用程序所创建的所有窗口的列表,并赋予每个窗口一个唯一值。创建一个简单的新应用程序并在其中放一个按钮,保存并运行程序。使用DELPHI的WINSIGHT工具可以看到系统窗口的列表。应用程序就是窗口。从WINSIGHT信息的分析中,可以看到,应程序具有一个额外的窗口,增加到主窗体系统菜单上的项目并未增加到任务条上。当我们创建一个全新的应用程序时,DELPHI会为项目文件生成一些代码,包括下列代码: PROGRAME PROJECT1; USES FORMS,UNIT1 IN‘UNIT1。PAS’{FORM1} {$R*。RES} BEGIN APPLICATION.INITIALIZE; APPLICATION.CREATEFORM(TFORM1,FORM1); APPLICATION.RUN; END; 当窗体创建时,会接收到ONCREAT事件,并可以改变或测试初始窗体的属性或元素。但窗体的创建不可改变。与窗体创建相应的语句在项目的源文件中(。DPR)文件中,使用PROJECT|VIEWSOURCE可以看到; 如果不希望窗体自动创建,也可以改动相应代码;或在PROJECTOPTIONS对话框中选择不自动创建,在屏幕后发生了一些事件,当调用CREATFORM时,如果当前没有主窗体,当前窗体会被赋为主窗体。因此对话框MAINFORM编辑框表示的窗体对应着对应程序CREATFORM对象方法的第一次调用,就是说,当启动时可能有多个窗体创建,而MAINFORM是第一个。 DELPHI中,所有窗体都是重叠型窗口,甚至对话框也是如此。在DELPHI中,弹出式菜单只出现于隐藏应用程序窗口。在系统中,它们被用作消息框以及弹出式菜单或下拉式菜单。 不知这些是否是你想要的。
//******************************************************************* To WuWZY: //******************************************************************* 1、TCustomForm.Create 在 TCustomForm.Create 中调用 TCustomForm.CreateNew; 2、TCustomForm.CreateNew; 调用 FCanvas := TControlCanvas.Create; 触发 TControlCanvas.Create; 触发 TControlCanvas.CreateHandle; 3、TControlCanvas.CreateHandle; 调用 FControl.GetDeviceContext(FWindowHandle); 即 TWinControl.GetDeviceContext(FWindowHandle); 4、TWinControl.GetDeviceContext(FWindowHandle); 调用 TWinControl.GetDC(Handle); 此处说明一下: 对 TWinControl 的 Handle 属性的读取会触发 TWinControl.GetHandle; 可以察看 Property Handle; 的声明。 5、第四步中对 Handle 进行读取,触发下述序列:(TWinControl) Handle->GetHandle->HandleNeeded 6、TWinControl.HandleNeeded 检查 FHandle 的值: if FHandle = 0 then begin if Parent <> nil then Parent.HandleNeeded; CreateHandle; // 调用 CreateHandle; end; 7、TWinControl.CreateHandle 调用 CreateWnd; if FHandle = 0 then // 此时 FHandle 仍然为零 begin CreateWnd; ... end; 8、TWinControl.CreateWnd 调用 CreateParams(Params); // 让用户有机会加入新的特征参数 CreateParams(Params); with Params do begin ... // 标准的 API 使用,注册窗口类,CreateWindowEx ... if Windows.RegisterClass(WindowClass) = 0 then RaiseLastWin32Error; ... CreateWindowHandle(Params); ... end; 9、CreateWindowHandle(Params); FHandle := CreateWindowEx(ExStyle, WinClassName, Caption, Style, X, Y, Width, Height, WndParent, 0, WindowClass.hInstance, Param); 完成真正的窗口创建,并赋予 FHandle 窗口句柄。 10、回到第一步 CreateNew 之后调用 DoCreate try CreateNew(AOwner); ... if OldCreateOrder then DoCreate; finally ... end; 11、DoCreate 调用用户的 OnCreate 事件: if Assigned(FOnCreate) then try FOnCreate(Self); // 调用 OnCreate; except Application.HandleException(Self); end; if fsVisible in FFormState then Visible := True; // *************************************************************** The End. From: BaKuBaKu // ***************************************************************
补充一点: 其他的控件比如 TEdit 等都是 TWinControl 的子孙,构造的顺序都差不多, 关键的一点是: 对 TWinControl.Handle 属性的第一次访问会触发对窗口句柄的真正创建。 即:Handle->GetHandle->HandleNeeded 关于这一点,可以察看 Delphi Help->HandleAllocated 方法的注解。 上文只是剖析了 TForm 的构造过程,其它类似控件可能有所差别,其它控件并不 一定是在构造 TControlCanvas 时才第一次访问 TWinControl.Handle 的,也许 是在其他地方,不过没有必要都写出来。
windows使用createWidnow,createWidnowEx函数进行所有窗口的创建工作. delphi的CreateParams类似与此,只是一个外壳而已. 每个窗口(指所有大大小小的窗口)都有一个窗口过程winproc,窗口的消息在此 过程中进行处理.当然,消息是链式传递的,windows内建一个缺省的窗口过程,即: defWidnowProc,程序中某些消息的处理不使用缺省过程,而是自己处理. c语言中有个winmain函数,这是程序的入口点, delphi中即程序文件中program中的begin...end过程. 去吧.
求助:有谁知道Delphi中窗口的创建过程,此“窗口”不仅仅指 TForm 类型, 还包括一般的窗口控件,如TButton,TEdit等等,希望有能够十分详细的运作 过程,比如说CreatParams,CreateWindowHandle等等函数的调用情况,可能 调试过 Delphi VCL 源代码这个问题才能解决此问题,我很想知道。谢谢!
你的问题只需要从对象的概念来理解也就好了呀! 其实在Delphi中,所有的VCL不就是一个个对象么? 它有图形外观也是因为它能够响应消息呀!(WM_Pain消息) 基本而言,一个VCL组件创建过程没有什么特殊的,只是将其所有的数据成员 初始化而已(这里的数据成员包括一些消息处理,不过在Delphi中消息处理是 由Delphi内置的功能完成的,通过message关键字) 至于这个初始化数据成员的顺序,也就是一般意义上的先创建自身的,然后再初始化 子类的(其实应该是每一个子类都是先初始化父类对象成员inherited Create,然后 再初始化自己的成员)。 其余操作都是由消息来完成的如一个控件的外观是由WM_PAINT消息驱动的,此消息 在窗口需要重画时发送出来(如果是Windows处理的消息,只有TWinControl才能得到 而在Delphi中的TGraphControl,类似的消息是由Delphi来处理的,当初这样处理 是为了节约资源,当年可用窗口句柄数量不像现在这样没有节制,如果多了,可以促使 Windows死掉的) 总之一句话,创建过程中初始化成员数据的过程,我是指在Create方法中(所以我在 Form的Create中一身不作很多事情,而是在FormShow中做一些事情),而在释放过程 中释放这些资源,其它事情都是消息驱动的,无论这些消息是来自Windows,Delphi 更或者是应用程序自身 闲着也是闲着,多写了几句,不好意思,如果哪位用了自动回复,收到的信希望不太 大。
DELPHI中的窗口分为重叠型窗口,弹出式窗口与子窗口,WINDOW系统库中包含着每个应用程序所创建的所有窗口的列表,并赋予每个窗口一个唯一值。创建一个简单的新应用程序并在其中放一个按钮,保存并运行程序。使用DELPHI的WINSIGHT工具可以看到系统窗口的列表。应用程序就是窗口。从WINSIGHT信息的分析中,可以看到,应程序具有一个额外的窗口,增加到主窗体系统菜单上的项目并未增加到任务条上。当我们创建一个全新的应用程序时,DELPHI会为项目文件生成一些代码,包括下列代码: PROGRAME PROJECT1; USES FORMS,UNIT1 IN‘UNIT1。PAS’{FORM1} {$R*。RES} BEGIN APPLICATION.INITIALIZE; APPLICATION.CREATEFORM(TFORM1,FORM1); APPLICATION.RUN; END; 当窗体创建时,会接收到ONCREAT事件,并可以改变或测试初始窗体的属性或元素。但窗体的创建不可改变。与窗体创建相应的语句在项目的源文件中(。DPR)文件中,使用PROJECT|VIEWSOURCE可以看到; 如果不希望窗体自动创建,也可以改动相应代码;或在PROJECTOPTIONS对话框中选择不自动创建,在屏幕后发生了一些事件,当调用CREATFORM时,如果当前没有主窗体,当前窗体会被赋为主窗体。因此对话框MAINFORM编辑框表示的窗体对应着对应程序CREATFORM对象方法的第一次调用,就是说,当启动时可能有多个窗体创建,而MAINFORM是第一个。 DELPHI中,所有窗体都是重叠型窗口,甚至对话框也是如此。在DELPHI中,弹出式菜单只出现于隐藏应用程序窗口。在系统中,它们被用作消息框以及弹出式菜单或下拉式菜单。 不知这些是否是你想要的。
//******************************************************************* To WuWZY: //******************************************************************* 1、TCustomForm.Create 在 TCustomForm.Create 中调用 TCustomForm.CreateNew; 2、TCustomForm.CreateNew; 调用 FCanvas := TControlCanvas.Create; 触发 TControlCanvas.Create; 触发 TControlCanvas.CreateHandle; 3、TControlCanvas.CreateHandle; 调用 FControl.GetDeviceContext(FWindowHandle); 即 TWinControl.GetDeviceContext(FWindowHandle); 4、TWinControl.GetDeviceContext(FWindowHandle); 调用 TWinControl.GetDC(Handle); 此处说明一下: 对 TWinControl 的 Handle 属性的读取会触发 TWinControl.GetHandle; 可以察看 Property Handle; 的声明。 5、第四步中对 Handle 进行读取,触发下述序列:(TWinControl) Handle->GetHandle->HandleNeeded 6、TWinControl.HandleNeeded 检查 FHandle 的值: if FHandle = 0 then begin if Parent <> nil then Parent.HandleNeeded; CreateHandle; // 调用 CreateHandle; end; 7、TWinControl.CreateHandle 调用 CreateWnd; if FHandle = 0 then // 此时 FHandle 仍然为零 begin CreateWnd; ... end; 8、TWinControl.CreateWnd 调用 CreateParams(Params); // 让用户有机会加入新的特征参数 CreateParams(Params); with Params do begin ... // 标准的 API 使用,注册窗口类,CreateWindowEx ... if Windows.RegisterClass(WindowClass) = 0 then RaiseLastWin32Error; ... CreateWindowHandle(Params); ... end; 9、CreateWindowHandle(Params); FHandle := CreateWindowEx(ExStyle, WinClassName, Caption, Style, X, Y, Width, Height, WndParent, 0, WindowClass.hInstance, Param); 完成真正的窗口创建,并赋予 FHandle 窗口句柄。 10、回到第一步 CreateNew 之后调用 DoCreate try CreateNew(AOwner); ... if OldCreateOrder then DoCreate; finally ... end; 11、DoCreate 调用用户的 OnCreate 事件: if Assigned(FOnCreate) then try FOnCreate(Self); // 调用 OnCreate; except Application.HandleException(Self); end; if fsVisible in FFormState then Visible := True; // *************************************************************** The End. From: BaKuBaKu // ***************************************************************
补充一点: 其他的控件比如 TEdit 等都是 TWinControl 的子孙,构造的顺序都差不多, 关键的一点是: 对 TWinControl.Handle 属性的第一次访问会触发对窗口句柄的真正创建。 即:Handle->GetHandle->HandleNeeded 关于这一点,可以察看 Delphi Help->HandleAllocated 方法的注解。 上文只是剖析了 TForm 的构造过程,其它类似控件可能有所差别,其它控件并不 一定是在构造 TControlCanvas 时才第一次访问 TWinControl.Handle 的,也许 是在其他地方,不过没有必要都写出来。
windows使用createWidnow,createWidnowEx函数进行所有窗口的创建工作. delphi的CreateParams类似与此,只是一个外壳而已. 每个窗口(指所有大大小小的窗口)都有一个窗口过程winproc,窗口的消息在此 过程中进行处理.当然,消息是链式传递的,windows内建一个缺省的窗口过程,即: defWidnowProc,程序中某些消息的处理不使用缺省过程,而是自己处理. c语言中有个winmain函数,这是程序的入口点, delphi中即程序文件中program中的begin...end过程. 去吧.
|
请发表评论