Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Так как Динамический обмен данными (DDE) использует объекты памяти для передачи данных из одного приложения в другое, библиотека управления динамическими данными (DDEML) предоставляет набор функций, которые приложения DDE могут использовать для создания объектов DDE и управления ими.
Все транзакции, связанные с обменом данными, требуют, чтобы приложение предоставляло данные для создания локального буфера, содержащего данные, а затем вызывать функцию DdeCreateDataHandle. Эта функция выделяет объект DDE, копирует данные из буфера в объект и возвращает дескриптор данных. Дескриптор данных — это значение DWORD, которое DDEML использует для предоставления доступа к данным в объекте DDE. Чтобы предоставить доступ к данным в объекте DDE, приложение передает дескриптор данных DDEML, а DDEML передает дескриптор функции обратного вызова DDE приложения, получающего транзакцию данных.
В следующем примере показано, как создать объект DDE и получить дескриптор объекта. Во время транзакции XTYP_ADVREQ функция обратного вызова преобразует текущее время в строку ASCII, копирует строку в локальный буфер, а затем создает объект DDE, содержащий строку. Функция обратного вызова возвращает дескриптор объекту DDE (HDDEDATA) DDEML, который передает дескриптор клиентскому приложению.
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.
}
}
Принимающее приложение получает указатель на объект DDE путем передачи дескриптора данных в функцию DdeAccessData. Указатель, возвращаемый DdeAccessData предоставляет доступ только для чтения. Приложение должно использовать указатель для проверки данных, а затем вызвать функцию DdeUnaccessData, чтобы сделать указатель недействительным. Приложение может скопировать данные в локальный буфер с помощью функции DdeGetData.
В следующем примере получает указатель на объект DDE, определенный параметром hData, копирует содержимое в локальный буфер, а затем делает указатель недействительным.
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;
//
Обычно, когда приложение, создающее дескриптор данных, передает дескриптор DDEML, дескриптор становится недопустимым в создании приложения. Эта ситуация не является проблемой, если приложение должно совместно использовать данные только с одним приложением. Если приложение должно совместно использовать одни и те же данные с несколькими приложениями, однако создание приложения должно указать флаг HDATA_APPOWNED в DdeCreateDataHandle. Это дает право собственности на объект DDE для создания приложения и предотвращает дескриптор данных DDEML. Затем приложение может передать обработку данных любое количество раз после вызова DdeCreateDataHandle только один раз.
Если приложение указывает флаг HDATA_APPOWNED в параметре afCmdDdeCreateDataHandle, он должен вызвать функцию DdeFreeDataHandle, чтобы освободить дескриптор памяти независимо от того, передается ли дескриптор DDEML. Перед завершением работы приложение должно вызвать DdeFreeDataHandle, чтобы освободить все созданные данные, но не передать в DDEML.
Приложение, которое еще не передало дескриптор объекту DDE в DDEML, может добавлять данные в объект или перезаписывать данные в объекте с помощью функции DdeAddData. Как правило, приложение использует DdeAddData для заполнения неинициализированного объекта DDE. После передачи дескриптора данных в DDEML объект DDE, идентифицированный дескриптором, не может быть изменен; его можно освободить только.