VSOFT.MESSAGGES是一种Libary,提供了用于Delphi应用程序的内部同步/异步发布/订阅消息系统。
该图书馆被Final Builder使用,并且已经运行良好了很多年。
该库利用了TObject.Dispatch和动态方法,这些方法是在Delphi 1.0中引入的。调度方法是如何将Windows消息派发到Tobject后代的消息处理程序方法。
虽然最初是为了派遣Windows消息而添加了TObject.Dispatch ,但实际上并未绑在Windows上。这意味着该库应在Delphi支持的任何平台上使用。也就是说,我只在Win32/Win64(VCL和FMX)上对此进行了测试。
消息定义为记录,并带有msgid字段。
// create a unique message id.
// on windows this needs to be higher than WM_USER
const PROJECT_OPENED_MSG = WM_USER + $ 1000 ;
type
TProjectOpenedMessage = record
MsgID : TMessageID;
Filler : TMessageFiller;
// payload starts here.
ProjectName : string;
public
constructor Create( const theProjectName : string);
end ;
implementation
constructor TProjectOpenedMessage.Create( const theProjectName : string);
begin
MsgID := PROJECT_OPENED_MSG; // assign our message id
ProjectName := theProjectName; // store the payload.
end ;
TMessageID定义为TMessageID = Cardinal;
仅当您要处理VCL或FMX(Windows)应用程序中的消息时,才需要“填充”字段,然后仅当您在表单,帧或Wincontrols上处理它们时,即带有WindProc的任何内容。这是因为TControl , TWinControl和TCustomForm中的Defaulthandler将消息参数投入到TMessage 。如果您在其他平台上使用了此功能,则可以将Word用于MSGID字段,因为这就是TObject.Dispatch使用的所有内容
消息是通过通道对象发送的。要创建频道,请使用TMessageChannelFactory.CreateChannel方法
var
channel : IMessageChannel;
begin
channel := TMessageChannelFactory.CreateChannel;
...例子 :
procedure SendProjectOpenedMessage ( const projectName : string)
var
msg : TProjectOpenedMessage;
begin
msg := TProjectOpened.Create(projectName);
FChannel.Queue.PostMessage(msg); // async
// or
FChannel.Queue.SendMessage(msg); // sync
end ;请注意, PostMessage和SendMessage在频道上的原因纯粹是为了围绕Delphi中的通用限制工作,在Delphi中,非传播接口无法具有通用方法(记录可以,因此排队实际上是记录)。
Queue.PostMessage会异步发送消息,即在接收到消息之前返回的方法。
所有调度员都完成了邮件后, Queue.SendMessage返回。注意SendMessage不应用于将消息发送给在用户界面上操作的调度程序,而是使用PostMessage 。
要使对象接收消息,它需要创建一个调度程序,并将调度程序挂接到自身和频道
type
TReceiver = class
private
FDispatcher : IMessageDispatcher;
public
constructor Create( const channel : IMessageChannel);
end ;
implementation
constructor TReceiver.Create( const channel : IMessageChannel);
begin
FDispatcher := TMessageDispatcherFactory.CreateDispatcher;
// tell the dispatcher where to dispatch the messages to.
FDispatcher.Target := Self;
// hook up the dispatcher to the channel.
FDispatcher.Channel := channel;
end ;
注意:如果要在将要更新UI更新的表单/帧/控件上处理消息,则应使用TMessageDispatcherFactory.CreateUIDispatcher这确保仅在主线程上派出消息(呼叫tthread.queue)。出于性能原因,不应将CreateUidisPatcher用于非UI代码,并且您应该避免使用太多挂在同一频道上的UI调度器。
处理消息就像在Delphi中处理Windows消息
type
TReceiver = class
private
...
procedure ProjectOpened ( var msg : TProjectOpenedMessage); message PROJECT_OPENED_MSG;
...
end ;
implementation
procedure TReceiver.ProjectOpened ( var msg : TProjectOpenedMessage);
begin
// use msg.ProjectName payload here.
end ;