Delphi中对消息的处理
刘文彦 张 翔
摘 要:本文对覆盖消息和自定义消息的处理方法进行讨论,总结出两类消息处理的步骤,
并通过例程加以实现。
关键词:Delphi; 消息; 通讯
1. 引言
在Windows操作系统中,可以同时运行多个应用程序,并且保持相对的独立性。Windows和应用程序之间是通过发送消息的方法互相联系。Windows为每一个应用程序建立一个消息队列,当应用程序执行某一操作时,将产生相应的消息事件,Windows将事件放入消息队列中等候应用程序取走,应用程序取走消息后,将执行相应程序命令,处理完毕后再取下一条消息。同时,消息也可以在不同的应用程序中进行传递,这就保证了应用程序之间的相互联系和通讯。
2.消息分析
处理Windows发往各个应用程序的消息是Windows编程的重要内容之一,深刻了解消息的处理方法是编写一个好的应用程序的重要基础。Delphi中提供了对消息的处理方法,并把Windows中的消息转化为自己的组件。消息的处理过程见图1。
图1
在Delphi中处理Windows预定义的消息通常叫覆盖消息,另一类是自定义消息。Windows在消息处理过程中为每一个消息确定了一个消息索引号,其范围是1~49151。Windows保留了1~1024范围。所以,覆盖消息的索引号在1~1024范围内,而自定义的消息就不要与预定义的消息发生冲突。下面对两类消息的处理方法做一说明。
2.1 覆盖消息
覆盖消息是将Windows预定义的消息进行覆盖。覆盖消息的原理是通过给新的消息处理方法赋予原消息索引号。这样,当某个事件产生消息的发生事件时,根据其索引号得到新的消息处理方法。覆盖消息的处理步骤:
1)确定所需处理的消息
确定消息是确定覆盖的系统消息,不同的事件有不同的消息,例如:鼠标单击窗口中的标题栏(窗口中的蓝色彩条)所产生的消息是WM_SYSCOMMAND。
2)在程序中声明所处理的消息(覆盖原消息)
在派生类的protected部分声明消息处理方法,此方法必须是过程:例如:
Procedure mymessage(var msg:Tmessage);
message WM_messageindex;
在protected中声明主要是在该类的封装时将其私有化(只允许该类使用),mymessage为此消息的过程名,用关键字message将WM_messageindex的索引号分配给mymessage,即覆盖WM_messageindex消息。WM_messageindex可以是前面提到的WM_SYSCOMMAND消息。
3)编写消息处理过程
在程序的implementation部分编写消息的实现代码。具体如下:
Procedure mymessage(var msg:Tmessage);
Begin
//所要执行的具体内容。
End;
2.2 自定义消息
自定义消息是声明Windows没有预定义的消息,因为不是预定义的消息,所以要编写程序,发送消息。而且用户可以定义一些本消息自带的参数。通过自定义消息,作者可以编写具有特色的应用程序。
自定义消息的步骤:
1)声明消息的索引号
前面已经提到了消息索引号的范围以及分配情况。在Delphi中常量WM_USER=1024可以用做自定义消息索引号的起始值,如:
const
WM_mymessage=WM_USER+$100;
但要注意的是一些Windows的标准组件已经占用了1024以外的索引号,为了避免这样的冲突,在Delphi中有另处一个常量WM_APP=32768,建议自定义消息的索引号以WM_APP为起点
,如:
const
WM_mymessage=WM_APP+$100
2)定义消息记录类型
在定义完消息的索引号后,还需要定义消息的记录类型。消息记录类型是传送给消息处理方法的参数结构类型。整个消息记录类型共128bits。定义消息记录类型时记录大小不能超出此范围。下面是一个消息记录类型的例子:
Type
TWMmymessage=record
Msg:Cardinal;//该记录对应的消息。
Name:DWORD;//对应参数wParam
Time:DWORD;//对应参数1Param;
Result:Longint;
end;
3)在程序中声明所处理的消息
声明消息的方法和声明覆盖消息的方法是相同的,使用规则也是一样的。
4)编写消息处理过程
和前面提到的覆盖消息处理过程方法一样,可以参考前面的例子进行编写。
5)发送自定义消息
自定义消息不是通过系统发生的某一件事所产生,而是需要我们自己发送到消息队列中。这就涉及到消息的发送问题,在用户发送消息时可以使用下面两个Windows的API函数:
① LRESULT SendMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM 1Param);
② BOOL PostMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM 1Param);
3. 应用程序设计
3.1 程序实例
下面是该程序的部分代码:
unit Unit1;
interface
uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,
shellapi,StdCtrls;//因为要用到Windows//API函数所以在此声明Shellapi
//定义消息索引号
const
WM_mymessage=WM_USER+$100;
//定义消息类型
Type
TWMmymessage=record
Msg:Cardinal;//该记录对应的消息。
Name:DWORD;//对应参数wParam
Time:DWORD;//对应参数1Param;
Result:Longint;
end;
type
TForm1=class(TForm)
Label1:TLabel;
label2:TLabel;
wp:TLabel;
lp:TLabel;
Button1:TButton;
Button2:TButton;
Edit1:TEdit;
Edit2:TEdit;
Procedure Button1Click(Sender:TObject);
Procedure Button2Click(Sender:TObject);
private
{Private declarations}
procedure mytitlemessage(var msg:TWmsyscommand);message
WM_SYSCOMMAND;
Procedure myownermessage(var msg:tWMmymessage);message
WM_mymessage);message
WM_mymessage;
public
{Public declarations}
end;
var
Form1:TForm1;
implementation
{$R*.DFM}
//覆盖消息的处理过程
procedure Tform1.mytitlemessage(var msg:TWmsyscommand);
begin
//得到消息的参数
case msg.CmdType of
SC_CLOSE:showmessage (您单击了关闭按扭);//按了关闭按扭
SC_MAXIMIZE:showmessage (您单击了最大化按扭);//按了最大化按扭
SC_MINIMIZE:showmessage (您单击了最小化按扭);//按了最小化按扭
end;
inherited;
end;
//自定义消息处理
procedure Tform1.myownermessage(var msg:TWMmymessage);
begin
//得到消息的参数
wp.Caption:=inttostr(msg.name);
lp.caption:=inttostr(msg.time);
end;
//用sendmessage函数发送消息
procedure TForm1.Button1Click(Sender:TObject);
var
hwn:hwnd;
begin
//得到当前窗口的句柄
hwn:=findwindow(`tform1',`消息处理');
//其中edit1.text、edit2.text为所要传递
//消息的参数
Sendmessage(hwn,cardinal(WM_mymessage),
strtoint(edit1.text),strtoint(edit2.text);
end;
//用postmessage函数传递消息
procedure Tform1.Button2Click(Sender:TObject);
var
hwn:hwnd;
begin
//得到当前窗口的句柄
hwn:=findwindow('tform1','消息处理');
//其中edit1.text、edit2.text为所要传递//消息的参数
postmessage(hwn,cardinal(WM_mymessage)),
strtoint(edit1.text),strtoint(edit2.text);
end;
end.
3.2 程序说明
该程序实现对标题栏单击事件所产生的消息覆盖,当用户单击标题栏的三个按扭时,弹出对话框提示用户操作。
本程序已在Delphi 5.0和Windows 98中调试通过。
4. 结论
1)应用程序中有许多需要处理的消息,只要知道消息的索引号就可以对发向本应用程序的
消息进行特殊的处理,然后返回其默认的消息参数。比如Windows系统中的关闭操作,向各个应用程序发送的消息是WM-QUERYENDSESSION,这样可以在应用程序中覆盖这个消息来完成关闭程序所需要完成的工作,不影响Windows的正常关闭,而且返回其适当的值可以禁止Windows的关闭。这对制作监控类的应用软件是非常重要的。
2)通过自定义消息,可以实现不同应用程序之间的通讯。在开发具有多个可执行文件的软
件时,可以通过自定义消息来完成两个程序之间的通讯。
参考文献:
[1]朱宏伟。Delphi5.0编程指南。北京:冶金工业出版社。2000.1
[2]新智工作室。Delphi5.0基础与提高。北京:电子工业出版社。2000.3
[3]吕宗智、汪世攀。Delphi实用技术精粹。北京:人民邮电出版社。2000.3
Delphi中对消息的处理相关推荐
- DELPHI 中 Window 消息大全使用详解
Window 消息大全使用详解 导读: Delphi是Borland公司的一种面向对象的可视化软件开发工具. Delphi集中了Visual C++和Visual Basic两者的优点:容易上手.功能 ...
- Delphi中的消息截获
Windows是一个基于消息驱动的系统,因此,在很多时候,我们需要截获一些消息然后自己进行处理.而VCL系统又有一些特定的消息.下面对我所了解的delphi环境中截获消息进行一些总结. 就 ...
- 【Delphi】中使用消息Messages(七)Android 系统消息
前面6节介绍了Delphi中消息机制的基本原理,并通过一个演示程序进行实际演示.本节开始,我讲介绍Delphi开发Android系统时需要使用的一些特殊消息.以下所说系统,泛指Android系统. 一 ...
- 【Delphi】中使用消息Messages(五)Windows消息
目录 Windows消息使用流程 Windows消息注意事项 Dispatch消息使用流程 Dispatch消息注意事项: 上一节讲述了RTL消息,本节讲述下Windows消息.首先看下演示程序如下: ...
- 【Delphi】中使用消息Messages(八)Android 系统消息感知
目录 一.实现android广播消息事件绑定 二.在onReceive中实现接收系统广播消息处理: 三.注册(订阅)系统状态变化消息广播: 四.控件整体定义: 在上一节我提出了两个问题: App中主动 ...
- Delphi中的容器类(二)
TStrings类 出于效率的考虑,Delphi并没有象C++和Java那样将字符串定义为类,因此TList本身不能直接存储字符串,而字符串列表又是使用非常广泛的,为此Borland提供了TStrin ...
- Delphi中的线程类
Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchr ...
- Delphi中静态方法重载还是覆盖的讨论
Delphi中静态方法重载还是覆盖的讨论 新人学习Delphi的时候,容易搞不懂的一个问题,当子类方法和基类方法同名,并且参数也一样的时候,叫做什么呢?是覆盖,还是重载呢? 答案是隐藏父类方法. 一般 ...
- Delphi中多线程用Synchronize实现VCL数据同步显示
概述: VCL实现同步的另一种方法就是调用线程类的Synchronize的过程,此过程需要一个无参数的procedure,故在此procedure中无法传递参数值,但可以通过类的成员来实现.在类的Ex ...
最新文章
- MySQL 重要函数实例
- c语言中的关于数学问题的编程,C语言中具有代表性几种数学问题编程技巧探索.doc...
- mysql无法建立连接_【MySql】mysql无法建立连接或建立连接失败原因分析
- 【图像分割模型】编解码结构SegNet
- 安卓--L2T虚拟连接
- 地理生物高考成绩查询2021,2021北京中考地理生物成绩查询时间【已公布】
- matplotlib(一):散点图
- C#.NET学习笔记7--11---算术运算符,变量赋值,变量的交换,布尔表达式1,布尔表达式2
- APACHE 问题集合
- 1031. 查验身份证(15)-PAT乙级真题
- 【声学检测】基于matlab MFCC+GMM安全事件声学检测系统【含Matlab源码 1699期】
- Python:实现蓝牙通信
- MATLAB中矩阵求和的方法
- 一个不常用的DOM原生API,closest
- STM32F103C8T6移植uC/OS-III基于HAL库超完整详细过程
- 常见的医学图像成像(总)
- ensp启动设备蓝屏_戴尔笔记本蓝屏原因 戴尔笔记本蓝屏解决方法【详解】
- brk系统调用和copy-on-write机制
- PowerBI账户免费注册
- log4j2日志配置不生效
热门文章
- oracle 18c 18.3 学习之五 unplug drop plug pdb
- oracle expdp impdp 数据迁移 备份恢复某个用户数据
- 利用JAVA编写剪刀石头布的程序
- java static的作用
- ChemOffice Professional 16.0新增了哪些功能
- linux系统日志分几个等级,Linux下日志系统详解
- Linux查看系统日志
- 小球弹跳c语言实现实验报告,C语言实现简单弹跳球游戏
- Eclipse错误:找不到或无法加载主类 解决办法
- 网页返回顶部功能实现