Delphi中消息的特殊处理
对于编写过Windows程序的编程人员来说,对Windows中的消息肯定不会陌生,它是Windows编程中关键的技术内容之一,深刻地理解Windows对消息的处理机制是编制出优秀的Windows应用程序的基础。Delphi提供了大多数常用消息的处理方法,但在某些特定的场合下则需要我们对Windows消息进行一些特殊的处理,如用户需要改变已有消息的处理方法及功能,或自定义消息及编写对应的消息处理方法。现具体介绍如下:
#1 一、覆盖原有消息
覆盖原有的消息处理方法主要用于在我们需要修改原有的Windows消息的时候,它工作的原理就是通过给新的消息处理方法赋予原有消息的消息索引号。这样,当某个事件发生而触发该消息时,根据该消息的索引号所得到的是新的消息的处理方法。具体的编程步骤如下:
1.确定我们所需要处理的消息;
2.声明消息处理方法;
3.编写具体的代码;
下面我们通过一个简单的例子来加以说明,范例程序的运行结果如图1。((图1))

这里是该范例程序的主要部分的源代码:
unit OverMsg
……
private
{ Private declarations }
flagBoolean;//禁止程序在开始运行时就响应WM_PAINT消息
public
Public declarations
protected;//新的消息处理方法,覆盖了WM_PAINT消息
procedure OverMsgPaint (var MsgTWMPaint);message WM_PAINT;
end;
…….
procedure TfrmMain.OverMsgPaint (var Msg:TWMPaint)
begin //通过覆盖WM_PAINT消息来加入我们自己的代码
if flag then
edtMsg.Text:='成功收到Paint消息!'
inherited;
end;
procedure TfrmMain.btnSendMsgClick(Sender: TObject)
begin
flag:=true;
repaint;//发送WM_PAINT消息
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
flag:=false;
end;
end.
#1 二、自定义消息及对应消息
每一条Windows消息都要对应一个消息标识符,自定义消息首先就要声明消息标识符。消息标识符是一个整型常量,它的大小在1~49151之间,而Windows保留了前1023的数值作为系统的消息索引号,自定义消息是不能占用这些索引号的,所以自定义消息的标识符应从1024开始,但有一些Windows标准组件也使用自定义范围内的消息,为了不与它们冲突,我们在自定义消息标识符时从32768开始(即WM_APP常量),声明如下:
const
CM_MYMSG=WM_APP+$100
我们在定义了消息标识之后,还要为此消息指定消息记录类型,消息记录类型是传递给消息处理方法的参数的数据类型。我们也可以使用已经定义的消息记录类型(消息在messages.pas中定义),如果我们需要新的消息记录类型,则可以根据实际情况自行定义,自定义消息记录类型的结构规定如下:
1.消息记录的第一个域命名为Msg,类型为Cardinal(32位无符号类型);
2.定义四个字节对应参数wParam;
3.定义四个字节对应参数lParam;
4.最后一个域命名为Result,数据类型为Longint;
整个消息记录共有128位,其中用户可自已定义的只有中间的64位。它还可以定义为各种数据类型的组合。
下面是一个简单的范例,程序运行如图2。((图2))

范例程序的主要部分的源代码如下:
unit DefMsg;
……
const //定义消息标识符WM_DEFMSG和WM_MYMSG
WM_DEFMSG=WM_APP+$100;
WM_MYMSG=WM_APP+$101;
type //定义消息记录类型
TMyMSG=record
Msg:Cardinal;
nLeft:word;//顺次的32位对应wParam参数
nTop;word:
nRight:word;//接着的32位对应lParam参数
nButtom;word:
Result;Longint://32位返回值,由SendMessage函数取得
end
……
protected
//此处声明自定义消息的处理方法
procedure WMDefMsg(var Msg:TMessage);message WM_DEFMSG
procedure WMMyMsg(var Msg:TMyMSG);message WM_MYMSG
end;
……
procedure TfrmMain.WMDefMsg(var Msg:TMessage);
begin
lblDefMsg.Caption:='成功收到默认的消息,其中wParam='+inttostr(Msg.wparam)+
'lParam='+inttostr(Msg.lParam)+!;
inherited;
end;
procedure TfrmMain.WMMyMsg (var Msg:TMyMsg);
begin
lblMyMsg.Caption:='成功收到自定义的消息,其中nLeft='+inttostr(Msg.nLeft)+
', nTop='+inttostr(Msg.nTop)+', nRight='+inttostr(Msg.nRight)+
', nButtom='+inttostr(Msg.nButtom)+'!'
inherited
Msg.Result :=1;//由SendMessage函数获得返回值
end
procedure TfrmMain.bntDefSendMsgClick(Sender:TObject);
begin://通过PostMessage函数发送WM_DEFMSG消息
PostMessage(Self.Handle ,Cardinal(WM_DEFMSG),4,3);
end
procedure TfrmMain.bntMySendMsgClick(Sender:TObject);
var
wParam,lParam,Result,integer;
begin
wParam:=(50 shl 16)+100;//把16位的nLeft和nTop处理为32位的wParam
lParam:=(80 shl 16)+200;//把16位的nRight和nButtom处理为32位的lParam
//通过SendMessage()函数发送WM_MYMSG消息,并取得返回值
Result:=SendMessage(Self.Handle,Cardinal(WM_MYMSG),wParam,lParam);
if Result>0 then
MessageDlg('发送消息成功!',mtInformation,[mbOK],0);
end;
end.