Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы

         

Файл 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.


Содержание раздела