我对windows和delphi的消息处理还不大熟悉,哪位大虾能给讲解以下,如果有资料就更好了。
附加一个问题:delphi应用程序的消息循环从(系统的,自身的)消息队列中取消息,还是windows将消息队列中的消息发给程序呢?
附加一个问题:delphi应用程序的消息循环从(系统的,自身的)消息队列中取消息,还是windows将消息队列中的消息发给程序呢?
解决方案 »
- SQL书籍汇总(mssql)
- cxGrid onFocusedRecordChanged事件
- MDI窗体的borderstyle:=dsnone后,显示出来的MDI窗体为什么最大化最小化关闭按钮都存在,我不想看到这些按钮,在MDI窗体上如何设置?
- 大家知道在VC中打::就能弹出全局函数和全局变量的代码辅助框,那么我想在DELPHI中想要看看它都支持哪些全局API和变量,怎么看
- 简单问题,关于dll
- 请问如何得到当前应用程序的路径?在线~
- tcxtreelist 每个 node设置不同properties 有人解决吗?QQ281482913 在线等!
- 问一个简单问题,在三层结构中,你们想在客户端提取一些数据显示,一般是用什么方法呢?
- delphi 想说爱你不容易!
- 在Delphi数据库程序中如何显示空的日期
- 小弟初学DELPHI,谁能帮帮我啊!
- 小弟初学,有C\C++其础,买什么Delphi书好?
窗口尺寸、按下键盘上的一个键都会使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就允许其他应用程序处理它们的消息。
此,用不着考虑怎样从消息队列中检索消息然后再把它指派给某个窗口。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是根
据消息的常量来区分过程的。