Datenverwaltung
Da Dynamic Data Exchange (DDE) Speicherobjekte verwendet, um Daten von einer Anwendung an eine andere zu übergeben, bietet die Dynamic Data Exchange Management Library (DDEML) eine Reihe von Funktionen, die DDE-Anwendungen zum Erstellen und Verwalten von DDE-Objekten verwenden können.
Alle Transaktionen, die den Datenaustausch beinhalten, erfordern, dass die Anwendung, die die Daten bereitstellt, einen lokalen Puffer mit den Daten erstellt und dann die DdeCreateDataHandle-Funktion aufruft . Diese Funktion ordnet ein DDE-Objekt zu, kopiert die Daten aus dem Puffer in das -Objekt und gibt ein Datenhandle zurück. Ein Datenhandle ist ein DWORD-Wert , den die DDEML zum Bereitstellen des Zugriffs auf Daten im DDE-Objekt verwendet. Um die Daten in einem DDE-Objekt freizugeben, übergibt eine Anwendung das Datenhandle an die DDEML, und die DDEML übergibt das Handle an die DDE-Rückruffunktion der Anwendung, die die Datentransaktion empfängt.
Das folgende Beispiel zeigt, wie Sie ein DDE-Objekt erstellen und ein Handle für das -Objekt abrufen. Während der XTYP_ADVREQ Transaktion konvertiert die Rückruffunktion die aktuelle Zeit in eine ASCII-Zeichenfolge, kopiert die Zeichenfolge in einen lokalen Puffer und erstellt dann ein DDE-Objekt, das die Zeichenfolge enthält. Die Rückruffunktion gibt das Handle an das DDE-Objekt (HDDEDATA) an die DDEML zurück, die das Handle an die Clientanwendung übergibt.
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.
}
}
Die empfangende Anwendung ruft einen Zeiger auf das DDE-Objekt ab, indem sie das Datenhandle an die Funktion DdeAccessData übergibt. Der von DdeAccessData zurückgegebene Zeiger bietet schreibgeschützten Zugriff. Die Anwendung sollte den Zeiger verwenden, um die Daten zu überprüfen, und dann die Funktion DdeUnaccessData aufrufen, um den Zeiger ungültig zu machen. Die Anwendung kann die Daten mithilfe der DdeGetData-Funktion in einen lokalen Puffer kopieren.
Im folgenden Beispiel wird ein Zeiger auf das durch den hData-Parameter identifizierte DDE-Objekt abgerufen, der Inhalt wird in einen lokalen Puffer kopiert und dann der Zeiger ungültig.
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;
//
Wenn eine Anwendung, die ein Datenhandle erstellt hat, dieses Handle an die DDEML übergibt, wird das Handle in der erstellenden Anwendung in der Regel ungültig. Dies ist kein Problem, wenn die Anwendung Daten nur für eine einzelne Anwendung freigeben muss. Wenn eine Anwendung jedoch dieselben Daten mit mehreren Anwendungen gemeinsam nutzen muss, sollte die erstellende Anwendung das flag HDATA_APPOWNED in DdeCreateDataHandle angeben. Dadurch wird der erstellenden Anwendung der Besitz des DDE-Objekts übertragen und verhindert, dass die DDEML das Datenhandle ungültig macht. Die Anwendung kann das Datenhandle dann beliebig oft übergeben, nachdem DdeCreateDataHandle nur einmal aufgerufen wurde.
Wenn eine Anwendung das flag HDATA_APPOWNED im afCmd-Parameter von DdeCreateDataHandle angibt, muss sie die DdeFreeDataHandle-Funktion aufrufen, um das Speicherhandle freizugeben, unabhängig davon, ob das Handle an die DDEML übergeben wurde. Bevor sie beendet wird, muss eine Anwendung DdeFreeDataHandle aufrufen, um alle Datenhandles frei zu geben, die sie erstellt, aber nicht an die DDEML übergeben hat.
Eine Anwendung, die das Handle noch nicht an ein DDE-Objekt an die DDEML übergeben hat, kann dem Objekt Mithilfe der DdeAddData-Funktion Daten hinzufügen oder Daten im Objekt überschreiben. In der Regel verwendet eine Anwendung DdeAddData , um ein nicht initialisiertes DDE-Objekt auszufüllen. Nachdem eine Anwendung ein Datenhandle an die DDEML übergeben hat, kann das durch das Handle identifizierte DDE-Objekt nicht mehr geändert werden. sie kann nur freigegeben werden.