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

         

Регистрация в библиотеке DDEML


Библиотека DDEML используется одновременно многими приложениями, однако, подобно всем DLL-библиотекам, находится в оперативной памяти в единственном экземпляре. Функция LibMain, выполняющая инициализацию DLL-библиотеки, вызывается только один раз при первой загрузке библиотеки в память (для Windows версии 3.1), поэтому LibMain не может использоваться для регистрации приложений.

Если приложение собирается использовать DDEML, оно должно зарегистрировать себя в библиотеке DDEML, вызвав специально предназначенную для этого функцию с именем DdeInitialize.

Прототип функции DdeInitialize определен в файле ddeml.h (который должен быть включен в исходный текст DDEML-приложения наряду с файлом windows.h):

UINT WINAPI DdeInitialize(

DWORD FAR* pidInst, // адрес идентификатора приложения

PFNCALLBACK pfnCallback, // адрес функции обратного вызова

DWORD afCmd, // флаги DWORD ulRes); // зарезервировано

Функция DdeInitialize используется в процессе инициализации и серверов, и клиентов DDEML. Сама по себе она не создает никаких каналов передачи данных между приложениями, однако процедура регистрации приложения, выполняемая этой функцией, должна быть проведена до вызова любых других функций, имеющих отношение к DDEML.

Займемся параметрами функции DdeInitialize.

Параметр pidInst представляет собой указатель на двойное слово, в которое после регистрации будет записан идентификатор, присвоенный копии приложения библиотекой DDEML (одновременно могут работать несколько копий одного и того же DDEML-приложения). Иными словами, в процессе регистрации библиотека DDEML присваивает копии приложения некоторый идентификатор, под которым она его "знает". Вы должны указывать полученный от функции идентификатор при вызове всех остальных функций библиотеки DDEML.

Перед вызовом функции DdeInitialize ваше приложение должно записать в двойное слово, адрес которого передается через первый параметр, нулевое значение.

Заметим, что идентификатор копии приложения, присвоенный в процессе регистрации, и идентификатор копии приложения, полученный через параметр функции WinMain - разные по смыслу (и по значению) идентификаторы.




Параметр pfnCallback представляет собой указатель на функцию обратного вызова, определенную приложением для обработки транзакций. Как сервер, так и клиент должны определить такую функцию. Функция обратного вызова вызывается системой DDEML и содержит в себе всю логику обработки транзакций, определенную вами при разработке приложения.

Если приложение вызывает функцию DdeInitialize несколько раз для многократной регистрации, каждый раз следует указывать отдельную функцию обратного вызова. Многократная регистрация вполне допустима, так как каждый раз библиотека DDEML будет создавать для себя новый идентификатор приложения. Такая методика используется при создании DLL-библиотек, работающих с DDEML. Обычным приложениям достаточно зарегистрировать себя один раз и, соответственно, определить одну функцию обратного вызова.

Через параметр afCmd передается двойное слово, каждый бит которого является флагом, определяющим режимы работы канала связи, а также влияющие на действия, выполняемые функцией DdeInitialize.

Последний параметр с именем ulRes зарезервирован и должен иметь нулевое значение.

Приведем фрагмент кода, выполняющего регистрацию сервера в библиотеке DDEML:

idInst = 0L; lpDdeSrProc = MakeProcInstance((FARPROC)DDEServerCallback, hInst); if(DdeInitialize((LPDWORD)&idInst, (PFNCALLBACK)lpDdeSrProc, APPCLASS_STANDARD, 0L)) { return FALSE; }

В этом фрагменте вначале создается переходник для функции обратного вызова, затем адрес этого переходника указывается во втором параметре функции DdeInitialize.

В случае успеха функция DdeInitialize возвращает нулевое значение. Для проверки можно также использовать константу DMLERR_NO_ERROR, определенную в файле ddeml.h. Если произошла ошибка, возвращается ненулевой код ошибки. Соответствующие константы определены в файле ddeml.h и имеют префикс имени DMLERR.

Немного о флагах, передаваемых через параметр afCmd.

Символические константы с префиксом имени APPCLASS позволяют задать класс приложения с точки зрения использования DDEML.



Класс APPCLASS_STANDARD предназначен для регистрации стандартного DDEML-приложения. Этот класс использован в приведенном выше фрагменте кода и в приложении DDEMLSR, исходные тексты которого вы увидите позже.

Класс APPCLASS_MONITOR предназначен для отладчиков и других приложений, управляющих работой системы DDEML. В качестве примера можно привести приложение DDESpy. Это приложение поставляется в составе Microsoft SDK for Windows 3.1 и предназначено для отладки DDE-приложений (и, разумеется, DDEML-приложений). В конце данной главы мы научим вас использовать приложение DDESpy для отладки созданных вами DDE-приложений.

Символические константы с префиксом имени APPCMD позволяют конкретизировать функции, выполняемые приложением, и экономить системные ресурсы. Если DDEML-приложение выполняет только функции клиента, следует указать флаг APPCMD_CLIENTONLY:

if(DdeInitialize((LPDWORD)&idInst, (PFNCALLBACK)lpDdeClProc, APPCMD_CLIENTONLY, 0L)) { return NULL; }

В простейших случаях можно ограничиться использованием класса APPCLASS_STANDARD при создании сервера DDEML и флага APPCMD_CLIENTONLY при создании клиента DDEML. Мы так и поступили в наших приложениях DDEMLSR и DDEMLCL, выполняющих, соответственно, функции сервера и клиента DDEML. Остальные флаги влияют на то, когда и зачем будет вызываться функция обратного вызова.

Если приложение больше не собирается работать с библиотекой DDEML, оно должно вызвать функцию DdeUninitialize, передав ей в качестве единственного параметра идентификатор копии приложения, полученный от функции DdeInitialize:

BOOL WINAPI DdeUninitialize(DWORD idInst);


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