기본 개념(DDE)

이러한 개념은 DDE(동적 데이터 교환) 및 DDEML(동적 데이터 교환 관리 라이브러리)을 이해하는 데 핵심적인 요소입니다.

클라이언트 및 서버 상호 작용

DDE는 항상 클라이언트 애플리케이션과 서버 애플리케이션 간에 발생합니다. DDE 클라이언트 애플리케이션서버에 트랜잭션을 보내는 서버와의 대화를 설정하여 교환을 시작합니다. 트랜잭션은 데이터 또는 서비스에 대한 요청입니다. DDE 서버 애플리케이션클라이언트에 데이터 또는 서비스를 제공하여 트랜잭션에 응답합니다. 예를 들어 그래픽 애플리케이션에는 회사의 분기별 이익을 나타내는 막대 그래프가 포함될 수 있지만 막대 그래프의 데이터는 스프레드시트 애플리케이션에 포함될 수 있습니다. 최신 수익 수치를 얻기 위해 그래픽 애플리케이션(클라이언트)은 스프레드시트 애플리케이션(서버)과 대화를 설정할 수 있습니다. 그런 다음 그래픽 애플리케이션은 스프레드시트 애플리케이션에 트랜잭션을 보내 최신 수익 수치를 요청할 수 있습니다.

서버에는 동시에 많은 클라이언트가 있을 수 있으며 클라이언트는 여러 서버에서 데이터를 요청할 수 있습니다. 애플리케이션은 클라이언트와 서버 모두일 수도 있습니다. 클라이언트 또는 서버는 언제든지 대화를 종료할 수 있습니다.

트랜잭션 및 DDE 콜백 함수

DDEML은 애플리케이션의 DDE 콜백 함수에 트랜잭션을 전송하여 애플리케이션에 영향을 주는 DDE 활동에 대해 애플리케이션에 알깁니다. DDE 트랜잭션은 트랜잭션에 대한 추가 정보를 포함하는 다른 매개 변수와 함께 명명된 상수인 메시지와 유사합니다.

DDEML은 트랜잭션 유형에 적합한 작업을 수행하는 애플리케이션 정의 DDE 콜백 함수에 트랜잭션을 전달합니다. 예를 들어 클라이언트 애플리케이션이 서버 애플리케이션과의 대화를 설정하려고 하면 클라이언트는 DdeConnect 함수를 호출합니다. 이 함수를 사용하면 DDEML이 XTYP_CONNECT 트랜잭션을 서버의 DDE 콜백 함수로 보냅니다. 콜백 함수는 DDEML에 TRUE를 반환하여 대화를 허용하거나 FALSE를 반환하여 대화를 거부할 수 있습니다. 트랜잭션에 대한 자세한 내용은 트랜잭션 관리를 참조하세요.

서비스 이름, 토픽 이름 및 항목 이름

DDE 서버는 3단계 계층 서비스 이름(이전 DDE 설명서의 "애플리케이션 이름"이라고 함), 토픽 이름 및 항목 이름을 사용하여 대화 중에 서버가 교환할 수 있는 데이터 단위를 고유하게 식별합니다.

서비스 이름은 클라이언트가 서버와의 대화를 설정하려고 할 때 서버 애플리케이션이 응답하는 문자열입니다. 클라이언트는 서버와의 대화를 설정하기 위해 이 서비스 이름을 지정해야 합니다. 서버는 많은 서비스 이름에 응답할 수 있지만 대부분의 서버는 하나의 이름에만 응답합니다.

토픽 이름은 논리 데이터 컨텍스트를 식별하는 문자열입니다. 파일 기반 문서에서 작동하는 서버의 경우 토픽 이름은 일반적으로 파일 이름입니다. 다른 서버의 경우 다른 애플리케이션별 문자열입니다. 클라이언트는 서버와의 대화를 설정하려고 할 때 서버의 서비스 이름과 함께 토픽 이름을 지정해야 합니다.

항목 이름은 트랜잭션 중에 서버가 클라이언트에 전달할 수 있는 데이터 단위를 식별하는 문자열입니다. 예를 들어 항목 이름은 정수, 문자열, 여러 텍스트 단락 또는 비트맵을 식별할 수 있습니다.

서비스, 토픽 및 항목 이름을 사용하면 클라이언트가 서버와 대화를 설정하고 서버에서 데이터를 받을 수 있습니다.

시스템 토픽

시스템 항목은 모든 DDE 클라이언트에 대한 일반적인 관심 정보를 위한 컨텍스트를 제공합니다. 서버 애플리케이션은 시스템 토픽을 항상 지원하는 것이 좋습니다. 시스템 항목은 DDEML에 정의되어 있습니다. H 헤더 파일을 SZDDESYS_TOPIC.

