Partager via


Concepts de base (DDE)

Ces concepts sont essentiels pour comprendre l’échange dynamique de données (DDE) et la bibliothèque de gestion d’échange de données dynamiques (DDEML).

Interaction entre le client et le serveur

DDE se produit toujours entre une application cliente et une application serveur. L’application cliente DDE lance l’échange en établissant une conversation avec le serveur pour envoyer des transactions au serveur. Une transaction est une demande de données ou de services. L’application serveur DDE répond aux transactions en fournissant des données ou des services au client. Par exemple, une application graphique peut contenir un graphique à barres représentant les bénéfices trimestriels d’une société, mais les données du graphique à barres peuvent être contenues dans une application de feuille de calcul. Pour obtenir les derniers chiffres de profit, l’application graphique (le client) peut établir une conversation avec l’application de feuille de calcul (le serveur). L’application graphique peut ensuite envoyer une transaction à l’application de feuille de calcul, en demandant les derniers chiffres de profit.

Un serveur peut avoir plusieurs clients en même temps, et un client peut demander des données à plusieurs serveurs. Une application peut également être à la fois un client et un serveur. Le client ou le serveur peut mettre fin à la conversation à tout moment.

Transactions et fonction de rappel DDE

Le DDEML avertit une application de l’activité DDE qui affecte l’application en envoyant des transactions à la fonction de rappel DDE de l’application. Une transaction DDE est similaire à un message, il s’agit d’une constante nommée accompagnée d’autres paramètres qui contiennent des informations supplémentaires sur la transaction.

Le DDEML transmet une transaction à une fonction de rappel DDE définie par l’application qui effectue une action appropriée au type de transaction. Par exemple, lorsqu’une application cliente tente d’établir une conversation avec une application serveur, le client appelle la fonction DdeConnect . Cette fonction entraîne l’envoi d’une transaction XTYP_CONNECT à la fonction de rappel DDE du serveur. La fonction de rappel peut autoriser la conversation en retournant TRUE au DDEML, ou elle peut refuser la conversation en retournant FALSE. Pour une présentation détaillée des transactions, consultez Gestion des transactions.

Noms de service, noms de rubriques et noms d’éléments

Un serveur DDE utilise un nom de service de hiérarchie à trois niveaux (appelé « nom de l’application » dans la documentation DDE précédente), un nom de rubrique et un nom d’élément pour identifier de manière unique une unité de données que le serveur peut échanger pendant une conversation.

Un nom de service est une chaîne à laquelle une application serveur répond lorsqu’un client tente d’établir une conversation avec le serveur. Un client doit spécifier ce nom de service pour établir une conversation avec le serveur. Bien qu’un serveur puisse répondre à de nombreux noms de service, la plupart des serveurs répondent à un seul nom.

Un nom de rubrique est une chaîne qui identifie un contexte de données logiques. Pour les serveurs qui fonctionnent sur des documents basés sur des fichiers, les noms de rubriques sont généralement des noms de fichiers ; pour d’autres serveurs, il s’agit d’autres chaînes spécifiques à l’application. Un client doit spécifier un nom de rubrique ainsi que le nom de service d’un serveur lorsqu’il tente d’établir une conversation avec un serveur.

Un nom d’élément est une chaîne qui identifie une unité de données qu’un serveur peut transmettre à un client pendant une transaction. Par exemple, un nom d’élément peut identifier un entier, une chaîne, plusieurs paragraphes de texte ou une bitmap.

Les noms de service, de rubrique et d’élément permettent au client d’établir une conversation avec un serveur et de recevoir des données du serveur.

Rubrique système

La rubrique Système fournit un contexte pour les informations d’intérêt général pour tout client DDE. Il est recommandé que les applications serveur prennent en charge la rubrique Système à tout moment. La rubrique Système est définie dans le DDEML. Fichier d’en-tête H en tant que SZDDESYS_TOPIC.

Pour déterminer les serveurs présents et les types d’informations qu’ils peuvent fournir, une application cliente peut demander une conversation sur la rubrique Système au démarrage, en définissant le nom de l’appareil sur NULL. Ces conversations génériques étant coûteuses en termes de performances du système, elles doivent être conservées au minimum. Pour plus d’informations sur le lancement de conversations DDE, consultez Gestion des conversations.

