第一部分:流程概述
这是一个很大的题目,本人才疏学浅难免有纰漏之处,还请大家多多见谅!
虽然这篇文章是讨论Delphi的消息机制,但是如果不知道Windows的程序是如何运转的,就根本无从下手,所以先费点口沫,让我们回顾一下Windows的消息机制。
让我们先从一张图开始:
这张图大概说明了Window的消息处理流程,首先,桌面上或许有很多窗口,但是对于操作系统来说,如果某个窗口被鼠标点击了一下,系统可以分辨出是那一个窗口被点击,根据该窗口的句柄(每个窗口的唯一标识符)就可以找到这个窗口是由那一个程序创建的。
在windows系统中,时刻都会产生许多事件,因此,为了让应用程序处理各种事件,必须创建一种可以让应用程序有效处理事件的机制,因此为每个程序维护一个独立的消息列表是操作系统责无旁贷的义务,系统会把所有关于该程序的事件全部发送到这个队列当中,而用户程序在一个循环中不停的去这个队列里取消息并进行处理,这样就基本构成了一个消息的循环体系。
但是,这里需要注意的是,第一,该消息队列是由操作系统维护的,用户程序不用太担心怎么样去维护它,第二,系统并不是把消息投递到队列就完事了,它必须要知道用户程序是怎么处理处理该消息的,这样它才能维护该程序的消息队列。
基于这样的原因,应用程序并不是直接处理从消息队列取得的消息,(注意打叉的箭头),而是请求windows调用自己设定好的处理程序。看上去有些奇怪,为什么要绕这个弯呢?其实除了上面说的原因,还有其它的理由,因为系统并不是把所有的消息都投递到消息队列中去的,有些需要及时处理的消息(比如设置光标)等都被直接投递到消息处理程序,还有,如果程序里使用了Sendmessage函数,这个函数也会把消息直接投递到(非跨进程)消息处理程序中去。如下图:
所以,当我们向系统申请创建一个窗口的时候,在我们填的申请表格里就要填上该消息处理模块的地址,系统将根据创建好的窗口的句柄和我们申请时填写的消息