데이터 관리

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에 전달하면 애플리케이션 만들기에서 핸들이 유효하지 않습니다. 애플리케이션이 단일 애플리케이션과만 데이터를 공유해야 하는 경우에는 이 상황이 문제가 되지 않습니다. 그러나 애플리케이션이 여러 애플리케이션과 동일한 데이터를 공유해야 하는 경우 만드는 애플리케이션은 DdeCreateDataHandle에서 HDATA_APPOWNED 플래그를 지정해야 합니다. 이렇게 하면 DDE 개체의 소유권이 생성 애플리케이션에 부여되고 DDEML에서 데이터 핸들이 무효화되지 않습니다. 그런 다음 애플리케이션은 DdeCreateDataHandle 을 한 번만 호출한 후 데이터 핸들을 여러 번 전달할 수 있습니다.

애플리케이션이 DdeCreateDataHandleafCmd 매개 변수에서 HDATA_APPOWNED 플래그를 지정하는 경우 DDEML에 핸들을 전달했는지 여부에 관계없이 메모리 핸들을 해제하려면 DdeFreeDataHandle 함수를 호출해야 합니다. 애플리케이션이 종료되기 전에 DdeFreeDataHandle 을 호출하여 생성되었지만 DDEML에 전달되지 않은 데이터 핸들을 해제해야 합니다.

아직 DDE 개체에 핸들을 DDEML에 전달하지 않은 애플리케이션은 DdeAddData 함수를 사용하여 개체에 데이터를 추가하거나 개체의 데이터를 덮어쓸 수 있습니다. 일반적으로 애플리케이션은 DdeAddData 를 사용하여 초기화되지 않은 DDE 개체를 채웁니다. 애플리케이션이 DDEML에 데이터 핸들을 전달한 후에는 핸들로 식별된 DDE 개체를 변경할 수 없습니다. 해제할 수 있습니다.