VSoft.Messaging est un Libary qui fournit un système de messagerie publique / souscrit synchrone / asynchrone interne pour les applications Delphi.
Cette bibliothèque est utilisée par FinalBuilder et fonctionne bien depuis de nombreuses années.
Cette bibliothèque tire parti de TObject.Dispatch et des méthodes dynamiques qui ont été introduites dans Delphi 1.0. La méthode de répartition est la façon dont les messages Windows sont envoyés sur les méthodes de gestionnaire de messages sur les descendants à tobject.
Alors que TObject.Dispatch a été initialement ajouté dans le but de répartir les messages Windows, il n'est pas réellement lié à Windows. Cela signifie que cette bibliothèque devrait fonctionner sur n'importe quelle plate-forme que Delphi prend en charge. Cela dit, je ne l'ai testé que sur Win32 / Win64 (VCL et FMX).
Les messages sont définis comme des enregistrements, avec un champ 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 est défini comme TMessageID = Cardinal;
Le champ de remplissage n'est nécessaire que si vous gérez des messages dans les applications VCL ou FMX (sur Windows), et seulement si vous les manipulez sur des formulaires, des cadres ou WinControls, c'est-à-dire quelque chose avec un WindProc. TWinControl TControl TCustomForm TMessage Si vous utilisez cela sur d'autres plates-formes, vous pouvez utiliser Word pour le champ msgide, car c'est tout ce qui est utilisé par TObject.Dispatch
Les messages sont envoyés via un objet de canal. Pour créer un canal, utilisez la méthode TMessageChannelFactory.CreateChannel
var
channel : IMessageChannel;
begin
channel := TMessageChannelFactory.CreateChannel;
...Exemple :
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 ; Notez que la raison pour laquelle le PostMessage et SendMessage sont sur la propriété Channel.queue est purement pour contourner les limitations génériques de Delphi, où les interfaces non génériques ne peuvent pas avoir de méthodes génériques (les enregistrements peuvent, donc la file d'attente est en fait un enregistrement).
Queue.PostMessage envoie le message de manière asynchrone, c'est-à-dire que la méthode revient avant la réception du message.
Queue.SendMessage revient après que tous les répartiteurs aient terminé la répartition du message. Remarque SendMessage ne doit pas être utilisé pour envoyer des messages aux répartiteurs qui fonctionnent sur l'interface utilisateur, utilisez plutôt PostMessage .
Pour qu'un objet reçoive les messages, il doit créer un répartiteur et accrocher le répartiteur à lui-même et au canal
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 ;
Remarque: Si vous gérez des messages sur des formulaires / cadres / contrôles où vous ferez des mises à jour d'interface utilisateur, vous devez utiliser TMessageDispatcherFactory.CreateUIDispatcher - Cela garantit que les messages ne sont envoyés que sur le thread principal (appelle tthread.queue). Pour des raisons de performances, CreateUidispatcher ne doit pas être utilisé pour le code non intermédiaire, et vous devez éviter d'utiliser trop de répartiteurs d'interface utilisateur accrochés au même canal.
Gestion des messages, c'est comme gérer les messages 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 ;