존재하는 서버와 제공할 수 있는 정보의 종류를 확인하기 위해 클라이언트 애플리케이션은 시작 시 시스템 토픽에서 디바이스 이름을 NULL로 설정하여 대화를 요청할 수 있습니다. 이러한 와일드카드 대화는 시스템 성능 측면에서 비용이 많이 들기 때문에 최소한으로 유지해야 합니다. DDE 대화를 시작하는 방법에 대한 자세한 내용은 대화 관리를 참조하세요.

서버는 시스템 토픽 내에서 다음 항목 이름과 클라이언트에 유용한 다른 항목 이름을 지원해야 합니다.

항목 설명
SZDDE_ITEM_ITEMLIST 비 시스템 항목에서 지원되는 항목 목록입니다. (이 목록은 모멘트마다, 토픽마다 다를 수 있습니다.)
SZDDESYS_ITEM_FORMATS 서비스 애플리케이션에서 지원될 수 있는 모든 클립보드 형식을 나타내는 탭으로 구분된 문자열 목록입니다. 미리 정의된 클립보드 형식을 나타내는 문자열은 "CF_" 접두사를 제거한 CF_ 값과 동일합니다. 예를 들어 CF_TEXT 형식은 문자열 "TEXT"로 표시됩니다. 이러한 문자열은 미리 정의된 형식으로 추가로 식별하려면 대문자여야 합니다. 형식 목록은 콘텐츠가 가장 풍부하고 콘텐츠가 가장 적은 순서로 표시되어야 합니다. 클립보드 형식 및 렌더링 데이터에 대한 자세한 내용은 클립보드를 참조하세요.
SZDDESYS_ITEM_HELP 일반적인 관심의 사용자가 읽을 수 있는 정보입니다. 이 항목에는 최소한 서버 애플리케이션의 DDE 기능을 사용하는 방법에 대한 정보가 포함되어야 합니다. 이 정보에는 토픽 내에서 항목을 지정하는 방법, 서버가 수행할 수 있는 실행 문자열, 허용되는 찌르기 트랜잭션 및 다른 시스템 항목 항목에 대한 도움말을 찾는 방법이 포함될 수 있습니다.
SZDDESYS_ITEM_RTNMSG 가장 최근에 사용한 WM_DDE_ACK 메시지에 대한 세부 정보 지원 이 항목은 8비트 이상의 애플리케이션별 반환 데이터가 필요한 경우에 유용합니다.
SZDDESYS_ITEM_STATUS 서버의 현재 상태를 나타내는 표시입니다. 일반적으로 이 항목은 CF_TEXT 형식만 지원하며 준비 또는 없음 문자열을 포함합니다.
SZDDESYS_ITEM_SYSITEMS 이 서버에서 시스템 항목에서 지원되는 항목 목록입니다.
SZDDESYS_ITEM_TOPICS 현재 서버에서 지원하는 항목 목록입니다. (이 목록은 순간마다 다를 수 있습니다.)

이러한 항목 이름은 DDEML에 정의된 값입니다. H 헤더 파일입니다. 이러한 문자열에 대한 문자열 핸들을 가져오려면 애플리케이션은 DDEML 애플리케이션의 다른 문자열과 마찬가지로 DDEML 문자열 관리 함수를 사용해야 합니다. 문자열 관리에 대한 자세한 내용은 문자열 관리를 참조하세요.

초기화

다른 DDEML 함수를 호출하기 전에 애플리케이션은 DdeInitialize 함수를 호출해야 합니다. DdeInitialize 는 애플리케이션에 대한 인스턴스 식별자를 가져오고, 애플리케이션의 DDE 콜백 함수를 DDE에 등록하고, 콜백 함수에 대한 트랜잭션 필터 플래그를 지정합니다.

애플리케이션 또는 DLL의 각 인스턴스는 해당 인스턴스 식별자를 idInst 매개 변수로 필요한 다른 DDEML 함수에 전달해야 합니다. 여러 DDEML 인스턴스의 목적은 애플리케이션에서 DDEML을 사용하는 동시에 DDEML을 사용해야 하는 DLL을 지원하는 것입니다. 애플리케이션은 DDEML 인스턴스를 둘 이상 사용하면 안됩니다.

트랜잭션 필터는 DDEML이 원치 않는 트랜잭션을 애플리케이션의 DDE 콜백 함수에 전달하지 못하도록 하여 시스템 성능을 최적화합니다. 애플리케이션은 DdeInitialize ufCmd 매개 변수에서 트랜잭션 필터를 설정합니다. 애플리케이션은 콜백 함수에서 처리하지 않는 각 트랜잭션 형식에 대한 트랜잭션 필터 플래그를 지정해야 합니다. 애플리케이션은 DdeInitialize에 대한 후속 호출을 사용하여 트랜잭션 필터를 변경할 수 있습니다. 트랜잭션에 대한 자세한 내용은 트랜잭션 관리를 참조하세요.