Un serveur doit prendre en charge les noms d’éléments suivants dans la rubrique Système et tout autre nom d’élément utile à un client.

Élément Description
SZDDE_ITEM_ITEMLIST Liste des éléments pris en charge sous une rubrique non-Système. (Cette liste peut varier d’un moment à l’autre et d’une rubrique à l’autre.)
SZDDESYS_ITEM_FORMATS Liste délimitée par des tabulations de chaînes représentant tous les formats du Presse-papiers potentiellement pris en charge par l’application de service. Les chaînes qui représentent des formats prédéfinis du Presse-papiers sont équivalentes aux valeurs CF_ avec le préfixe « CF_ » supprimé. Par exemple, le format CF_TEXT est représenté par la chaîne « TEXT ». Ces chaînes doivent être en majuscules pour mieux les identifier en tant que formats prédéfinis. La liste des formats doit apparaître dans l’ordre du contenu le plus riche au moins riche en contenu. Pour plus d’informations sur les formats du Presse-papiers et le rendu des données, consultez Presse-papiers.
SZDDESYS_ITEM_HELP Informations lisibles par l’utilisateur d’intérêt général. Cet élément doit contenir au minimum des informations sur l’utilisation des fonctionnalités DDE de l’application serveur. Ces informations peuvent inclure, sans s’y limiter, comment spécifier des éléments dans des rubriques, quelles chaînes d’exécution le serveur peut effectuer, quelles transactions d’erreur sont autorisées et comment trouver de l’aide sur d’autres éléments de rubrique Système.
SZDDESYS_ITEM_RTNMSG Détails de prise en charge du message WM_DDE_ACK le plus récemment utilisé. Cet élément est utile lorsque plus de 8 bits de données de retour spécifiques à l’application sont nécessaires.
SZDDESYS_ITEM_STATUS Indication de la status actuelle du serveur. En règle générale, cet élément prend uniquement en charge le format CF_TEXT et contient la chaîne Prêt ou Occupé.
SZDDESYS_ITEM_SYSITEMS Liste des éléments pris en charge dans la rubrique Système par ce serveur.
SZDDESYS_ITEM_TOPICS Liste des rubriques prises en charge par le serveur à l’heure actuelle. (Cette liste peut varier d’un moment à l’autre.)

Ces noms d’éléments sont des valeurs définies dans le DDEML. Fichier d’en-tête H. Pour obtenir des handles de chaîne à ces chaînes, une application doit utiliser les fonctions de gestion des chaînes DDEML, comme pour toute autre chaîne dans une application DDEML. Pour plus d’informations sur la gestion des chaînes, consultez Gestion des chaînes.

Initialisation

Avant d’appeler une autre fonction DDEML, une application doit appeler la fonction DdeInitialize . DdeInitialize obtient un identificateur de instance pour l’application, inscrit la fonction de rappel DDE de l’application auprès du DDE et spécifie les indicateurs de filtre de transaction pour la fonction de rappel.

Chaque instance d’une application ou d’une DLL doit passer son identificateur de instance en tant que paramètre idInst à toute autre fonction DDEML qui l’exige. L’objectif de plusieurs instances DDEML est de prendre en charge les DLL qui doivent utiliser le DDEML en même temps qu’une application l’utilise. Une application ne doit pas utiliser plusieurs instance du DDEML.

Les filtres de transactions optimisent les performances du système en empêchant le DDEML de transmettre des transactions indésirables à la fonction de rappel DDE de l’application. Une application définit les filtres de transaction dans le paramètre ufCmdDdeInitialize. Une application doit spécifier un indicateur de filtre de transaction pour chaque type de transaction qu’elle ne traite pas dans sa fonction de rappel. Une application peut modifier ses filtres de transaction avec un appel suivant à DdeInitialize. Pour plus d’informations sur les transactions, consultez Gestion des transactions.

L’exemple suivant montre comment initialiser une application pour utiliser le DDEML.

