在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
两类主要消息处理函数: 1)向自身分发消息,由自己的成员函数处理:Dispatch(var message:string); 同步 2)向指定的类投递消息: a)SendMessage 异步投递 b)PostMessage 同步投递
一.自定义消息号和消息结构 const WM_5001=WM_USER+5001; WM_5002=WM_USER+5002; WM_5003=WM_USER+5003; WM_6001=WM_USER+6001; type //自定义消息结构 PMsgRec = ^TMsgRec; TMsgRec = record msgNo : Cardinal; msgText: string; end;
二.消息分发 向特定的对象分发消息:Dispatch函数 原理: 在TObject类中,有一个Dispatch()方法和一个DefaultHandler()方法,它们都是与消息 消息接收类:TMsgAccepter //自定义消息接收类 TMsgAccepter=class private procedure Msg5001Accepter(var msg:TMsgRec); message WM_5001; public procedure defaultHandler(var message); override; end; implementation uses Main; { TMsgAccepter } procedure TMsgAccepter.Msg5001Accepter(var msg: TMsgRec); begin FrmMain.Memo1.Lines.Add('接收类已收到5001消息,并对其进行了处理!') end; procedure TMsgAccepter.defaultHandler(var message); var theMsg:TMsgRec; begin theMsg:=TMsgRec(message); FrmMain.Memo1.Lines.Add('接收类收到消息请求,但该消息号无指定处理函数!消息号为:'+IntToStr(theMsg.msgNo)); end; a)向对象theMsgAccepter分发消息WM_5001(有对应处理函数) var theMsg:TMsgRec; begin theMsg.msgNo:=WM_5001; theMsg.msgText:=''; theMsgAccepter.Dispatch(theMsg); end; 运行结果:
b)向对象theMsgAccepter分发消息WM_6001(无对应处理函数) var theMsg:TMsgRec; begin theMsg.msgNo:=WM_6001; theMsg.msgText:=''; theMsgAccepter.Dispatch(theMsg); end; 运行结果:
三.消息投递:向特定窗口投递消息 消息响应窗口:TFrmMsgProcess TFrmMsgProcess = class(TForm) Memo1: TMemo; procedure FormCreate(Sender: TObject); private { Private declarations } procedure Msg5002Accepter(var msg:TMessage); message WM_5002; procedure Msg5003Accepter(var msg:TMessage); message WM_5003; public { Public declarations } end; var FrmMsgProcess: TFrmMsgProcess; implementation uses Main; {$R *.dfm} { TFrmMsgProcess } procedure TFrmMsgProcess.Msg5002Accepter(var msg:TMessage); var pTheMsg:PMsgRec; begin Self.Memo1.Lines.Add('窗口已收到5002号消息,并开始进行处理。。。'); Self.Memo1.Lines.Add('窗口收到的字符串参数信息为:'+String(msg.WParam)); pTheMsg:=PMsgRec(msg.LParam); Self.Memo1.Lines.Add('窗口收到的结构体参数信息为:'+pTheMsg.msgText); Self.Memo1.Lines.Add('窗口对5002号消息的处理已完成!'); end; procedure TFrmMsgProcess.FormCreate(Sender: TObject); begin self.Memo1.Color:=clblack; self.Memo1.Font.Color:=clgreen; end; procedure TFrmMsgProcess.Msg5003Accepter(var msg: TMessage); begin FrmMain.Memo1.Lines.Add('窗口已收到5003号消息,并开始进行处理。。。'); Sleep(1000); FrmMain.Memo1.Lines.Add('窗口对5003号消息的处理已完成!'); end; a)异步方式:Postmessage,发出后不等待,直接返回 begin Self.Memo1.Lines.Add('主线程向子窗口发送5003号消息。。。'); PostMessage(FrmMsgProcess.Handle,WM_5003,0,0); Self.Memo1.Lines.Add('主线程消息发送函数已结束!'); end; 运行结果: b)同步方式:SendMessage,等窗口响应后,再返回 begin Self.Memo1.Lines.Add('主线程向子窗口发送5003号消息。。。'); SendMessage(FrmMsgProcess.Handle,WM_5003,0,0); Self.Memo1.Lines.Add('主线程消息发送函数已结束!'); end; 运行结果:
c)带参数信息的消息投递 发送“字符串或结构体”时,尽可能用sendMessage,否则,可能内存中的内容 已被更改,而窗口消息响应函数还未处理。 var msgStr:string; theMsg:TMsgRec; begin msgStr:='WM_5002消息的字符串说明'; theMsg.msgNo:=WM_5002; theMsg.msgText:='WM_5002消息的结构体说明'; SendMessage(FrmMsgProcess.Handle,WM_5002,WParam(PChar(msgStr)),LParam(@theMsg)); end; 运行结果:
PS:以上均是在同一个进程里投递消息,若在不同进程间投递消息,则必须使用“内存映射文件”存储字符 串或结构体消息,而不是直接放在消息参数sparam和lparan中,那样会出现地址空间访问冲突的问题。 四.其他 a)wparam与lparam wParam: 原win16系统中,word类型的整数,16位;现在的win32系统中,扩展为32位整型。 注:WPARAM常常代表一些控件的ID或者高位底位组合起来分别表示鼠标的位置,如果 消息的发送者需要将某种结构的指针或者是某种类型的句柄时,习惯上用LPARAM来传递。 b)常用消息处理函数 Peekmessage() 从消息队列中读消息 c)窗口过程函数 从消息队列中取消息 d)消息路由 e)参考界面 线程安全 http://blog.csdn.net/danscort2000/article/details/2780418 ——原理 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论