消息是Windows发出的一个通知,它告诉应用程序某个事件发生了。在Delphi中,大多数情况下Windows的消息被封装在VCL的事件中,我们只需处理相应的VCL事件就可以了,但如果我们需要编写自己的控件、截获或过滤消息就必须深入研究Win32的消息处理机制。

在Delphi中消息以TMessage记录的方式定义。
打开Message.pas文件,我们可以看到Tmessage是这样定义的:

type 
TMessage = packed record 
Msg: Cardinal; 
case Integer of 
0: ( WParam: Longint; 
LParam: Longint; 
Result: Longint); 
1: ( WParamLo: Word; 
WParamHi: Word; 
LParamLo: Word; 
LParamHi: Word; 
ResultLo: Word; 
ResultHi: Word); 
end;

windows是消息驱动的系统,系统为每一个程序(应该说进程)建立一个消息队列。

消息的组成:一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。

WPARAM常常代表一些控件的ID或者高位低位组合起来分别表示鼠标的位置,如果消息的发送者需要将某种结构的指针或者是某种类型的句柄时,习惯上用LPARAM来传递,

例如当菜单转中之后会有WM_COMMAND消息发送,WPARAM的低字中(LOWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。   

一个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。

未处理的消息到那里去了:微软为窗口编写了默认的窗口过程,这个窗口过程将负责处理那些你不处理消息。正因为有了这个默认窗口过程我们才可以利用Windows的窗口进行开发而不必过多关注窗口各种消息的处理。例如窗口在被拖动时会有很多消息发送,而我们都可以不予理睬让系统自己去处理。   

每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。

例如有两个窗口共用一个窗口过程代码,你在窗口一上按下鼠标时消息就会通过窗口1的句柄被发送到窗口1而不是窗口2。

示例:下面有一段伪代码演示如何在窗口过程中处理消息   
LONG yourWndProc(HWND hWnd,UINT uMessageType,WPARAM wP,LPARAM)  
 {   
switch(uMessageType)  
{//使用SWITCH语句将各种消息分开   
case(WM_PAINT):   doYourWindow(...);//在窗口需要重新绘制时进行输出   break;  
 
case(WM_LBUTTONDOWN):   doYourWork(...);//在鼠标左键被按下时进行处理   break; 
  
default:   callDefaultWndProc(...);//对于其它情况就让系统自己处理   break;  
 
}   
}   

消息机制:系统将会维护一个或多个消息队列,所有产生的消息都回被放入或是插入队列中。
系统会在队列中取出每一条消息,根据消息的接收句柄而将该消息发送给拥有该窗口的程序的消息循环。
每一个运行的程序都有自己的消息循环,在循环中得到属于自己的消息并根据接收窗口的句柄调用相应的窗口过程。而在没有消息时消息循环就将控制权交给系统所以Windows可以同时进行多个任务。

下面的伪代码演示了消息循环的用法:   
while(1)   {   
id=getMessage(...);   
if(id == quit)   break;   
translateMessage(...);   
}   
当该程序没有消息通知时getMessage就不会返回,也就不会占用系统的CPU时间。

举我们选择菜单的例子,当选择了一个菜单项的时候,Windows向菜单所属的窗口发送WM_COMMAND消息;而用户按下了一个加速键的时候,windows向TranslateAccelerate函数指定的目标窗口发送WM_COMMAND消息。一般这两者对应的窗口都是主窗口,所以在主窗口中的窗口过程中集中处理WM_COMMAND消息,而不必考虑它究竟是菜单引发的还是加速键引发的。

WM_COMMAND消息的两个参数是这样定义的: 
wParam的高位 =wNotifyCode ;通知码 
wParam的低位 =wID ;命令ID 
lParam = hwdCtl ;发送WM_COMMAND 消息的子窗口句柄,即谁发的该消息

除了菜单和加速键,WM_COMMAND 消息也可以由其他子窗口引发,如主窗口中的按钮或工具栏,还有你提到的系统托盘的鼠标事件等等,lParam参数指定了引发消息的子窗口句柄,对于菜单和加速键引发的WM_COMMAND消息,lParam的值为0。wParam参数的低16位是命令ID,也就是资源脚本文件中菜单项的命令ID或加速键的命令ID,高16位是通知码,菜单消息的通知码是0,加速键消息的通知码为1。 
这只是菜单和加速键的定义。其他的消息可能与此不同,具体查资料吧。

perform是给自己发消息,所以同SendMessage或PostMessage的区别只在于少了第一个HWND参数, 
perform(WM_MESG,WPARAM,LPARAM); 
可以打开Messages.pas,参考DELPHI所用(不仅仅Windows标准消息,还有很多VCL所用自定义消息也在里面)的消息结构及定义

Delphi中的消息 (转载)的更多相关文章

  1. Delphi中window消息截获的实现方式(2)

    Delphi是Borland公司提供的一种全新的WINDOWS编程开发工具.由于它采用了具有弹性的和可重用的面向对象Pascal(object-orientedpascal)语言,并有强大的数据库引擎 ...

  2. Delphi中的消息截获(六种方法:Hook,SubClass,Override WndProc,Message Handler,RTTI,Form1.WindowProc:=@myfun)good

    Windows是一个基于消息驱动的系统,因此,在很多时候,我们需要截获一些消息然后自己进行处理.而VCL系统又有一些特定的消息.下面对我所了解的delphi环境中截获消息进行一些总结.      就个 ...

  3. Delphi中控制Excel(转载)

    用Delphi从数据库中取得资料,然后导出到Excel中做成报表是个不错的选择,因为Excel强大的报表功能那可是没话说前提Delphi中要 uses comobj;var Excel:Variant ...

  4. Delphi中window消息截获的实现方式(1)

    近来笔者在一个项目中需要实现一个功能:模仿弹出菜单的隐藏方式,即鼠标在窗口的非PanelA区域点击时,使得PanelA隐藏.   经过思考,笔者想到通过处理鼠标的点击事件来实现相应功能.但是,究竟由谁 ...

  5. delphi中Message消息的使用方法

    实例1 unit Unit1; interface   uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls ...

  6. delphi中Time消息的使用方法

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  7. Delphi中Message消息的三种使用方法(覆盖WndProc,覆盖消息函数,改写WMCommand)

    实例1 unit Unit1; interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Fo ...

  8. Delphi——Window 消息 - 转载▼

    Delphi是Borland公司的一种面向对象的可视化软件开发工具. Delphi集中了Visual C++和Visual Basic两者的优点:容易上手.功能强大,特别是在界面设计.数据库编程.网络 ...

  9. delphi XE7 中的消息

    在delphi XE7的程序开发中,消息机制保证进程间的通信. 在程序中,消息来自: 1)系统: 通知你的程序用户输入,涂画以及其他的系统范围的事件: 2)你的程序:不同的程序部分之间的通信信息.   ...