DWORD idInst = 0; 
HINSTANCE hinst; 
 
DdeInitialize(&idInst,         // receives instance identifier 
    (PFNCALLBACK) DdeCallback, // pointer to callback function 
    CBF_FAIL_EXECUTES |        // filter XTYPE_EXECUTE 
    CBF_SKIP_ALLNOTIFICATIONS, // filter notifications 
    0); 

Une application doit appeler la fonction DdeUninitialize lorsqu’elle ne va plus utiliser le DDEML. Cette fonction met fin aux conversations actuellement ouvertes pour l’application et libère les ressources DDEML allouées par le système pour l’application.

Fonction de rappel

Une application qui utilise le DDEML doit fournir une fonction de rappel qui traite les événements DDE affectant l’application. Le DDEML avertit une application de ces événements en envoyant des transactions à la fonction de rappel DDE de l’application. Les transactions qu’une fonction de rappel reçoit dépendent du filtre de rappel qui signale l’application spécifiée dans DdeInitialize et si l’application est un client, un serveur ou les deux. Pour plus d’informations, consultez DdeCallback.

L’exemple suivant montre la structure générale d’une fonction de rappel pour une application cliente classique.

HDDEDATA CALLBACK DdeCallback(uType, uFmt, hconv, hsz1, 
    hsz2, hdata, dwData1, dwData2) 
UINT uType;       // transaction type 
UINT uFmt;        // clipboard data format 
HCONV hconv;      // handle to conversation 
HSZ hsz1;         // handle to string 
HSZ hsz2;         // handle to string 
HDDEDATA hdata;   // handle to global memory object 
DWORD dwData1;    // transaction-specific data 
DWORD dwData2;    // transaction-specific data 
{ 
    switch (uType) 
    { 
        case XTYP_REGISTER: 
        case XTYP_UNREGISTER: 
            . 
            . 
            . 
            return (HDDEDATA) NULL; 
 
        case XTYP_ADVDATA: 
            . 
            . 
            . 
            return (HDDEDATA) DDE_FACK; 
 
        case XTYP_XACT_COMPLETE: 
            
            // 
            
            return (HDDEDATA) NULL; 
 
        case XTYP_DISCONNECT: 
            
            // 
            
            return (HDDEDATA) NULL; 
 
        default: 
            return (HDDEDATA) NULL; 
    } 
} 

Le paramètre uType spécifie le type de transaction envoyé à la fonction de rappel par le DDEML. Les valeurs des paramètres restants dépendent du type de transaction. Les types de transactions et les événements qui les génèrent sont décrits dans les rubriques suivantes. Pour plus d’informations sur chaque type de transaction, consultez Gestion des transactions.

Gestion des chaînes

Pour effectuer une tâche DDE, de nombreuses fonctions DDEML nécessitent l’accès aux chaînes. Par exemple, un client doit spécifier un nom de service et un nom de rubrique lorsqu’il appelle la fonction DdeConnect pour demander une conversation avec un serveur. Une application spécifie une chaîne en passant un handle de chaîne (HSZ) plutôt qu’un pointeur dans une fonction DDEML. Un handle de chaîne est une valeur DWORD , affectée par le système, qui identifie une chaîne.

Une application peut obtenir un handle de chaîne pour une chaîne particulière en appelant la fonction DdeCreateStringHandle . Cette fonction inscrit la chaîne auprès du système et retourne un handle de chaîne à l’application. L’application peut passer le handle aux fonctions DDEML qui doivent accéder à la chaîne. L’exemple suivant obtient des handles de chaîne à la chaîne de rubrique système et à la chaîne de nom de service.

HSZ hszServName; 
HSZ hszSysTopic; 
hszServName = DdeCreateStringHandle( 
    idInst,         // instance identifier 
    "MyServer",     // string to register 
    CP_WINANSI);    // Windows ANSI code page 
 
hszSysTopic = DdeCreateStringHandle( 
    idInst,         // instance identifier 
    SZDDESYS_TOPIC, // System topic 
    CP_WINANSI);    // Windows ANSI code page 
    

