我对windows和delphi的消息处理还不大熟悉,哪位大虾能给讲解以下,如果有资料就更好了。
附加一个问题:delphi应用程序的消息循环从(系统的,自身的)消息队列中取消息,还是windows将消息队列中的消息发给程序呢?

解决方案 »

  1.   

    消息,就是指Wi n d o w s发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变
    窗口尺寸、按下键盘上的一个键都会使Wi n d o w s发送一个消息给应用程序。
    消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,
    对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做T M s g,它
    在Wi n d o w s单元中是这样声明的:
    t y p e
    TMsg = packed record
    hwnd: HWND; / /窗口句柄
    message: UINT; / /消息常量标识符
    wParam: WPA R A M ; // 32位消息的特定附加信息
    lParam: LPA R A M ; // 32位消息的特定附加信息
    time: DWORD; / /消息创建时的时间
    pt: TPoint; / /消息创建时的鼠标位置
    e n d ;
    消息中有什么?
    是否觉得一个消息记录中的信息像希腊语一样?如果是这样,那么看一看下面的解释:
    hwnd 32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可
    视对象的句柄(窗口、对话框、按钮、编辑框等)。
    message 用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也
    第5章理解Wi n d o w s消息1 1 5
    可以是自定义的常量。
    wParam 通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。
    lParam 通常是一个指向内存中数据的指针。由于W P a r a m、l P a r a m和P o i n t e r都是3 2位的,
    因此,它们之间可以相互转换。Wi n d o w s的消息系统是由3个部分组成的:
    • 消息队列。Wi n d o w s能够为所有的应用程序维护一个消息队列。应用程序必须从消息队列中获取
    消息,然后分派给某个窗口。
    • 消息循环。通过这个循环机制应用程序从消息队列中检索消息,再把它分派给适当的窗口,然
    后继续从消息队列中检索下一条消息,再分派给适当的窗口,依次进行。
    • 窗口过程。每个窗口都有一个窗口过程来接收传递给窗口的消息,它的任务就是获取消息然后
    响应它。窗口过程是一个回调函数;处理了一个消息后,它通常要返回一个值给Wi n d o w s。
    注意回调函数是程序中的一种函数,它是由Windows或外部模块调用的。
    一个消息从产生到被一个窗口响应,其中有5个步骤:
    1) 系统中发生了某个事件。
    2) Wi n d o w s把这个事件翻译为消息,然后把它放到消息队列中。
    3) 应用程序从消息队列中接收到这个消息,把它存放在T M s g记录中。
    4) 应用程序把消息传递给一个适当的窗口的窗口过程。
    5) 窗口过程响应这个消息并进行处理。
    步骤3和4构成了应用程序的消息循环。消息循环往往是Wi n d o w s应用程序的核心,因为消息循环
    使一个应用程序能够响应外部的事件。消息循环的任务就是从消息队列中检索消息,然后把消息传递给适当的窗口。如果消息队列中没有消息,Wi n d o w s就允许其他应用程序处理它们的消息。
      

  2.   

    V C L替你处理了许多Wi n d o w s消息系统的细节。例如,消息循环己经封装到V C L的F o r m s单元,因
    此,用不着考虑怎样从消息队列中检索消息然后再把它指派给某个窗口。D e l p h i还把Wi n d o w s的T M s g
    记录中的信息映射为T M e s s a g e记录:
    需要注意的是, T M e s s a g e记录中的信息要比T M s g中的信息少一点,这是因为D e l p h i把有些信息封
    装起来,T M e s s a g e中只包含了处理消息所必需的信息。
    特别要注意的是, T M e s s a g e记录中包含了一个R e s u l t域。正如前面提到的那样,某些信息需要窗
    口过程返回一个值。在D e l p h i中,要返回一个值,只要对T M e s s a g e记录的R e s u l t域赋值。后面的5 . 5 . 2
    节“对R e s u l t域赋值”将详细解释这一点。
    特殊的消息记录
    除了通用的T M e s s a g e记录外,D e l p h i为每个Wi n d o w s消息定义了一个特殊的消息记录,这样就不
    必从w P a r a m域和l P a r a m域中分解出有关信息。这些特殊的记录可以在M e s s a g e s单元中找到。
    注意几乎每一个Wi n d o w s消息都定义一个消息记录。消息记录的命名是在消息标识符的前面加
    上大写字母T并去掉下划线。例如,与消息W M _ S E T F O N T对应的消息记录名称叫T W M S e t F o n t。
    顺便说一下,TMessage记录对所有的消息都是适用的,而特殊的消息记录只适用于某些消息。
    所谓消息处理,就是应用程序以某种方式响应Wi n d o w s消息。在一个标准的Wi n d o w s应用程序中,
    消息是由窗口过程处理的。不过, D e l p h i封装了窗口过程,这使得消息处理简单多了。以前,一个窗
    口程序需要处理各种消息,而在D e l p h i中,每个消息都有各自的过程。用于消息处理的过程必须满足
    下列3个条件:
    • 这个过程必须是一个对象中的方法。
    • 这个过程必须有一个v a r参数,变量的类型是T M e s s a g e或其他特殊的消息记录。
    • 声明这个过程时,必须使用m e s s a g e指示符,后面跟要处理的消息的常量值。
    下面是声明一个处理W M _ PA I N T消息的过程的代码:
    注意给用于消息处理的过程命名时采用这样的约定:过程名与消息的标识符一致,但不要全
    部大写,也不要有下划线。
    作为一个例子,下面写一个处理W M _ PA I N T消息的过程。
    首先,创建一个新的空白的项目。然后访问这个项目的代码编辑窗口并在T F o r m对象的p r i v a t e部
    分加入下面这一行。
    然后,在单元的i m p l e m e n t a t i o n部分实现这个过程。记住,要在这个过程的名称前加T F o r m 1,但
    不需要m e s s a g e指示符。
    请注意上述代码中的i n h e r i t e d语句。当想传递消息给祖先对象的处理过程时,请调用i n h e r i t e d语句。
    这个语句的作用是把消息传递给T F o r m中处理W M _ PA I N T消息的过程。
    注意调用inherited时不需要给出祖先类中方法的名称。因为方法的名称并不重要,Delphi是根
    据消息的常量来区分过程的。
      

  3.   

    Delphi封装了Windows的消息系统,并加上了Delphi自定义的消息