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 fonctionne autant en ANSI qu'en Unicode.

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.

Source / Exemple :


/* Dans tout ce qui suit :

  • uFormat : Désigne le format presse papier utilisé pour les données.
  • 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.
  • - UINT : DDE_FACK si traité, DDE_FBUSY si le server est trop occupé, DDE_FNOTPROCESSED si non traité.
  • - HDDEDATA : Donnée de retour.
  • /
/********************************************
  • Messages client
                                                                                        • /
// Client Message XTYP_ADVDATA. // Le serveur a envoyer des données dans le contexte d'une conversation Advise. UINT OnAdvData(UINT uFormat, String topic, String item, HDDEDATA 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(UINT uFormat, String topic, String item, HDDEDATA data, DWORD 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. HDDEDATA OnAdvReq(UINT uFormat, String topic, String item); // Server Message XTYP_ADVSTART. // Le client a demmandé l'initialisation d'une transaction advise. BOOL OnAdvStart(UINT uFormat, String topic, String item); // Server Message XTYP_ADVSTOP. // Le client ferme une transaction advise. void OnAdvStop(UINT uFormat, String topic, String item); // Server Message XTYP_CONNECT. // Un client demande à se connecter au server. BOOL OnConnect(String topic, CONVCONTEXT *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. UINT OnExecute(String topic, byte *command, DWORD length); // Server Message XTYP_POKE. // Le client dépose des données au server. Le server doit agir en conséquence. UINT OnPoke(UINT uFormat, String topic, String item, byte *data, DWORD length); // Server Message XTYP_REQUEST. // Le client demande des données au server. HDDEDATA OnRequest(UINT 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(WORD 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. HCONV Connect(String Service, String Topic) const; // Déconnexion. Client/Server. // Déconnecte une conversation préalablement créée. BOOL Disconnect(HCONV hConv) const; // Transaction Execute. Client. // Demande l'exécution d'une commande au serveur. Ne peut être utilisé que par un client. UINT Execute(BYTE *pData, DWORD dwLen, HCONV hConv) const; // Transaction Poke. Client. // Dépose des données au serveur. Ne peut être utilisé que par le client. UINT Poke(BYTE *pData, DWORD dwLen, HCONV hConv, String item, WORD wFormat) const; // Transaction Request. Client. // Demande des données au serveur. Ne peut être utilisé que par le client. // Le pointeur est initialisée avec la structure de fourniture de données. // La strucutre peut être détruite grâce à la méthode FreeRequestData. void Request(HCONV hConv, String item, WORD wFormat, DDEManager::Data *&pData) const; // 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. BOOL AdvStart(HCONV hConv, String item, WORD wFormat, UINT wFlag = 0) const; // Transaction AdvStop. Client. // Termine une transaction Advise. Ne peut être utilisé que par le client. void AdvStop(HCONV hConv, String item, WORD wFormat) const; // 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) const; // 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. HDDEDATA CreateDataHandle(BYTE *pData, DWORD dwLen, DWORD dwOffset, String item, WORD wFormat, BOOL share = FALSE) const; // Récupérer la dernière erreur // Fourni le message d'erreur correspondant à la dernière erreur. String GetLastError() const; // Détruit une structure de fourniture de donnée créée lors de l'appel à Request. // Initialise le pointeur DDEMANAGER_API void FreeRequestData(DDEManager::Data *&pData) const; // Libère un identificateur de donnée et initialise la variable. DDEMANAGER_API void FreeDataHandle(HDDEDATA &hData) const; /************************************************************************/ /* Structures de donnée internes */ /************************************************************************/ // Structure de donnée de fourniture de données. // Cette structure n'est intiantiable que par DDEManager. // Aucune dérivation ne permet son instantiation. // Celà permet de sécuriser la manipulation de cette structure pour la création et la suppression. DDEManager::Data // Données fournies. Ne pas essayer de détruire manuellement les données. // Celà pourrais entrainer l'arrêt de votre application. BYTE *const data; // Longueur des données fournies. const DWORD length;

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'objet ou de tampon de donnée récupéré. L'utilisateur n'a plus besoin de se soucier de ces appels.

Afin de permettre un meilleurs fonctionnement au niveau de l'allocation mémoire, l'application se base sur les bibliothèques existantes pour allouer les emplacements de données. La seule allocation et destruction faite par l'objet sont celles pour les données reçues en Request qui ne s'utilisent donc que dans un seul Thread normalement. Toutes les allocations pour les chaînes sont effectuées par ATL par la classe générique StringT et son contrôle du buffer interne.

Le support Unicode/Ansi a été amélioré et sont fournis les différents modèles de compilation.

Il est notable que l'utilisation d'ATL en réduction des dépendances ne permet pas compiler en release pour une raison qui m'est inconnue. Si quelqu'un a la réponse, qu'il n'hésite pas et laisse un commentaire.

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 .NET qui découle de cette implémentation : http://www.csharpfr.com/code.aspx?ID=33352

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.