Le paramètre idInst de l’exemple précédent spécifie l’identificateur instance obtenu par la fonction DdeInitialize.

La fonction de rappel DDE d’une application reçoit un ou plusieurs handles de chaîne pendant la plupart des transactions DDE. Par exemple, un serveur reçoit deux handles de chaîne pendant la transaction XTYP_REQUEST : l’un identifie une chaîne spécifiant un nom de rubrique et l’autre identifie une chaîne spécifiant un nom d’élément. Une application peut obtenir la longueur de la chaîne qui correspond à un handle de chaîne et copier la chaîne dans une mémoire tampon définie par l’application en appelant la fonction DdeQueryString , comme illustré dans l’exemple suivant.

DWORD idInst; 
DWORD cb; 
HSZ hszServ; 
PSTR pszServName; 
cb = DdeQueryString(idInst, hszServ, (LPSTR) NULL, 0, 
    CP_WINANSI) + 1; 
pszServName = (PSTR) LocalAlloc(LPTR, (UINT) cb); 
DdeQueryString(idInst, hszServ, pszServName, cb, CP_WINANSI); 

Un handle de chaîne spécifique à instance ne peut pas être mappé d’un handle de chaîne à une chaîne et à un handle de chaîne. Par instance, bien que DdeQueryString crée une chaîne à partir d’un handle de chaîne et que DdeCreateStringHandle crée un handle de chaîne à partir de cette chaîne, les deux handles ne sont pas identiques, comme illustré dans l’exemple suivant.

DWORD idInst; 
DWORD cb; 
HSZ hszInst, hszNew; 
PSZ pszInst; 
DdeQueryString(idInst, hszInst, pszInst, cb, CP_WINANSI); 
hszNew = DdeCreateStringHandle(idInst, pszInst, CP_WINANSI); 
// hszNew != hszInst ! 

Pour comparer les valeurs de deux handles de chaîne, utilisez la fonction DdeCmpStringHandles .

Un handle de chaîne passé à la fonction de rappel DDE d’une application devient non valide lorsque la fonction de rappel est retournée. Une application peut enregistrer un handle de chaîne à utiliser après le retour de la fonction de rappel à l’aide de la fonction DdeKeepStringHandle .

Lorsqu’une application appelle DdeCreateStringHandle, le système entre la chaîne spécifiée dans une table de chaînes et génère un handle qu’elle utilise pour accéder à la chaîne. Le système gère également un nombre d’utilisation pour chaque chaîne de la table de chaînes.

Lorsqu’une application appelle DdeCreateStringHandle et spécifie une chaîne qui existe déjà dans la table, le système incrémente le nombre d’utilisations au lieu d’ajouter une autre occurrence de la chaîne. (Une application peut également incrémenter le nombre d’utilisations à l’aide de DdeKeepStringHandle.) Lorsqu’une application appelle la fonction DdeFreeStringHandle , le système décrémente le nombre d’utilisations.

Une chaîne est supprimée de la table lorsque son nombre d’utilisation est égal à zéro. Étant donné que plusieurs applications peuvent obtenir le handle d’une chaîne particulière, une application ne doit pas libérer un handle de chaîne plus de fois qu’elle n’en a créé ou conservé le handle. Sinon, l’application peut entraîner la suppression de la chaîne de la table, ce qui refuse à d’autres applications l’accès à la chaîne.

Les fonctions de gestion des chaînes DDEML sont basées sur le gestionnaire d’atomes et sont soumises aux mêmes restrictions de taille que les atomes.

DDEML et threads

La fonction DdeInitialize inscrit une application auprès du DDEML, créant ainsi un instance DDEML. Un instance DDEML est basé sur des threads, associé au thread appelé DdeInitialize.

Tous les appels de fonction DDEML pour les objets appartenant à un instance DDEML doivent être effectués à partir du même thread appelé DdeInitialize pour créer le instance. Si vous appelez une fonction DDEML à partir d’un autre thread, la fonction échoue. Vous ne pouvez pas accéder à une conversation DDEML à partir d’un thread autre que celui qui a alloué la conversation.