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 ;