データ管理
Dynamic Data Exchange (DDE) はメモリ オブジェクトを使用して、あるアプリケーションから別のアプリケーションにデータを渡すために、DDE アプリケーションで DDE オブジェクトの作成と管理に使用できる一連の関数を提供します。
データの交換に関連するすべてのトランザクションでは、データを提供するアプリケーションが、データを含むローカル バッファーを作成し、 DdeCreateDataHandle 関数を呼び出す必要があります。 この関数は、DDE オブジェクトを割り当て、バッファーからオブジェクトにデータをコピーし、データ ハンドルを返します。 データ ハンドルは、 DDEML が DDE オブジェクト内のデータへのアクセスを提供するために使用する DWORD 値です。 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.
}
}
受信側のアプリケーションは、データ ハンドルを DdeAccessData 関数に渡すことによって、DDE オブジェクトへのポインターを取得します。 DdeAccessData によって返されるポインターは、読み取り専用アクセスを提供します。 アプリケーションでは、ポインターを使用してデータを確認し、 DdeUnaccessData 関数を呼び出してポインターを無効にする必要があります。 アプリケーションは、 DdeGetData 関数を使用してローカル バッファーにデータをコピーできます。
次の例では、 hData パラメーターによって識別される DDE オブジェクトへのポインターを取得し、その内容をローカル バッファーにコピーしてから、ポインターを無効にします。
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 に渡すと、作成するアプリケーションでハンドルが無効になります。 アプリケーションが 1 つのアプリケーションとデータを共有する必要がある場合、この状況は問題になりません。 ただし、アプリケーションが複数のアプリケーションと同じデータを共有する必要がある場合は、作成するアプリケーションで DdeCreateDataHandle に HDATA_APPOWNED フラグを指定する必要があります。 これにより、DDE オブジェクトの所有権が作成アプリケーションに与え、DDEML がデータ ハンドルを無効にできなくなります。 その後、アプリケーションは DdeCreateDataHandle を 1 回だけ呼び出した後、データ ハンドルを何度でも渡すことができます。
アプリケーションが DdeCreateDataHandle の afCmd パラメーターに HDATA_APPOWNED フラグを指定する場合、DDEML にハンドルを渡したかどうかに関係なく、 DdeFreeDataHandle 関数を呼び出してメモリ ハンドルを解放する必要があります。 アプリケーションが終了する前に、アプリケーションは DdeFreeDataHandle を呼び出して、作成したが DDEML に渡さなかったデータ ハンドルを解放する必要があります。
DDEML に対して DDE オブジェクトにハンドルをまだ渡していないアプリケーションは、 DdeAddData 関数を使用してオブジェクトにデータを追加したり、オブジェクト内のデータを上書きしたりすることができます。 通常、アプリケーションは DdeAddData を使用して、初期化されていない DDE オブジェクトを埋めます。 アプリケーションが DDEML にデータ ハンドルを渡した後、ハンドルによって識別される DDE オブジェクトを変更することはできません。解放のみ可能です。