欢迎来到天天文库
浏览记录
ID:37709009
大小:44.00 KB
页数:6页
时间:2019-05-29
《delphi消息机制》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、永远记住,无论你是用SDK还是借用VCL来创建窗口,都要遵循Windows的游戏规则,即先注册窗口类,然后再创建窗口实例,在消息循环中写实现代码。你还要知道Windows已经为了我们预注册了多个窗口类,例如“Edit”、“ComboBox”,这时候我们要做的就是直接创建这些窗口,无需注册窗口类了;在Delphi中这一切更简单了,VCL全部为你做好了,你只需简单地在设计窗体上拖动你要的控件再写实现代码就可以了,是不是很cool? 一、窗口的创建 VCL中,具有句柄(Handle)属性的真正窗口控件
2、全部继承自TWinControl,那就从TWinControl的创建开始说起。 VCL中窗口的建立不是按照我们想象中的流程创建的,即先把所有的窗口都创建好,然后再调用,而是在需要时才创建。可能你还不能理解我这句话的意思,慢慢看。继承自TWinControl的窗口控件都会有Handle属性,当代码中需要Handle值时,通过该属性的getter调用TWinControl.HandleNeeded来获得句柄,这时如果窗体已经建立,直接返回句柄,否则先创建窗口实例,再返回句柄,因此窗口创建是在TWinCo
3、ntrol.HandleNeeded中实现的。Borland这样做的目的我想是最大程度地来节省系统资源吧。 TWinControl.HandleNeeded中有几个重要的方法,通过他们才得以创建窗口。TWinControl.HandleNeeded调用TWinControl.CreateHandle来获得Handle。但CreateHandle只是个包装函数,它首先调用TWinControl.CreateWnd来创建窗口,CreateWnd是一个重要的过程,它先调用TWinControl.Creat
4、eParams设置创建窗口的参数,通过这些参数调用RegisterClassAPI注册窗口类,CreateWnd然后调用TWinControl.CreateWindowHandle,CreateWindowHandle才是真正调用CreateWindowExAPI创建窗口实例的函数。CreateHandle、CreateWnd、CreateParams、CreateWindowHandle都是虚方法,派生类可以重载这些方法以获得更多的功能,其中CreateParams被重载的几率最大。 上面提到的方
5、法源码我建议你都要仔细看一遍,加深印象,后面我提到的方法,你也都要看看源码,受益无穷呀,我将不再提示。 至此一个窗口算是建立起来了,但是还是无法正确运行,因为它还没有消息循环。 二,消息循环的实现 消息循环的实现是整个VCL消息框架中写得最精彩的地方,因为传统的Windows回调函数是一个静态函数,而VCL中的窗体是类,调用类方法时,除了函数本身的地址,还需一个Self,在它们之间建立关联真不是一件容易的事情,需要大量的代码技巧,同时消息循环还要保证每秒钟能处理几百到几万次的消息量,因此代码更需
6、要写得精巧。研习这部分代码可能会花比较多的时间。 我们知道注册窗体类时就要提供窗体回调函数入口地址,那么可以想象到VCL中这个过程是发生在对TWinControl.CreateWnd的调用中,在该方法中,静态函数指针@InitWndProc被赋值给WNDCLASSEX结构中的lpfnWndProc,这是VCl窗体首次建立消息循环的地方。InitWndProc第一次被调用时,通过SetWindowLongAPI将消息回调函数替换成TWindowControl.FObjectInstance,而TWin
7、Control.FObjectInstance就是一个普通的Pointer,赋值是在TWinControl.Create中通过那个最具Magic的函数MakeObjectInstance完成的,这个过程非常复杂,详细描述见参考[3]。 替换的结果是类方法TWinControl.MainWndProc成为真正的消息处理Handler,随后的对应窗体实例的消息处理全部在TWinControl.MainWndProc中完成。其中还有一个细节就是消息在被MainWndProc处理之前还要调用一个纯汇编写的静
8、态函数--StdWndProc将消息统一派发[1]。至此完成消息回调从普通的静态函数到类方法的转变。 事实上TWinControl.MainWndProc是调用WindowsProc来实际处理窗口消息,在TControl.Create中WindowsProc是被指定成类中虚拟方法WndProc。从TControl到实际的VCL窗体类这条继承链上,很多派生类都重载了WndProc,从而每个重载该方法的派生类都会增加一些功能。当然在继承链的末端,例如TFo
此文档下载收益归作者所有