データ管理

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 回だけ呼び出した後、データ ハンドルを何度でも渡すことができます。

アプリケーションが DdeCreateDataHandleafCmd パラメーターに HDATA_APPOWNED フラグを指定する場合、DDEML にハンドルを渡したかどうかに関係なく、 DdeFreeDataHandle 関数を呼び出してメモリ ハンドルを解放する必要があります。 アプリケーションが終了する前に、アプリケーションは DdeFreeDataHandle を呼び出して、作成したが DDEML に渡さなかったデータ ハンドルを解放する必要があります。

DDEML に対して DDE オブジェクトにハンドルをまだ渡していないアプリケーションは、 DdeAddData 関数を使用してオブジェクトにデータを追加したり、オブジェクト内のデータを上書きしたりすることができます。 通常、アプリケーションは DdeAddData を使用して、初期化されていない DDE オブジェクトを埋めます。 アプリケーションが DDEML にデータ ハンドルを渡した後、ハンドルによって識別される DDE オブジェクトを変更することはできません。解放のみ可能です。