Delphi的消息处理

原创 2004年02月17日 18:48:00
Delphi是Borland公司的一种面向对象的可视化软件开发工具。 Delphi集中了Visual C++和Visual Basic两者的优点:容易上手、功能强大,特别是在界面设计、数据库编程、网络编程方面更有其独特的优势。

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;

其中,Msg是区别于其他消息的常量值,这些常量值可以是Windows单元中预定义的常量,也可以是用户自己定义的常量。Wparam通常是一个与消息有关的常量值,也可以是窗口或控件的句柄。LParam通常是一个指向内存中数据的指针。

Result是消息处理的返回值。Wparam、Lparam和Result都是32位的,如果想访问其中的低16位或高16位可以分别使用WparamLo、WparamHi、 LParamLo、LparamHi、ResultLo和ResultHi。

在Delphi中除了通用的Tmessage外,还为每个Windows定义了一个特殊的消息记录。我们可以浏览Message.pas文件,下面是键盘的消息记录:

TWMKey = packed record

Msg: Cardinal;

CharCode: Word;

Unused: Word;

KeyData: Longint;

Result: Longint;

与键盘相关的消息如:WM_KEYDOWN、 WM_KEYUP、 WM_CHAR、 WM_SYSKEYDOWN WM_SYSKEYUP、 WM_SYSCHAR的记录也被定义为TWMkey。在Message.pas文件中有以下声明:

TWMChar=TWMkey; TWMKeyDown=

TWMkey;TWMKeyUp=TWMkey; TWMSys

-KeyDown=TWMkey; TWMSysKeyUp=

TWMkey;TWMSysChar=TWMkey;

消息的发送

消息处理就是定义应用程序如何响应Windows的消息。在Delphi中每一个消息都有自己的处理过程,它必须是一个对象中的方法,且只能传递一个Tmessage或其他特殊的消息记录,方法声明后要有一个message命令,后接一个在0到32767之间的常量。

前面我们提到的消息都是标准的Windows消息(WM_X),除此之外还有VCL内部消息、通知消息和用户自定义消息。

VCL内部消息通常以“CM_”开头,用于管理VCL内部的事物。如果改变了某个属性值或组件的其他一些特性后,需要通过内部消息将该变化通知其他组件。例如,激活输入焦点消息是向被激活的或被停用的组件发送的,用于接受或放弃输入焦点。

另外还有通知消息,一个窗口内的子控件发生了一些事情,需要通知父窗口,这是通过通知消息实现的。它只适用于标准的窗口控件,如按钮、列表框、编辑框等等。打开Message.pas文件,在标准的Windows后就是通知消息的声明:

const

{$EXTERNALSYM BN_CLICKED}

BN_CLICKED = 0;

{$EXTERNALSYM BN_PAINT}

BN_PAINT = 1;

{$EXTERNALSYM BN_HILITE}

BN_HILITE = 2;

以上是按钮的通知消息,分别表示用户单击了按钮、按钮应当重画、用户加亮了按钮。

用户也可以自己定义消息、给自己发送消息和编写消息处理过程。消息的常量值为WM_USER+100到$7FFF, 这个范围是Windows为用户自定义消息保留的。

Delphi消息的发送有三种方法:

1.Tcontrol类的Perform对象方法。可以向任何一个窗体或控件发送消息,只需要知道窗体或控件的实例。其声明如下:

function Tcontrol.Perform(Msg:Cardinal;Wparam,Lparam:Longint):Longint

2.Windows的API函数SendMessage()和Postmessage()。其声明如下:

function SendMessage(hWnd: HWND; Msg: UINT;wParam:WPARAM; lParam: LPARAM):LRESULT;stdcall;

function SendMessage(hWnd: HWND; Msg: UINT;wParam: WPARAM; lParam:LPARAM):LRESULT;stdcall

PostMessage函数将消息添加到应用程序的消息队列中去。应用程序的消息循环会从消息队列中提取登记的该消息,再发送到相应的窗口中。

SendMessage函数可以越过消息队列直接向窗口过程发送。所以当Windows需要立刻返回值时使用SendMessage,当需要不同的应用程序依次处理消息时使用PostMessage。而Perform从本质上和SendMessage相似,它们直接向窗口过程发送。SendMessage、Postmessage函数只需要知道窗口的句柄就可以发送消息,所以它们可以向非Delphi窗体发送一条消息,但而Perform必须知道窗体或控件的实例。

VCL消息处理机制

在Delphi应用程序的源代码中有语句Application.Run,它的作用是启动消息循环,然后调用Application.ProcessMessage,该函数会在应用程序的消息队列中查找一条消息。当在消息队列中检索到一条消息后,触发Application.OnMessage事件。这样在Windows本身对消息处理之前,就会响应OnMessage事件的处理过程,它优于任何消息处理,而且只接收登记的消息,即前面所述的由PostMessage发送的消息。响应Application.OnMessage事件的处理过程必须是TmessageEvent类型,其声明如下:

