Delphi中的消息 (转载)
消息是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中的消息 (转载)的更多相关文章
- Delphi中window消息截获的实现方式(2)
Delphi是Borland公司提供的一种全新的WINDOWS编程开发工具.由于它采用了具有弹性的和可重用的面向对象Pascal(object-orientedpascal)语言,并有强大的数据库引擎 ...
- Delphi中的消息截获(六种方法:Hook,SubClass,Override WndProc,Message Handler,RTTI,Form1.WindowProc:=@myfun)good
Windows是一个基于消息驱动的系统,因此,在很多时候,我们需要截获一些消息然后自己进行处理.而VCL系统又有一些特定的消息.下面对我所了解的delphi环境中截获消息进行一些总结. 就个 ...
- Delphi中控制Excel(转载)
用Delphi从数据库中取得资料,然后导出到Excel中做成报表是个不错的选择,因为Excel强大的报表功能那可是没话说前提Delphi中要 uses comobj;var Excel:Variant ...
- Delphi中window消息截获的实现方式(1)
近来笔者在一个项目中需要实现一个功能:模仿弹出菜单的隐藏方式,即鼠标在窗口的非PanelA区域点击时,使得PanelA隐藏. 经过思考,笔者想到通过处理鼠标的点击事件来实现相应功能.但是,究竟由谁 ...
- delphi中Message消息的使用方法
实例1 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls ...
- delphi中Time消息的使用方法
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- Delphi中Message消息的三种使用方法(覆盖WndProc,覆盖消息函数,改写WMCommand)
实例1 unit Unit1; interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Fo ...
- Delphi——Window 消息 - 转载▼
Delphi是Borland公司的一种面向对象的可视化软件开发工具. Delphi集中了Visual C++和Visual Basic两者的优点:容易上手.功能强大,特别是在界面设计.数据库编程.网络 ...
- delphi XE7 中的消息
在delphi XE7的程序开发中,消息机制保证进程间的通信. 在程序中,消息来自: 1)系统: 通知你的程序用户输入,涂画以及其他的系统范围的事件: 2)你的程序:不同的程序部分之间的通信信息. ...
随机推荐
- 居于U2000手机管理光猫,小区运营商FTTH光猫注册神器,MA5680T手机管理,自动添加光猫
此软件居于U2000开发,需要U2000管理支持 主要功能: 光猫查看->上线情况.下线原因.下线时间.光猫重启.光模块发送功能.接收功能.温度 Radius诊断->用户基本信息.拨打电话 ...
- MSSQL和MYSQL数据库降权
在服务器上如果是 system 用户在运行 MySQL ,这个是非常危险的,一旦Mysql 出现漏洞,或被其他模式提权,直接就是 system 权限.所以我们现在要给MySQL降权! 作用:增强服务器 ...
- python 算术运算
1. 算术运算符与优先级 # -*- coding:utf-8 -*- # 运算符含有+,-,*,/,**,//,% # ** 表示^ , 也就是次方 a = 2 ** 4 print '2 ** 4 ...
- jenkins git 之 Advanced clone behaviours
jenins 上的 Git Plugin插件,默认是下载完整的历史版本,随着分支约多,历史版本约多,整个文件会很大,下载常常会超时. 单独的git命令可以使用以下方式来优化 git clone --d ...
- JavaSE assert断言的学习
在Java中,assert关键字是从JAVA SE 1.4 引入的,为了避免和老版本的Java代码中使用了assert关键字导致错误,Java在执行的时候默认是不启动断言检查的(这个时候,所有的断言语 ...
- SQLite可视化工具SQLite studio
特点: 1.轻量级2.独立性,没有依赖,无需安装3.隔离性 全部在一个文件夹系统4.跨平台 支持众多操作系统5.多语言接口 支持众多编程语言6.安全性 事物,通过独占性和共享锁来实现独立事务的处理,多 ...
- C++ Addon Async 异步机制
线程队列: libuv,window 可在libuv官网下载相应版本 opencv: 编译的时候opencv的位数要和 node的bit 一致 兼容electron : node-gyp rebu ...
- rails 杂记 - model 中的exists?
1. exists? 用法 有一段代码 参考 def generate_token(column) begin self[column] = SecureRandom.urlsafe_base64 e ...
- What do cryptic Github comments mean?
LGTM — looks good to me ACK — acknowledgement, i.e. agreed/accepted change NACK/NAK — negative a ...
- myBatis框架_关于怎么获得多表查询的总记录数
<!-- 查找总记录数 --> <select id="billCount" resultType="int"> select coun ...