而在一个Window的Session里面,消息是最为可靠、简单的。那么,如何确定消息被每一个用户侦听到呢?因为在SendMessage或PostMessage时,一般地,对于任何一个别的应用其句柄是无法事先得知的,因此,对任何并行的应用进行广播是确实可行的方法。全局广播句柄在Windows被定义为HWND_BROADCAST。
另外,在进行全局广播时,必须让所广播的消息得到Windows的登记和确认,与私有消息不同的是,全局消息是通过你决定的消息字符串来得到的,也就是该消息是一个你定义的字符串,而消息句柄是由该字符串通过Windows登记后按一定的规则生成的返回值,如果在此之前该消息串已经有别的应用登记过了,那么所有的返回值都是同一值。
消息登记的函数原形如下:
UINT RegisterWindowMessage(
LPCTSTR lpString //消息字串的地址
);
由于RegisterWindowMessage的消息句柄是一个不定数,我们不能简单的定义一个Message消息处理机制来侦听它,也不能放到Application.OnMessage里面来处理,因为Application会把它过滤掉。因此,必须上到Window类定义的原WNDPROC消息处理机制这一最低原始层次来考虑,这可以使用SetWindowLong函数来办到。
下面是一简单的使用。
首先建立一个Form,上面分别放上三个按钮"Register"、"SendMsg"和"Stop".
然后把"SendMsg"和"Stop"的Enabled属性变为False,其意义是登记后方可使用。
如果程序正确运行,就可以看到标题栏改变成“全局消息已收到”。
原程序如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
AppEvnts, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
p edure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementationVar
OldWNDProc : Pointer; //原Window类定义的WNDProc消息处理函数
GlobeMsg : UInt; //全局消息句柄
{$R *.DFM}
function NewWNDProc(uHandle : hWnd; //发送消息的对象句柄
Msg : UInt; //消息句柄
ParamW : UInt; //消息参数W及消息参数L
ParamL : UInt) : LongInt stdcall;
begin
if Msg = GlobeMsg then begin
//侦听到全局消息
Form1.Caption := Receive MEssage Globe Msg;
//告知其后的对象,“我已处理过了"
Result := 0;
end else
//让原函数处理
Result := CallWindowProc(OldWNDProc,
uHandle,
Msg,
ParamW,
ParamL);end;
procedure TForm1.Button1Click(Sender: TObject); // "Register" Buttonbegin
GlobeMsg := RegisterWindowMessage(myTEST); //登记全局消息
if GLobeMsg $#@60;$#@62; 0 then //登记失败为0
OldWNDProc := Pointer(SetWindowLong(Handle,GWL_WNDPROC,LongInt(@NewWNDProc)));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
GlobeMsg := 0;
end;
procedure TForm1.Button2Click(Sender: TObject); // "SendMsg" Buttonbegin
if GlobeMsg $#@60;$#@62; 0 Then SendMessage(HWND_BROADCAST, GlobeMsg, 0,0 ); //让所有人听到
end;
procedure TForm1.Button3Click(Sender: TObject); // "Stop" Buttonbegin
SetWindowLong(Handle,GWL_WNDPROC,LongInt(OldWNDProc));
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin//让Destroy顺利进行
button3Click(Sender);
end;
end.
关注此文的读者还看过: