Файл ddeml/ddemlfn.cpp
// ----------------------------------------------------- // Функции для работы с библиотекой DDEML // Сервер DDEML // ----------------------------------------------------- #define STRICT #include <windows.h>
#include <windowsx.h>
#include <ddeml.h>
#include <dde.h>
#include <mem.h>
#include <string.h>
#pragma hdrstop
#include "ddemlsr.hpp"
HDDEDATA EXPENTRY _export DDEServerCallback(WORD wType, WORD wFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dwData1, DWORD dwData2 );
// Идентификатор приложения, полученный после регистрации в // библиотеке DDEML DWORD idInst = 0L;
FARPROC lpDdeProc; HSZ hszService = NULL; HSZ hszTopic = NULL; HSZ hszItem = NULL;
// Идентификатор канала HCONV hConvApp = NULL;
// Буфер для приема данных char szDDEData[200];
// Версия сервера. Эта текстовая строка // передается клиенту по его запросу char szDDEServerVersion[] = "DDEML Server v.1.0, (C) Frolov A.V.";
//----------------------------------------------------- // Функция DDEServerOpen // Инициализация библиотеки DDEML //----------------------------------------------------- BOOL DDEServerOpen(HINSTANCE hInst, LPSTR szService, LPSTR szTopic, LPSTR szItem) { int rc;
// Создаем переходник для функции обратного вызова lpDdeProc = MakeProcInstance((FARPROC)DDEServerCallback, hInst);
// Выполняем инициализацию if(DdeInitialize((LPDWORD)&idInst, (PFNCALLBACK)lpDdeProc, APPCLASS_STANDARD, 0L)) { return FALSE; }
// После успешной инициализации получаем идентификаторы // строк для сервиса, раздела и элемента данных else { hszService = DdeCreateStringHandle(idInst, szService, CP_WINANSI);
hszTopic = DdeCreateStringHandle(idInst, szTopic, CP_WINANSI);
hszItem = DdeCreateStringHandle(idInst, szItem, CP_WINANSI);
// Регистрируем сервис DdeNameService(idInst, hszService, (HSZ)NULL, DNS_REGISTER);
return TRUE; } }
//----------------------------------------------------- // Функция DDEServerClose // Завершение работы с DDEML //----------------------------------------------------- void DDEServerClose(void) { // Завершение работы канала связи if(hConvApp != NULL) { DdeDisconnect(hConvApp);
hConvApp = NULL; }
// Сервис больше не доступен DdeNameService(idInst, hszService, (HSZ)NULL, DNS_UNREGISTER);
// Освобождение идентификаторов строк DdeFreeStringHandle(idInst, hszService);
DdeFreeStringHandle(idInst, hszTopic);
DdeFreeStringHandle(idInst, hszItem);
// Удаление переходника функции обратного вызова FreeProcInstance(lpDdeProc);
}
//----------------------------------------------------- // Функция DDEServerCallback // Функция обратного вызова для сервера DDEML //----------------------------------------------------- #pragma argsused HDDEDATA EXPENTRY _export DDEServerCallback(WORD wType, WORD wFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dwData1, DWORD dwData2) { switch(wType) { // Создание канала передачи данных case XTYP_CONNECT: { // Если сервис поддерживается, возвращаем // признак успешного создания канала if((HSZ)hsz2==(HSZ)hszService) return((HDDEDATA)TRUE);
else return((HDDEDATA)FALSE);
}
// Запрос данных от сервера case XTYP_REQUEST: { // Создаем идентификатор данных hData = DdeCreateDataHandle(idInst, szDDEServerVersion, lstrlen(szDDEServerVersion) + 1, 0L, hszItem, CF_TEXT, 0);
// В случае успеха возвращаем созданный идентификатор if(hData != NULL) return(hData);
else return(NULL);
}
// Запрос на выполнение команды, отрабатывается вхолостую case XTYP_EXECUTE: break;
// Передача данных серверу case XTYP_POKE: { // Проверяем элемент данных if(hsz1 == hszTopic) { // Получаем данные DdeGetData(hData, (LPBYTE) szDDEData, 200L, 0L);
// Отображаем принятые данные на экране if(szDDEData != NULL) { MessageBox(NULL, szDDEData, "DDEML Server", MB_OK | MB_SYSTEMMODAL | MB_ICONINFORMATION);
// Признак успешного завершения транзакции return((HDDEDATA)DDE_FACK);
} } else return((HDDEDATA)NULL);
break; }
// Подтверждение создания канала case XTYP_CONNECT_CONFIRM: { // Сохраняем идентификатор канала hConvApp = hConv; break; }
// Завершение работы канала case XTYP_DISCONNECT: { hConvApp = NULL; break; }
// Ошибка case XTYP_ERROR: { break; } } return((HDDEDATA)NULL);
}
Транзакция XTYP_ERROR передается в функцию обратного вызова в случае возникновения ошибки. Младшее слово параметра dwData1 содержит код ошибки.
Библиотека DDEML в Windows версии 3.1 поддерживает только один код ошибки - DML_ERR_LOW_MEMORY. Эта ошибка возникает при нехватке оперативной памяти. В случае возникновения такой ошибки выполнение обработки транзакции может быть не завершено.
Файл ddemlsr.hpp (листинг 3.3) содержит определения констант для приложения DDEMLSR.