Vsoft.Messaging - это ливик, которая обеспечивает внутреннюю синхронную/асинхронную систему сообщений о публикации/подписке для приложений Delphi.
Эта библиотека используется FinalBuilder и много лет работает.
Эта библиотека использует преимущества TObject.Dispatch и динамических методов, которые были введены обратно в Delphi 1.0. Метод отправки - это то, как сообщения Windows отправляются на методы обработчика сообщений на потомках Tobject.
Хотя TObject.Dispatch первоначально добавлен с целью отправки сообщений Windows, он на самом деле не привязан к 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. Это связано с тем, что Defaulthandler в TControl , TWinControl и TCustomForm отбрасывает параметр сообщения в 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 находятся на канале. Свойство Queue, заключается в том, чтобы обойти ограничения дженериков в 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 ;
ПРИМЕЧАНИЕ. Если вы обрабатываете сообщения на формах/кадрах/элементах управления, где вы будете делать обновления пользовательского интерфейса, то вам следует использовать TMessageDispatcherFactory.CreateUIDispatcher - это гарантирует, что сообщения направляются только в основном потоке (вызовы tthread.queue). По причинам производительности Createuidispatcher не следует использовать для кода без пользовательского интерфейса, и вы должны избегать использования слишком большого количества диспетчеров пользовательского интерфейса, зацещенных к одному и тому же каналу.
Обработка сообщений похожа на обработку сообщений Windows в Delphi
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 ;