다음 예제에서는 DDEML을 사용하도록 애플리케이션을 초기화하는 방법을 보여줍니다.

DWORD idInst = 0; 
HINSTANCE hinst; 
 
DdeInitialize(&idInst,         // receives instance identifier 
    (PFNCALLBACK) DdeCallback, // pointer to callback function 
    CBF_FAIL_EXECUTES |        // filter XTYPE_EXECUTE 
    CBF_SKIP_ALLNOTIFICATIONS, // filter notifications 
    0); 

애플리케이션은 DDEML을 더 이상 사용하지 않을 때 DdeUninitialize 함수를 호출해야 합니다. 이 함수는 애플리케이션에 대해 현재 열려 있는 모든 대화를 종료하고 시스템이 애플리케이션에 할당한 DDEML 리소스를 해제합니다.

콜백 함수

DDEML을 사용하는 애플리케이션은 애플리케이션에 영향을 주는 DDE 이벤트를 처리하는 콜백 함수를 제공해야 합니다. DDEML은 애플리케이션의 DDE 콜백 함수에 트랜잭션을 전송하여 이러한 이벤트를 애플리케이션에 알깁니다. 콜백 함수가 받는 트랜잭션은 DdeInitialize에 지정된 애플리케이션에 플래그를 지정하는 콜백 필터와 애플리케이션이 클라이언트, 서버 또는 둘 다인지에 따라 달라집니다. 자세한 내용은 DdeCallback을 참조하세요.

다음 예제에서는 일반적인 클라이언트 애플리케이션에 대한 콜백 함수의 일반적인 구조를 보여 있습니다.

HDDEDATA CALLBACK DdeCallback(uType, uFmt, hconv, hsz1, 
    hsz2, hdata, dwData1, dwData2) 
UINT uType;       // transaction type 
UINT uFmt;        // clipboard data format 
HCONV hconv;      // handle to conversation 
HSZ hsz1;         // handle to string 
HSZ hsz2;         // handle to string 
HDDEDATA hdata;   // handle to global memory object 
DWORD dwData1;    // transaction-specific data 
DWORD dwData2;    // transaction-specific data 
{ 
    switch (uType) 
    { 
        case XTYP_REGISTER: 
        case XTYP_UNREGISTER: 
            . 
            . 
            . 
            return (HDDEDATA) NULL; 
 
        case XTYP_ADVDATA: 
            . 
            . 
            . 
            return (HDDEDATA) DDE_FACK; 
 
        case XTYP_XACT_COMPLETE: 
            
            // 
            
            return (HDDEDATA) NULL; 
 
        case XTYP_DISCONNECT: 
            
            // 
            
            return (HDDEDATA) NULL; 
 
        default: 
            return (HDDEDATA) NULL; 
    } 
} 

uType 매개 변수는 DDEML에서 콜백 함수로 전송되는 트랜잭션 형식을 지정합니다. 나머지 매개 변수의 값은 트랜잭션 형식에 따라 달라집니다. 트랜잭션 형식 및 트랜잭션 형식을 생성하는 이벤트는 다음 항목에 설명되어 있습니다. 각 트랜잭션 유형에 대한 자세한 내용은 트랜잭션 관리를 참조하세요.

문자열 관리

DDE 작업을 수행하려면 많은 DDEML 함수가 문자열에 액세스해야 합니다. 예를 들어 클라이언트는 DdeConnect 함수를 호출하여 서버와의 대화를 요청할 때 서비스 이름과 토픽 이름을 지정해야 합니다. 애플리케이션은 DDEML 함수의 포인터가 아닌 HSZ(문자열 핸들)를 전달하여 문자열을 지정합니다. 문자열 핸들은 문자열을 식별하는 시스템에서 할당한 DWORD 값입니다.

애플리케이션은 DdeCreateStringHandle 함수를 호출하여 특정 문자열에 대한 문자열 핸들을 가져올 수 있습니다. 이 함수는 문자열을 시스템에 등록하고 애플리케이션에 문자열 핸들을 반환합니다. 애플리케이션은 문자열에 액세스해야 하는 DDEML 함수에 핸들을 전달할 수 있습니다. 다음 예제에서는 시스템 토픽 문자열 및 서비스 이름 문자열에 대한 문자열 핸들을 가져옵니다.

HSZ hszServName; 
HSZ hszSysTopic; 
hszServName = DdeCreateStringHandle( 
    idInst,         // instance identifier 
    "MyServer",     // string to register 
    CP_WINANSI);    // Windows ANSI code page 
 
