扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:DelphiCodeHome 来源:blog.csdn.net/DelphiCodeHome 2007年9月15日
关键字: 软件
Delphi的消息处理流程
TApplication.OnMessage只在应用程序的消息队列接收到一个消息时才被触发。一般应用程序接收到的消息是与窗口管理有关的消息(例如WM_PAINT和WM_SIZE),或由PostMessage()、PostAppMessage()或BroadcastSystemMessage()等API函数发送出的消息。但是,由于Windows或SendMessage()有可能会绕过消息队列直接将消息发送给窗口过程。当发生这种情况时,TApplication.OnMessage就不会被触发。
VCL的消息系统:
VCL定义了消息分发系统,该系统将所有的Windows消息传给相应的对象,由各对象的消息分发系统进行处理。
VCL对象用于接受消息的方法叫做MainWndProc()。通过MainWndPorc()可以对消息进行任何的处理。不过,一般情况下很少直接调用MainWndProc()来处理消息,除非不想让消息通过VCL的消息系统分发。
从MainWndProc()反回后,消息被传递给对象的WndProc()的方法,这就是该对象的窗体
过程,然后进入VCL的分发机构。分发机构使用Disptch()方法把消息分发给一个消息句柄。
消息到达该消息的处理句柄(Handler)后,经过该句柄的处理,这个消息处理过程就结束
了。事件--MainWndProc---WndProc----Dispatch----Handle
在平时写程序时,总是碰到窗体(TForm)与线程(TThread)消息通信问题。令人烦恼的是窗体不能向线程(TThread)发送消息(线程没有窗口句柄)。经过几天的折腾,想出二种解决方案,拿出来跟大家探讨探讨。
第一。我们知道VC++ 中的MFC类库是自已封装了消息处理(BEGINMESSAGE, ENDMESSAGE),在MFC中对消息的处理是通过建立一张消息映射表,而把方法(function)或过程(procedure)的地址保存到映射表里(消息处理实质上是方法或过程的调用),再加上一个消息分发机制,来实现消息的接收发送 <详见VC++技术内幕>。所以我们只要为线程里建立一张消息映射表,并建立相应的消息分发机制。这样就可以处理窗体发送到线程的消息。以下代码是实现消息映射表和消息分发的类(详见 <..\消息处理设计(线程)1\MessageHandle.pas> 中 )
unit MessageHandle;interface
uses messages,Classes,SysUtils,Dialogs;
const PMSG_BASE = $BE00; //自定义消息基址;
PMSG_NUM = 200; //消息表大小;
{**自定义消息处理类
*;功能 = 建立自定义消息表,处理线程之间 * 以及与主窗体之间的自定义消息(宏观)
*}
//消息处理句柄
TMessageHandle = procedure(var Message: TMessage) of Object;
TPDispatcher = class(TObject)
private
//消息对应表(消息ID为数组下标); MessageHandles: array of TMessageHandle;
//从消息ID得到数组ID
function GetIndexFromMsgID(const aMessageID: cardinal): Integer;public
constructor Create;
destructor Destroy;
//发送消息
procedure SendMessage(var Message: TMessage); overload;
//添加自定义消息到消息对应表;
procedure AddHandle(const aMessageID: cardinal; aMessageHandle: TMessageHandle);
end;
//
implementation
{ TPDispatcher }
constructor TPDispatcher.Create;
var i: Integer;
begin
SetLength(MessageHandles,PMSG_NUM); //200个消息的消息对应表
//初始化消息队列;
for i := 0 to Pred(PMSG_NUM) do
MessageHandles[i] := nil;
end;
destructor TPDispatcher.Destroy;
begin{释放消息对应表}
FreeAndNil(MessageHandles);
end;
procedure TPDispatcher.AddHandle(const aMessageID: cardinal;aMessageHandle: TMessageHandle);
var tID: Integer;
begin
tID := GetIndexFromMsgID(aMessageID);
Assert((tID > 0) or (tID < Pred(PMSG_NUM)) );
Assert(Assigned(aMessageHandle));
MessageHandles[tID] := aMessageHandle;
end;
function TPDispatcher.GetIndexFromMsgID(const aMessageID: cardinal): Integer;begin
Result := aMessageID - PMSG_BASE;
end;
procedure TPDispatcher.SendMessage(var Message: TMessage);
var tID: Integer;
tMsgHandle: TMessageHandle;
begin
tID := GetIndexFromMsgID(Message.Msg);
Assert((tID > 0) or (tID < Pred(PMSG_NUM)));
tMsgHandle := MessageHandles[tID];
if Assigned(tMsgHandle) then
tMsgHandle(Message);
end;
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者