type TMessageEvent = procedure (var Msg: TMsg; var Handled: Boolean) of object;

其中TMsg是Windows中定义的消息记录,我们可以这样声明:

Procedure OnMyMessage(var Msg:TMsg;var Handled:Boolean);

然后把此方法赋给Application.OnMessage事件:

Application.OnMessage :=OnMyMessage;

OnMessage事件将捕获发送给应用程序的所有消息,这是一个非常繁忙的事件,因此在处理OnMessage事件的处理过程中设置断点进行消息处理是不明智的。

VCL对象用于接收消息的方法叫MainWndProc。它是定义在Twincontrol类中的静态方法,不能被重载。它不直接处理消息,当消息离开MainWndProc后,消息被传递给对象的WndProc方法,WndProc方法是在Tcontrol类中定义的一个虚拟方法,由它调用Dispatch方法。Dispatch根据传入的Message来寻找相应的处理方法,如果最后找不到,就继续向上到父类中寻找消息处理方法,一直到找到为止,如果找不到则调用Defaulthandler。Defaulthandler方法对消息进行最后的处理,然后把消息传递给Windows的DefWindowProc函数或其他默认的窗口过程。

Delphi 的消息机制

=============================================================================== ⊙ 一个 GUI Applicatio...
  • zang141588761
  • zang141588761
  • 2016年09月05日 15:36
  • 1284

Delphi 集合 使用资料收集

集合的使用      (一)       delphi中的集合是对数学中集合的概念的简单实现。要求是集合中的元素必须同类型,且必须是序数类型,且集合中可能的元素个数不能大于255。     定义: t...
  • ainixiaozhuzi
  • ainixiaozhuzi
  • 2013年10月20日 10:12
  • 1111

Delphi xe7并行编程快速入门

现在多数设备、计算机都有多个CPU单元,即使是手机也是多核的。但要在开发中使用多核的优势,却需要一些技巧,花费时间编写额外的代码。好了,现在可以使用Delphi做并行编程了。在Delphi、C++ B...
  • henreash
  • henreash
  • 2014年11月20日 16:19
  • 6866

Delphi中Chrome Chromium、Cef3学习笔记(一)

官方下载地址:https://cefbuilds.com/ CEF简介:     嵌入式Chromium框架(简称CEF) 是一个由Marshall Greenblatt在20...
  • xtfnpgy
  • xtfnpgy
  • 2015年06月25日 13:25
  • 4901

Delphi 的绘图功能

//TPen 的主要属性有四: Color、Width、Style、Mode              {Color: 颜色}              {Width: 宽度; 默认是 1; ...
  • gzxiaorou
  • gzxiaorou
  • 2015年03月22日 15:34
  • 489

Delphi url 编码及转码及特殊字符串替换--百度和腾讯用的就是这个

先介绍一下,Delphi中处理Google的URL编码解码,其中就会明白URL编码转换的方法的 从delphi的角度看Google(谷歌)URL编码解码方式 在网上搜索了一下,似乎没有什么关于goo...
  • Syndicator
  • Syndicator
  • 2014年01月03日 11:59
  • 1954

Delphi 文件处理(4)

9.3.1 文件类型 1.文件类型概念 Delphi使用文件类型来读写存储在外部存储介质上的文件。一个文件变量能够与任意种类的外部设备建立通信,包括磁盘、打印机、键盘、绘图仪、调制解调器等。 ...
  • lailai186
  • lailai186
  • 2013年04月10日 10:01
  • 4850

Delphi实现通用的定时自动关机程序

一、问题的提出:运行某任务的计算机,尤其是服务器,如果能实现在无人职守的情况下,到达指定时间时自动关机,那么将极大地减轻系统管理员的负担,也会给我们的日常工作带来很大方便。    笔者用Delp...
  • my98800
  • my98800
  • 2016年08月29日 09:12
  • 1013

Delphi字符串分隔(似split函数功能)

Delphi字符串实现了和split()函数的功能. unit Unit1; interface uses Windows, Messages, SysUtils, Variant...
  • my98800
  • my98800
  • 2016年12月08日 08:40
  • 1775

[Delphi]内存分配和释放 内存操作函数(4): 清空与填充内存

FillMemory、ZeroMemory 一目了然的两个函数, 但其实它们都是调用了 FillChar; 清空不过就是填充空字符(#0: 编号为 0 的字符), 说来说去是一回事. 为了下面的测...
  • ly930156123
  • ly930156123
  • 2016年09月19日 11:15
  • 1755
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Delphi的消息处理
举报原因:
原因补充:

(最多只允许输入30个字)