在DELPHI中虽然TOBJECT是祖先类,但真正开始消息处理和分发的地方并不是直接由它来负责的。TApplication是整分VCL消息系统的初始点。从processmessages方法开始它从windows的消息队列里读取一条消息,这是在一个while循环中完成的。它的代码如下:
while ProcessMessage(Msg) do可以看到它又读用了另一个方法,这个方法是私有方法。注意processmessage不是processmessages,不要把这两个方法看成是一个。可以看出这个方法一直在不停的调用。而processmessage方法在内部调用一些API来操作消息。(注:Tmsg是一个消息结构,它是真正的对消息结构的封装,而Tmessage消息结构是在vcl内部使用的消息结构,它只是把有用的消息从Tmsg结构提取出来而重新分发的一个消息结构,vcl还提供了更进一步的封装,对于每个重要的消息基本上都提供了相应的专用消息结构,比如说:TWMMouseDown就是一个)首这个方法会把它取出来的消息从系统消息队列中删除,然后再查看如果是wm_quit消息的话就退出执行。如果不是,则去查看Tapplication的OnMessage事件是否为空,如果不是的话则执行些事件。所以一般情况下不要在此事件放入费时的操作,因为此事件实在是太忙了,以至于每秒中有几千条的消息需要经过此事件。然后它再去查看是何种消息。如果没有相应的处理方法。则把消息分发出去。首先得到引消息的方法是窗体过程。这是windows消息系统所要求的。这样由窗体来取得需要这个窗体处理的消息。这是通过句柄来识别的,所以你看句柄真的很消耗系统资源。因为系统需要把这个名柄进行维护和管理。而窗体过程则去给消息分类并调用defwindowproc来取得程序应有的默认行为,然后把分类后的消息转化为vcl内部消息去触发。而最终消息走到最后的终点是defaulthandler在这里你可以做更多的处理。
首先从TMsg结构说起。因为它是直接封装windows消息结构的VCL内部结构类型。它和系统消息结构完全对应。它在windows单元声明。代码如下:
PMsg = ^TMsg;
tagMSG = packed record
hwnd: HWND;
message: UINT;
wParam: WPARAM;
lParam: LPARAM;
time: DWORD;
pt: TPoint;
end;
{$EXTERNALSYM tagMSG}
TMsg = tagMSG;
MSG = tagMSG;
让我们来看看这个结构含义,Hwnd是一个句柄,表示这个消息需要被谁接收处理,实际上Hwnd类型是对应到Longword的一个引强类型声明,这样,编译就会认为Longword和Hwnd不是兼容的类型,而Uint实际也是对应到longword类型。都Lparam和Wparam实际都是longint类型,Dword也是Longword类型。而TPoint是一种结构。大部分的时候它代坐标。vcl把这个类型进行强制类型声明是为了做到和windows系统最大程度上的兼容,同时也照顾了c\c++程序员。因为可以直接使用他们已经习惯了的类型声明。它的成员参数的具体意义如下:message 代表这个消息的IDlParam这个参数据的具体值根据实际的消息类型来决定,比如说它可能是一个代表接键值。
wParam
这个参数的具体意义和用法和lparam差不多。这两个参数就是为了存储消息的附加值的time这个参数表明什么时候把这个消息发送给接收者pt
这代表发送消息的对表的屏幕坐标。
这个结构虽然简单,但却非常的重要,消息就是通过它才得以实现各种功能。
下面讲另一个结构
TMesaage,这个结构只用于VCL对部,并且它兼容于所有特定的消息结构,但不包括Tmsg。而tmsg则真正的兼容所有消息结构。Tmessage结构在messages单元声明,代码如下:
PMessage = ^TMessage;
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;
可以看出它的是个变体结构,是对tmsg结构最了进一点分化的结果。因此这个结构更易使用。它的主要特点就是Result参数,这个参数主要是为了在响应消息时返回给操作系统一个值,虽然不是所有消息都要求有返回值,但还是有一部分要求,比如说WM_Paint消息就是一个。以下是几个特定的消息结构。
TWMKey = packed record
Msg: Cardinal;
CharCode: Word;
Unused: Word;
KeyData: Longint;
Result: Longint;
end; TWMMouse = packed record
Msg: Cardinal;
Keys: Longint;
case Integer of
0: (
XPos: Smallint;
YPos: Smallint);
1: (
Pos: TSmallPoint;
Result: Longint);
end; TWMMouseWheel = packed record
Msg: Cardinal;
Keys: SmallInt;
WheelDelta: SmallInt;
case Integer of
0: (
XPos: Smallint;
YPos: Smallint);
1: (
Pos: TSmallPoint;
Result: Longint);
end; TMSHMouseWheel = packed record
Msg: Cardinal;
WheelDelta: Integer;
case Integer of
0: (
XPos: Smallint;
YPos: Smallint);
1: (
Pos: TSmallPoint;
Result: Longint);
end;
可以看出vcl是如何来封装系统消息的。这样delphi在vcl内部就实现和windows系统消息机制的无逢集成。
解决方案 »
- 请问如何强行释放所有已关闭的程序所残留的内存等资源?类似于微软的那个叫mem.exe的工具,如何入手呢?
- 数据集TClientDataset保存数据时报错,是什么原因!
- ExpressQuantumGrid->如何根据表结构,通过程序方式动态往表中添加字段并显示对应的值,谢谢
- 请问《Delphi 5 编程实例与技巧》和《delphi从入门到精通》的光盘哪里有下载?
- 怎么生成动态数组?
- delphi 中MDI 的问题?在线等
- 有谁做过类似于考试系统的那种软件?
- 如何用delphi创建shortcut?
- !!!Hint 问题!
- 如何写毕业论文
- 困惑多时的问题,怎样写这个统计的SQL语句?
- 如何让SQL SERVER2000 存储过程中的错误信息在DELPHI应用程序中弹出MESSAGE框!
有一点了解。