随机推荐

  1. Linux 公网IP和内网IP,Dubbo提供者注册到了内网IP上怎么处理!

    1.将Linux的localhost 改为公网IP: 改完以后重启网卡,并刷新Hosts: 2.将提供者和消息者的Dubbo 都改为公网IP: 3.开放端口:

  2. 项目中phpexcel的基本用法

    前提:要下载PHPEXCEL库文件 如:phpexcel官方下载    ,本人使用下载 情形一:对于将数据写入EXCEL表中的用法 header("content-type:text/htm ...

  3. 从0移植uboot (四) _点亮调试LED

    这一节主要讨论1个问题:点灯.点灯是实际开发中,特别是裸板开发中常见的调试手段,相当于主机开发中漫天飞舞的printf/printk.为了追踪程序的现场执行情况,很多时候我们都使用点一个灯的方法来进行 ...

  4. C#WinForm无边框窗体移动方法、模仿鼠标单击标题栏移动窗体位置

    C#WinForm无边框窗体移动方法.模仿鼠标单击标题栏移动窗体位置 这里介绍俩种办法 方法一:直接通过修改窗体位置从而达到移动窗体的效果 方法二:直接伪装发送单击任务栏消息,让应用程序误以为单击任务 ...

  5. nuxt二级路由

    耗费了大半天的时间,终于把页面的二级路由配置好了 先看我的目录 如果没有登陆页,根本就不用考虑嵌套路由的问题,主要的menu跳转和<nuxt />可以直接写到layouts/default ...

  6. js中 switch 注意事项

    var x = "2"; // 字符串 “2” switch (x) { case 1: console.log('x 等于1'); break; case 2: // 数值 2 ...

  7. 查看 java 中的编译的字节码文件

    javap -c Atomicity ---------- javap -c 产生的字节码文件---------- Compiled from "Atomicity.java" p ...

  8. 23、svn与打飞机

    svn与git 打飞机 css *{margin:0; padding:0;} html,body{width:100%; height:100%; overflow: hidden;} .main{ ...

  9. 百度地图API密钥

    百度地图API密钥 DD279b2a90afdf0ae7a3796787a0742e nSxiPohfziUaCuONe4ViUP2N   /*亲测可用*/ PlhFWpA02aoURjAOpnWcR ...

  10. java学习(三)--- 修饰符

    访问修饰符: default.public.private.protected 非访问修饰符 static: 静态方法,静态变量 final: final变量: final变量能够显示的初始化并且只能 ...