中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > 综合其它
Dephi 消息处理机制(2)
作者:佚名 时间:2007-09-20 16:14 出处:csdn 责编:月夜寒箫
              摘要:Dephi 消息处理机制(2)
VCL消息处理机制

 

 

Delphi的消息处理流程

 

TApplication.OnMessage只在应用程序的消息队列接收到一个消息时才被触发。一般应用程序接收到的消息是与窗口管理有关的消息(例如WM_PAINTWM_SIZE),或由PostMessage()PostAppMessage()BroadcastSystemMessage()API函数发送出的消息。但是,由于WindowsSendMessage()有可能会绕过消息队列直接将消息发送给窗口过程。当发生这种情况时,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;

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有