hszSysTopic = DdeCreateStringHandle( 
    idInst,         // instance identifier 
    SZDDESYS_TOPIC, // System topic 
    CP_WINANSI);    // Windows ANSI code page 
    

이전 예제의 idInst 매개 변수는 DdeInitialize 함수에서 가져온 인스턴스 식별자를 지정합니다.

애플리케이션의 DDE 콜백 함수는 대부분의 DDE 트랜잭션 중에 하나 이상의 문자열 핸들을 받습니다. 예를 들어 서버는 XTYP_REQUEST 트랜잭션 중에 두 개의 문자열 핸들을 받습니다. 하나는 토픽 이름을 지정하는 문자열을 식별하고 다른 하나는 항목 이름을 지정하는 문자열을 식별합니다. 애플리케이션은 다음 예제와 같이 DdeQueryString 함수를 호출하여 문자열 핸들에 해당하는 문자열의 길이를 가져오고 애플리케이션 정의 버퍼에 문자열을 복사할 수 있습니다.

DWORD idInst; 
DWORD cb; 
HSZ hszServ; 
PSTR pszServName; 
cb = DdeQueryString(idInst, hszServ, (LPSTR) NULL, 0, 
    CP_WINANSI) + 1; 
pszServName = (PSTR) LocalAlloc(LPTR, (UINT) cb); 
DdeQueryString(idInst, hszServ, pszServName, cb, CP_WINANSI); 

인스턴스별 문자열 핸들은 문자열 핸들에서 문자열로, 다시 문자열 핸들로 매핑할 수 없습니다. 예를 들어 DdeQueryString은 문자열 핸들에서 문자열을 만든 다음 DdeCreateStringHandle이 해당 문자열에서 문자열 핸들을 만들지만 다음 예제와 같이 두 핸들은 동일하지 않습니다.

DWORD idInst; 
DWORD cb; 
HSZ hszInst, hszNew; 
PSZ pszInst; 
DdeQueryString(idInst, hszInst, pszInst, cb, CP_WINANSI); 
hszNew = DdeCreateStringHandle(idInst, pszInst, CP_WINANSI); 
// hszNew != hszInst ! 

두 문자열 핸들의 값을 비교하려면 DdeCmpStringHandles 함수를 사용합니다.

콜백 함수가 반환되면 애플리케이션의 DDE 콜백 함수에 전달된 문자열 핸들이 유효하지 않습니다. 애플리케이션은 DdeKeepStringHandle 함수를 사용하여 콜백 함수가 반환된 후 사용할 문자열 핸들을 저장할 수 있습니다.

애플리케이션이 DdeCreateStringHandle을 호출하면 시스템은 지정된 문자열을 문자열 테이블에 입력하고 문자열에 액세스하는 데 사용하는 핸들을 생성합니다. 또한 시스템은 문자열 테이블의 각 문자열에 대한 사용 횟수를 유지 관리합니다.

애플리케이션이 DdeCreateStringHandle을 호출하고 테이블에 이미 있는 문자열을 지정하는 경우 시스템은 문자열의 다른 항목을 추가하는 대신 사용 횟수를 증분합니다. (애플리케이션을 사용하여 사용 횟수를 증분할 수도 있습니다.DdeKeepStringHandle.) 애플리케이션이 DdeFreeStringHandle 함수를 호출하면 시스템에서 사용 횟수가 감소합니다.

사용 횟수가 0이면 테이블에서 문자열이 제거됩니다. 둘 이상의 애플리케이션이 특정 문자열에 대한 핸들을 가져올 수 있으므로 애플리케이션은 핸들을 만들거나 유지한 것보다 더 많은 시간 동안 문자열 핸들을 해제해서는 안 됩니다. 그렇지 않으면 애플리케이션이 테이블에서 문자열을 제거하여 다른 애플리케이션에서 문자열에 대한 액세스를 거부할 수 있습니다.

DDEML 문자열 관리 함수는 원자 관리자를 기반으로 하며 원자와 동일한 크기 제한이 적용됩니다.

DDEML 및 스레드

DdeInitialize 함수는 DDEML에 애플리케이션을 등록하여 DDEML 인스턴스를 만듭니다. DDEML 인스턴스는 DdeInitialize라는 스레드와 연결된 스레드 기반입니다.

DDEML 인스턴스에 속하는 개체에 대한 모든 DDEML 함수 호출은 DdeInitialize를 호출한 동일한 스레드에서 만들어 인스턴스를 만들어야 합니다. 다른 스레드에서 DDEML 함수를 호출하면 함수가 실패합니다. 대화를 할당한 스레드가 아닌 다른 스레드에서 DDEML 대화에 액세스할 수 없습니다.