下面是按照书中例子写的:
首先是TDispatcher类,负责储存所有处理消息的方法
unit untDispatcher;
interface
uses
Messages;
const
MY_BASE = $BE00;
MY_MSG1 = MY_BASE + 01;
MY_MSG2 = MY_BASE + 02;
type
TMessageHandler = procedure (var aMessage: Tmessage) of object;
TDispatcher = class
private
Handles: array[0..100] of TMessageHandler;
function GetBaseIndex(const iMessageID: Integer): Integer;
procedure DoAddHandler(const iMessageID: Integer; aHandle: TMessageHandler);
public
constructor create;
procedure SendMessage(var aMessage: TMessage);
function AddHandle(const iMessageID: Integer; aHandle: TMessageHandler): Integer;
end;
implementation
{ TDispatcher }
function TDispatcher.AddHandle(const iMessageID: Integer; aHandle: TMessageHandler): Integer;
begin
Result := GetBaseIndex(iMessageID);
if Result <> -1 then
DoAddHandler(Result, aHandle);
end;
constructor TDispatcher.create;
var
I: Integer;
begin
for I := 0 to 100 do
begin
Handles[I] := nil;
end;
end;
procedure TDispatcher.DoAddHandler(const iMessageID: Integer; aHandle: TMessageHandler);
begin
Handles[iMessageID] := aHandle;
end;
function TDispatcher.GetBaseIndex(const iMessageID: Integer): Integer;
begin
Result := iMessageID - My_BASE;
end;
procedure TDispatcher.SendMessage(var aMessage: TMessage);
var
msgHdl: TMessageHandler;
begin
msgHdl := Handles[GetBaseIndex(aMessage.Msg)];
if Assigned(msgHdl) then
msgHdl(aMessage);
end;
end.
下面是主窗体,其中MyHandles里随便定义了两个消息方法,通过点击按钮btnOK将这两个方法以及所对应的消息,储存在FDispatcher里。最后点击按钮1和按钮2,查看消息的处理结果。
unit MainFrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, untDispatcher;
type
MyHandles = class
public
procedure MyHandle1(var aMessage: TMessage);
procedure MyHandle2(var aMessage: TMessage);
end;
TMainForm = class(TForm)
btnOK: TButton;
mm: TMemo;
btnMsg1: TButton;
btnMsg2: TButton;
procedure btnOKClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnMsg1Click(Sender: TObject);
procedure btnMsg2Click(Sender: TObject);
private
{ Private declarations }
FDispatcher: TDispatcher;
FMyHandles: MyHandles;
public
{ Public declarations }
procedure AddMm(const s: string);
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
{ TMainForm }
procedure TMainForm.AddMm(const s: string);
begin
mm.Lines.Add(s);
end;
{ MyHandles }
procedure MyHandles.MyHandle1(var aMessage: TMessage);
begin
MainForm.AddMm('aaaaaaaaaaa1');
end;
procedure MyHandles.MyHandle2(var aMessage: TMessage);
begin
MainForm.AddMm('bbbbbbbbbbbb2');
end;
procedure TMainForm.btnMsg1Click(Sender: TObject);
var
aMessage: TMessage;
begin
FillChar(aMessage, SizeOf(tmessage), 0);
aMessage.Msg := MY_MSG1;
FDispatcher.SendMessage(aMessage);
end;
procedure TMainForm.btnMsg2Click(Sender: TObject);
var
aMessage: TMessage;
begin
FillChar(aMessage, SizeOf(tmessage), 0);
aMessage.Msg := MY_MSG2;
FDispatcher.SendMessage(aMessage);
end;
procedure TMainForm.btnOKClick(Sender: TObject);
begin
FDispatcher.AddHandle(MY_MSG1, FMyHandles.MyHandle1);
FDispatcher.AddHandle(MY_MSG2, FMyHandles.MyHandle2);
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
FDispatcher := TDispatcher.create;
FMyHandles := MyHandles.Create;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
FreeAndNil(FDispatcher);
FreeAndNil(FMyHandles);
end;
end.
下面是程序运行结果:
这是dispatcher,还有broadcast模式,两者结合的话,对消息处理的处理,能发挥的能量更大。比如一个产品主窗体,上面贴着很多窗体,这些窗体都继承自一个基类比如XXForm,XXForm实现了broadcast方法,其中有调用Dobroadcast(虚方法,方便子类重写处理一些业务),然后循环所有包含的窗体执行相同的操作。而在Dobroadcast中,可以使用dispatcher模式,进行消息的处理。这样可以大大减少消息在VCL中的处理流程,加快处理速度。但这种方式,适合处理自定义消息非常多的产品,如果是windows消息或者VCL中的消息,以VCL framework一秒钟执行好几万条消息的处理速度,大可不必这么麻烦。
procedure TXXForm.Broadcast(const AMessage: TMessage; var AHandled: Boolean);
var
I: Integer;
begin
DoBroadcast(AMessage, AHandled);
if AHandled then Exit;
for I := 0 to GetItemCount - 1 do
begin
GetItems(I).Broadcast(AMessage, AHandled);
if AHandled then Break;
end;
end;
以上纯属个人愚见。。。有啥不足,欢迎指正^_^