关于Windows消息的发送和接收入门

关于Windows消息的发送和接收入门 

1.     发送消息

PostMessage 
函数功能:该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回,是异步消息模式。 
消息队列里的消息通过调用GetMessage和PeekMessage取得。 
函数原型: 
B00L PostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 
参数 
hWnd:其窗口程序接收消息的窗口的句柄。可取有特定含义的两个值: HWND_BROADCAST:消息被寄送到系统的所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口。消息不被寄送到子窗口。NULL:此函数的操作和调用参数dwThread设置为当前线程的标识符PostThreadMessage函数一样。 
Msg:指定被寄送的消息。如WM_USER 
wParam:指定附加的消息特定的信息 
IParam:指定附加的消息特定的信息。 
详情参考:http://baike.baidu.com/view/1080179.htm

 

自定义消息: 
每种消息WINDOWS用一个宏来表示 
具体参考:http://baike.baidu.com/view/2421603.htm 
其中WM_USER = $0400 之后一般为自定义用的消息,具体范围定义如下:

Range                                           Meaning 
0 through WM_USER - 1          Messages reserved for use by Windows. 
WM_USER through 0x7FFF      Integer messages for use by private window classes. 
0x8000 through 0xBFFF            Messages reserved for future use by Windows. 
0xC000 through 0xFFFF            String messages for use by applications. 
Greater than 0xFFFF                  Reserved by Windows for future use. 

DELPHI Example: 
// 用FindWindow获得窗体句柄 
PostMessage(FindWindow(nil, '接受消息'), WM_USERJQ, 1, 2); 
这样的方法通常发送到指定的进程。

 发送消息的另一种方法,是用广播的方式,也就是将这个消息广播出去,“所有的进程”都会收到。但这样的方法要注意两点。 
1.       要先在系统注册这个消息 
2.       用SendMessage()代替PostMessage() (或者用BroadcastSystemMessage) 
为什么要用SendMessage呢?这里设计到这两个函数之间的差别。

 SendMessage 
该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。 
函数原型: 
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam); 
和PostMessage不同的主要是返回值: 
返回值:返回值指定消息处理的结果,依赖于所发送的消息。 
备注:需要用HWND_BROADCAST通信的应用程序应当使用函数RegisterWindowMessage来为应用程序间的通信取得一个唯一的消息。 
详情参考:http://baike.baidu.com/view/1080187.htm

PostMessage 是异步的 
SendMessage 是同步的。                                                                      
PostMessage  只负责将消息放到消息队列中,不确定何时及是否处理 
SendMessage  要等到受到消息处理的返回码(DWord类型)后才继续 
PostMessage  执行后马上返回 
SendMessage  必须等到消息被处理后才会返回。 

DELPHI Example 
FJqMessage : DWORD; 
// 注册消息 
FJqMessage := RegisterWindowMessage('JQ_MESSAGE'); 
// 发送消息 
SendMessage(HWND_BROADCAST, FJqMessage, 3, 4);

 这样就可以把消息广播出去了 
以下附上Delphi 写的一个例子单元 

 

[delphi] view plaincopy
  1. // 发送消息  Jiao.Qi Create 10-10-26  
  2. unit ufrmPostMessage;  
  3.   
  4. interface  
  5.   
  6. uses  
  7.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  8.   Dialogs, StdCtrls;  
  9.   
  10. const  
  11.   WM_USERJQ = WM_USER + 1024;  
  12.   
  13. type  
  14.   TfrmMessageUse = class(TForm)  
  15.     btnPostMessage: TButton;  
  16.     btnPostMessageBroadCast: TButton;  
  17.     procedure btnPostMessageClick(Sender: TObject);  
  18.     procedure FormCreate(Sender: TObject);  
  19.     procedure btnPostMessageBroadCastClick(Sender: TObject);  
  20.   private  
  21.     FJqMessage : DWORD;  
  22.   public  
  23.   
  24.   end;  
  25.     
  26. var  
  27.   frmMessageUse: TfrmMessageUse;  
  28.   
  29.   
  30. implementation  
  31.   
  32. {$R *.dfm}  
  33.   
  34. //==============================================================================  
  35. // 直接POST发送:  
  36. //==============================================================================  
  37.   
  38. procedure TfrmMessageUse.btnPostMessageClick(Sender: TObject);  
  39. begin  
  40.   PostMessage(FindWindow(nil'接受消息'), WM_USERJQ, 12);  
  41. end;  
  42.   
  43.   
  44. //==============================================================================  
  45. // SEND广播发送:  
  46. //==============================================================================  
  47.   
  48. procedure TfrmMessageUse.FormCreate(Sender: TObject);  
  49. begin  
  50.   // 广播的方式,必须先注册  
  51.   FJqMessage := RegisterWindowMessage('JQ_MESSAGE');  
  52. end;  
  53.   
  54. procedure TfrmMessageUse.btnPostMessageBroadCastClick(Sender: TObject);  
  55. begin  
  56.   SendMessage(HWND_BROADCAST, FJqMessage, 34);  
  57. end;  
  58.   
  59. end.  
  

2.     接收消息

 接收消息一般有3个函数: 
GetMessage 
PeekMessage 
WaitMessage 

看一下VC的常用消息处理方式: 

  while(GetMessage(&msg, NULL, 0, 0))   {            if(!TranslateAccelerator(msg.hWnd, hAccelTable, &msg))            {                      TranslateMessage(&msg);                      DispatchMessage(&msg);            }     }

详情参考:http://baike.baidu.com/view/1651356.htm

那我们现在看一下用DELPHI的一般自定义消息处理方式 
一种方法是编写自己定义的消息处理函数:

DELPHI Example 
    // 处理常量消息 
    procedure GetMessage(var Msg: TMessage); message WM_USERJQ; 
这样的方法只能处理常量消息,也就是处理已知的WM_USERJQ 
还有一种方式就是重载窗口消息过程, 它可以处理常量或变量消息

DELPHI Example 
    // 重载窗口消息过程, 可以处理常量或变量消息; 
    procedure WndProc(var Msg:TMessage); override;      
这样我们可能获得窗口可接受的“所有消息”了

 以下同样附上Delphi 写的一个例子单元: 

[delphi]  view plain copy
  1. // 接收消息  Jiao.Qi Create 10-10-26  
  2. unit ufrmGetMessage;  
  3.   
  4. interface  
  5.   
  6. uses  
  7.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  8.   Dialogs, StdCtrls;  
  9.   
  10. const  
  11.   WM_USERJQ = WM_USER + 1024;  
  12.   
  13. type  
  14.   TfrmGetMessage = class(TForm)  
  15.     Label1: TLabel;  
  16.     procedure FormCreate(Sender: TObject);  
  17.   private  
  18.     FJqMessage : DWORD;  
  19.   public  
  20.     // 处理常量消息  
  21.     procedure GetMessage(var Msg: TMessage); message WM_USERJQ;  
  22.     // 重载窗口消息过程, 可以处理常量或变量消息;  
  23.     procedure WndProc(var Msg:TMessage); override;  
  24.   end;  
  25.   
  26. var  
  27.   frmGetMessage: TfrmGetMessage;  
  28.   
  29. implementation  
  30.   
  31. {$R *.dfm}  
  32.   
  33. { TfrmGetMessage }  
  34.   
  35. //==============================================================================  
  36. // 接受方式一:  
  37. //==============================================================================  
  38. procedure TfrmGetMessage.GetMessage(var Msg: TMessage);  
  39. begin  
  40.   ShowMessage(' 处理常量消息: ' + #13#10 +  
  41.               ' LParam = ' + IntToStr(Msg.LParam) + #13#10 +  
  42.               ' WParam = ' + IntToStr(Msg.WParam));  
  43. end;  
  44.   
  45.   
  46. //==============================================================================  
  47. // 接受方式二:  
  48. //==============================================================================  
  49. procedure TfrmGetMessage.FormCreate(Sender: TObject);  
  50. begin  
  51.   FJqMessage := RegisterWindowMessage('JQ_MESSAGE');  
  52. end;  
  53.   
  54. procedure TfrmGetMessage.WndProc(var Msg: TMessage);  
  55. begin  
  56.   if Msg.Msg = FJqMessage then  
  57.   begin  
  58.     ShowMessage(' 重载窗口消息过程处理消息: ' + #13#10 +  
  59.                 ' LParam = ' + IntToStr(Msg.LParam) + #13#10 +  
  60.                 ' WParam = ' + IntToStr(Msg.WParam));  
  61.   end;  
  62.   inherited WndProc(Msg);  
  63. end;  
  64.   
  65. end.  
  

 参考资料:

PostMessage: 
http://baike.baidu.com/view/1080179.htm 
SendMessage: 
http://baike.baidu.com/view/1080187.htm 
windows消息: 
http://baike.baidu.com/view/2421603.htm 
SendMessage和PostMessage的区别: 
http://apps.hi.baidu.com/share/detail/10329823 
delphi中Message消息的使用方法: 
http://blog.csdn.net/delphi1234/archive/2008/02/20/2110083.aspx 
GetMessage PeekMessage WaitMessage 
http://baike.baidu.com/view/1651356.htm





FindWindow(
  lpClassName,        {窗口的类名}
  lpWindowName: PChar {窗口的标题}
): HWND;              {返回窗口的句柄; 失败返回 0}

//FindWindowEx 比 FindWindow 多出两个句柄参数:
FindWindowEx(
  Parent: HWND;     {要查找子窗口的父窗口句柄}
  Child: HWND;      {子窗口句柄}
  ClassName: PChar; {}
  WindowName: PChar {}
): HWND;
{
如果 Parent 是 0, 则函数以桌面窗口为父窗口, 查找桌面窗口的所有子窗口;
如果  是 HWND_MESSAGE, 函数仅查找所有消息窗口;
子窗口必须是 Parent 窗口的直接子窗口;
如果 Child 是 0, 查找从 Parent 的第一个子窗口开始;
如果 Parent 和 Child 同时是 0, 则函数查找所有的顶层窗口及消息窗口.
}

 
 
//测试1: 试着找找新建程序主窗口的句柄 var   h: HWND; begin   {现在我们知道窗口的标题是: Form1、窗口的类名是: TForm1}   h := FindWindow('TForm1', 'Form1');   ShowMessage(IntToStr(h));      {656180; 这是随机, 每次启动窗口肯定不一样}   {假如不知道类名}   h := FindWindow(nil, 'Form1');   ShowMessage(IntToStr(h));      {656180}   {假如不知道标题名}   h := FindWindow('TForm1', nil);   ShowMessage(IntToStr(h));      {656180}   {其实这个窗口的句柄不就是 Self.Handle 吗}   ShowMessage(IntToStr(Handle)); {656180} end;
//测试2: 找计算器窗口的句柄(先打开计算器) var   h: HWND; begin   {如果不是简体中文系统, 这样可能不灵}   h := FindWindow(nil, '计算器');   ShowMessage(IntToStr(h)); {1508334}   {最好这样, 但你得提前知道计算器窗口的类名是: SciCalc}   h := FindWindow('SciCalc', nil);   ShowMessage(IntToStr(h)); {1508334} end;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值