Partager via


Gestion des données

Étant donné que Dynamic Data Exchange (DDE) utilise des objets de mémoire pour transmettre des données d’une application à une autre, la bibliothèque de gestion DDEML (Dynamic Data Exchange Management Library) fournit un ensemble de fonctions que les applications DDE peuvent utiliser pour créer et gérer des objets DDE.

Toutes les transactions impliquant l’échange de données nécessitent que l’application fournissant les données crée une mémoire tampon locale contenant les données, puis appelle la fonction DdeCreateDataHandle . Cette fonction alloue un objet DDE, copie les données de la mémoire tampon vers l’objet et retourne un handle de données. Un handle de données est une valeur DWORD que le DDEML utilise pour fournir l’accès aux données dans l’objet DDE. Pour partager les données dans un objet DDE, une application transmet le handle de données au DDEML, et le DDEML transmet le handle à la fonction de rappel DDE de l’application qui reçoit la transaction de données.

L’exemple suivant montre comment créer un objet DDE et obtenir un handle pour l’objet. Pendant la transaction XTYP_ADVREQ , la fonction de rappel convertit l’heure actuelle en chaîne ASCII, copie la chaîne dans une mémoire tampon locale, puis crée un objet DDE qui contient la chaîne. La fonction de rappel retourne le handle à l’objet DDE (HDDEDATA) à la DDEML, qui transmet le handle à l’application cliente.

typedef struct tagTIME 
{ 
    INT     hour;   // 0 - 11 hours for analog clock 
    INT     hour12; // 12-hour format 
    INT     hour24; // 24-hour format 
    INT     minute; 
    INT     second; 
    INT     ampm;   // 0 - AM , 1 - PM 
} TIME; 
 
HDDEDATA EXPENTRY DdeCallback(uType, uFmt, hconv, hsz1, hsz2, 
    hdata, dwData1, dwData2) 
UINT uType; 
UINT uFmt; 
HCONV hconv; 
HSZ hsz1; 
HSZ hsz2; 
HDDEDATA hdata; 
DWORD dwData1; 
DWORD dwData2; 
{ 
 
    CHAR szBuf[32];
    HRESULT hResult;
    size_t * pcch;
    HRESULT hResult; 
 
    switch (uType) 
    { 
    case XTYP_ADVREQ: 
        if ((hsz1 == hszTime && hsz2 == hszNow) && 
                (uFmt == CF_TEXT)) 
        { 
            // Copy the formatted string to a buffer. 
 
            itoa(tmTime.hour, szBuf, 10);
            hResult = StringCchCat(szBuf, 32/sizeof(TCHAR), ":"); 
            if (FAILED(hResult))
            {
            // TO DO: Write error handler.
                return;
            }
            if (tmTime.minute < 10)
                hResult = StringCchCat(szBuf, 32/sizeof(TCHAR), "0"); 
                if (FAILED(hResult)
            {
            // TO DO: Write error handler.
                return;
            } 
            hResult = StringCchLength(szBuf, 32/sizeof(TCHAR), pcch);
            if (FAILED(hResult))
            {
            // TO DO: Write error handler.
                return;
            }
            itoa(tmTime.minute, &szBuf[*pcch], 10);
            hResult = StringCchCat(szBuf, 32/sizeof(TCHAR), ":"); 
            if (FAILED(hResult)
            {
            // TO DO: Write error handler.
                return;
            }
            if (tmTime.second < 10) 
                hResult = StringCchCat(szBuf, 32/sizeof(TCHAR), "0"); 
            if (FAILED(hResult)
            {
            // TO DO: Write error handler.
                return;
            }
            hResult = StringCchLength(szBuf, 32/sizeof(TCHAR), pcch);
            if (FAILED(hResult))
            {
            // TO DO: Write error handler.
                return;
            }
            itoa(tmTime.second, &szBuf[*pcch], 10);
            hResult = StringCchLength(szBuf, 32/sizeof(TCHAR), pcch);
            if (FAILED(hResult))
            {
            // TO DO: Write error handler.
                return;
            } 
            szBuf[*pcch] = '\0'; 
 
            // Create a global object and return its data handle. 
            hResult = StringCchLength(szBuf, 32/sizeof(TCHAR), pcch);
            if (FAILED(hResult))
            {
            // TO DO: Write error handler.
                return;
            }
            return (DdeCreateDataHandle( 
                idInst, 
                (LPBYTE) szBuf,     // instance identifier 
                *pcch + 1,          // source buffer length 
                0,                  // offset from beginning 
                hszNow,             // item name string 
                CF_TEXT,            // clipboard format 
                0));                // no creation flags 
        } else return (HDDEDATA) NULL; 
 
    // Process other transactions. 
    } 
} 

L’application de réception obtient un pointeur vers l’objet DDE en passant le handle de données à la fonction DdeAccessData . Le pointeur retourné par DdeAccessData fournit un accès en lecture seule. L’application doit utiliser le pointeur pour passer en revue les données, puis appeler la fonction DdeUnaccessData pour invalider le pointeur. L’application peut copier les données dans une mémoire tampon locale à l’aide de la fonction DdeGetData .

L’exemple suivant obtient un pointeur vers l’objet DDE identifié par le paramètre hData , copie le contenu dans une mémoire tampon locale, puis invalide le pointeur.

HDDEDATA hdata; 
LPBYTE lpszAdviseData; 
DWORD cbDataLen; 
DWORD i; 
char szData[32]; 
 
// 
case XTYP_ADVDATA: 
    lpszAdviseData = DdeAccessData(hdata, &cbDataLen); 
    for (i = 0; i < cbDataLen; i++) 
        szData[i] = *lpszAdviseData++; 
    DdeUnaccessData(hdata); 
    return (HDDEDATA) TRUE; 
//

En règle générale, lorsqu’une application qui a créé un handle de données passe ce handle au DDEML, le handle devient non valide dans l’application de création. Cette situation n’est pas un problème si l’application doit partager des données avec une seule application. Toutefois, si une application doit partager les mêmes données avec plusieurs applications, l’application de création doit spécifier l’indicateur HDATA_APPOWNED dans DdeCreateDataHandle. Cela donne la propriété de l’objet DDE à l’application de création et empêche le DDEML d’invalider le handle de données. L’application peut ensuite transmettre le traitement des données un nombre quelconque de fois après avoir appelé DdeCreateDataHandle une seule fois.

Si une application spécifie l’indicateur HDATA_APPOWNED dans le paramètre afCmd de DdeCreateDataHandle, elle doit appeler la fonction DdeFreeDataHandle pour libérer le handle de mémoire, qu’elle ait ou non transmis le handle au DDEML. Avant de se terminer, une application doit appeler DdeFreeDataHandle pour libérer tout handle de données qu’elle a créé mais qu’elle n’a pas transmis au DDEML.

Une application qui n’a pas encore transmis le handle à un objet DDE au DDEML peut ajouter des données à l’objet ou remplacer des données dans l’objet à l’aide de la fonction DdeAddData . En règle générale, une application utilise DdeAddData pour remplir un objet DDE non initialisé. Une fois qu’une application a passé un handle de données au DDEML, l’objet DDE identifié par le handle ne peut pas être modifié ; il ne peut être libéré que.