Gestionnaire de server et client dde (dynamic data exchange)

Description

Bonjour,
Cette source contient une classe offrant un interface de gestion de clients et de serveurs DDE.
Pour l'utiliser, il suffit de créer une classe dérivant du gestionnaire. Puis surcharger les méthodes On* suivant les besoins. Un descriptif des méthodes à surcharger suis. Le gestionnaire fourni aussi les mes méthodes d'appels des différentes fonctions de DDE. Aussi décrites.
Le gestionnaire ne gère pas les connections provenant d'un seul client vers de multiple serveurs.
Il ne gère pas non plus les requêtes asynchrones pour l'instant.
Le composant utilise les versions Unicode de l'API DDEML.

Le composant est initialisé à sa création.
Les méthodes étant en portée protégée, il est impossible de les appeler manuellement en dehors du composant sans le dériver.
Ses contructeurs étant aussi protégés, il est impossible de l'instancier directement.

Pour créer un serveur DDE, il faut utiliser le constructeur qui prend une chaîne de caractères en paramètre. Le client utilise le constructeur sans paramètre.
Pour supprimer un serveur ou un client DDE, il suffit d'appeler la méthode IDisposable.Dispose() que le gestionnaire implémente.

Source / Exemple :


/* Dans tout ce qui suit :

  • topic : Désigne le sujet utilisé pour la conversation.
  • item : Désigne le nom de l'élément transmit ou demandé.
  • data : Donnée transmise par l'autre partie.
  • context : Contexte de la conversation créée.
  • sameInstance : Indique si l'autre partie est l'instance courante.
  • baseServiceName : Nom du service.
  • instanceServiceName : Nom de l'instance.
*
  • Valeurs de retour :
  • - bool : true si réussi sinon false.
  • - DDE : DDE.FACK si traité, DDE.FBUSY si le server est trop occupé, DDE.FNOTPROCESSED si non traité.
  • - IntPtr : Donnée de retour.
  • /
/********************************************
  • Énumérations très utilisées
                                                                                        • /
ClipboardFormat : Format du presse papier utilisé pour les données transmises. DDE : Valeur de retour de certaines transaction. Seul les valeurs FACK, FBUSY et FNOTPROCESSED sont utilisées. XTYPF : Modificateur de l'état de transaction pour AdvStart. La valeur NONE pour l'état normal, NODATA pour mettre en attente les données, ACKREQ pour l'attente d'une prise en compte. /////////////// // Warning ! // /////////////////////////////////////////////////////// // Faites attention à ne pas mélanger les différents // // types de valeur IntPtr. Il y a les Conversations, // // les Chaînes DDE et les données DDE. // /////////////////////////////////////////////////////// /********************************************
  • Messages client
                                                                                        • /
// Client Message XTYP_ADVDATA. // Le serveur a envoyer des données dans le contexte d'une conversation Advise. DDE OnAdvData(ClipboardFormat uFormat, string topic, string item, IntPtr data) // Client Message XTYP_XACT_COMPLETE. // Le serveur a fini une transaction asynchrone. // Le paramètre donnée est du type de donnée retournée par la transaction, voir les messages serveur. // transactionID fourni l'identifiant de transaction asynchrone donné lors de l'exécution de celle-ci. void OnXactComplete(ClipboardFormat uFormat, string topic, string item, IntPtr data, uint transactionID) /********************************************
  • Messages serveur
                                                                                        • /
// Server Message XTYP_ADVREQ. // Des données doivent être envoyées par le serveur. Déclencher par l'appel de PostAdvise() par le server. // Le format fourni est celui demandée par lors de la création de la transaction Advise. IntPtr OnAdvReq(ClipboardFormat uFormat, string topic, string item) // Server Message XTYP_ADVSTART. // Le client a demmandé l'initialisation d'une transaction advise. bool OnAdvStart(ClipboardFormat uFormat, string topic, string item) // Server Message XTYP_ADVSTOP. // Le client ferme une transaction advise. void OnAdvStop(ClipboardFormat uFormat, string topic, string item) // Server Message XTYP_CONNECT. // Un client demande à se connecter au server. bool OnConnect(string topic, PCONVCONTEXT context, bool sameInstance) // Server Message XTYP_CONNECT_CONFIRM. // La connection accepter, le server en reçoit la confirmation. void OnConnectConfirm(string topic, bool sameInstance) // Server Message XTYP_EXECUTE. // Le client demande au server d'exécuter une commande. // La commande doit être dans un format compris par le client et le server et dont il ont convenu préalablement. DDE OnExecute(string topic, byte[] command) // Server Message XTYP_POKE. // Le client dépose des données au server. Le server doit agir en conséquence. DDE OnPoke(ClipboardFormat uFormat, string topic, string item, byte[] data) // Server Message XTYP_REQUEST. // Le client demande des données au server. IntPtr OnRequest(ClipboardFormat uFormat, string topic, string item) /********************************************
  • Messages commun
                                                                                        • /
// Server and Client Message XTYP_DISCONNECT. // L'un des deux parti s'est déconnecté de la transaction void OnDisconnect(bool sameInstance) // Server and Client Message XTYP_ERROR. // Une erreur est survenue. Pour de plus amples information sur le code d'erreur, consultez le message XTYPE_ERROR de DDEML void OnError(ushort errorCode) // Server and Client Message XTYP_REGISTER. // Indique l'inscription d'un service. void OnRegister(string baseServiceName, string instanceServiceName) // Server and Client Message XTYP_UNREGISTER. // Indique la désinscription d'un service. void OnUnRegister(string baseServiceName, string instanceServiceName) /************************************************************************/ /* Raccourcis des méthodes DDE */ /************************************************************************/ // Connexion. Client/Server. Retourne l'handle de la conversation si réussi. sinon NULL. // Crée une conversation entre un client et un serveur. IntPtr Connect(string Service, string Topic) // Déconnexion. Client/Server. // Déconnecte une conversation préalablement créée. bool Disconnect(IntPtr hConv) // Transaction Execute. Client. // Demande l'exécution d'une commande au serveur. Ne peut être utilisé que par un client. ushort Execute(byte[] data, IntPtr hConv) // Transaction Poke. Client. // Dépose des données au serveur. Ne peut être utilisé que par le client. ushort Poke(byte[] data, IntPtr hConv, string item, ClipboardFormat wFormat) // Transaction Poke. Client. // Dépose des données sous forme d'une chaîne de caractère au serveur. Ne peut être utilisé que par le client. // Seuls formats supportés : ClipboardFormat.TEXT et ClipboardFormat.UNICODETEXT. Tout autre format ignore la demande ushort Poke(string texte, IntPtr hConv, string item, ClipboardFormat wFormat) // Transaction Request. Client. // Demande des données au serveur. Ne peut être utilisé que par le client. // Retourne un tableau d'octet contenant les données reçues le cas échant. null si rien n'a été reçu. byte[] Request(IntPtr hConv, string item, ClipboardFormat wFormat) // Transaction AdvStart. Client. wFlag peut prendre la valeur XTYPF_NODATA ou XTYPF_ACKREQ. // Démarre une transaction Advise. Ne peut être utilisé que par le client. // Le wFlag ignore la valeur XTYPF.NOBLOCK. bool AdvStart(IntPtr hConv, string item, ClipboardFormat wFormat, XTYPF wFlag) // Transaction AdvStop. Client. // Termine une transaction Advise. Ne peut être utilisé que par le client. void AdvStop(IntPtr hConv, string item, ClipboardFormat wFormat) // Transaction PostAdvise. Server. // Indique que le serveur doit envoyer des données pour une transaction Advise. Ne peut être utilisé que par le serveur. déclenche l'évènement OnAdvReq bool PostAdvise(string topic, string item) // Crée un identificateur de donnée. // A n'utiliser que si nécessaire. // L'argument share permet d'indiquer que les données sont partagées et non dupliquées. IntPtr CreateDataHandle(byte[] data, string item, ClipboardFormat wFormat) // share = false IntPtr CreateDataHandle(byte[] data, string item, ClipboardFormat wFormat, bool share) // Récupérer la dernière erreur // Fourni le message d'erreur correspondant à la dernière erreur. string GetLastError() // Libère un identificateur de donnée et initialise la variable. void FreeDataHandle(ref IntPtr hData) /************************************************************************/ /* Classes internes */ /************************************************************************/ class PCONVCONTEXT// : Classe utilisée par OnConnect pour gérer la non fourniture de la structure CONVCONTEXT. { bool Exists { get; } // Indique si la structure a été fournie. CONVCONTEXT CONVCONTEXT { get; } // Fournie la structure si elle existe. Lève une exception dans le cas contraire. }

Conclusion :


Comme l'utilisation de DDE nécessite une méthode de rappel, il faut alors en faire une par client/serveur. De plus l'API DDE nécessite des appels particuliers pour récupérer les informations. Et tout ces appels nécessite de se souvenir de l'identifiant de l'instance du client/server DDE que l'on a créée. Le composant permet de s'en affranchir et fourni les informations sous forme d'objets. L'utilisateur n'a plus besoin de se soucier de ces appels.

Il devrais bientôt y avoir des mises à jours pour les fonctionnalitées non gérées.

Attention : Les appels aux méthodes d'un client ou d'un server DDE doivent être effectuées dans le même processus légé (Thread) que sont initialisation.

J'espère que cette classe vous sera utile, en tout cas elle l'est pour moi.

Adresse de la version C++ dont cette implémentation découle : http://www.cppfrance.com/code.aspx?ID=33161

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.