ГЛАВА 8. ТЕХНОЛОГИИ ОБМЕНА ИНФОРМАЦИЕЙ В ОС WINDOWS 7 глава




WndProc в том, что возвращаемый ею ответ определяется приложением. Ниже приведен

список поступающих в функцию DdeCallback сообщений с указанием типов ожидаемых

ответов (табл. 8.5).

 

Таблица 8.5


Сообщение

XTYP_ADVSTART, XTYP_CONNECT

XTYP_ADVREQ, XTYP_REQUEST,

XTYP_WILDCONNECT

XTYP_ADVDATA, XTYP_EXECUTE,

XTYP_POKE

XTYP_ADVSTOP, XTYP_DISCONNECT,

XTYP_CONNECT_CONFIRM, XTYP_ERROR,

XTYP_REGISTER, XTYP_UNREGISTER,

XTYP_XACT_COMPLETE


Ответ

Логическое значение (TRUE, FALSE)

Дескриптор блока данных (или NULL)

 

Флаг: DDE_FACK, DDE_FBUSY или

DDE_FNOTPROCESSED

Нет ответа; только уведомление


 

 

Функция DdeClientTransaction дает команду DDEML отправить сообщение серве-

ру. Тип сообщения зависит от характера действий, запрашиваемых клиентом. В табл. 8.6

перечислены некоторые типы сообщений и соответствующие им транзакции, выполняе-

мые сервером.

Таблица 8.6


Сообщение


Транзакция


 

 



 

XTYP_REQUEST Подключение с необязательным ответом; передача одного элемен-

та данных

XTYP_ADVSTART Подключение с полуобязательным или обязательным ответом; пе-

редача данных и обновлений


XTYP_POKE


Запись (прием) данных от клиента


XTYP_EXECUTE Выполнение команды или действия

 

8.4.3. Механизмы обработки транзакций

 

Обработкатранзакцийснеобязательнымответом. Когда сервер получает со-

общение XTYP_REQUEST, он читает имена темы и элемента данных из двух строковых

параметров и проверяет запрашиваемый формат данных. Если сервер распознает эле-

мент и поддерживает данный формат, он создает объект данных, в который записывает

текущее значение элемента, и возвращает дескриптор этого объекта. Если сервер не

поддерживает данный формат или не распознает элемент, возвращается значение NULL.

Сервер, который не поддерживает транзакции данного типа, во избежание получе-

ния нежелательных сообщений XTYP_REQUEST должен установить в функции DdeIni-

tialize флаг CBF_FAIL_REQUESTS.

Значение, переданное сервером, возвращается клиенту в виде результата функции

DdeClientTransaction. Типичная схема такого взаимодействия представлена на рис. 8.1

[12]. Условно его можно разбить на три этапа.

1. Клиент посылает серверу запрос через DDEML.

2. Сервер расшифровывает запрос и формирует пакет запрашиваемых данных.

3. Клиент получает ответ и расшифровывает его.

 

Рис.8.1. Последовательность событий, происходящих после запроса клиентом элемента данных

Когда клиент делает запрос о возможности получить извещение об обновлении

данных, функция обратного вызова сервера принимает сообщение XTYP_ADVSTART.

Если сервер распознает имена темы и элемента данных, а также поддерживает запраши-

ваемый формат, он возвращает значение TRUE, подтверждая факт установления под-

ключения. Если одно из указанных условий не выполняется, сервер возвращает значение

FALSE, предотвращающее установление подключения.

Сообщение XTYP_ADVSTART не указывает серверу, с каким ответом, обязатель-

ным или полуобязательным, будет это подключение.

 



 

Транзакциисобязательнымответом. При установлении подключения с обяза-

тельным ответом сервер не возвращает данные немедленно. Он посылает их только при

последующих изменениях запрашиваемого элемента. В ответ на сообщение

XTYP_ADVSTART сервер часто устанавливает флаг, "напоминающий" ему о том, что

поступил запрос на обновление данных. При любых изменениях сервер проверяет со-

стояние этого флага и, если он установлен, вызывает функцию DdePostAdvise, которая

уведомляет DDEML о поступлении новых данных, интересующих клиента.

Сервер не должен помнить о том, какой из клиентов послал данный запрос, -

DDEML решает эту задачу собственными средствами. По заданным именам темы и эле-

мента, которые передаются сервером для идентификации доступных данных, DDEML

определяет, какой из клиентов "находится на связи" и каким, обязательным или полу-

обязательным, является подключение.

В случае обязательного подключения DDEML немедленно отправляет серверу со-

общение XTYP_ADVREQ, получает от него данные и передает их клиенту в виде сооб-

щения XTYP_ADVDATA. Этапы этого процесса можно представить следующим обра-

зом (см. рис. 8.2):

1. Инициатором сеанса выступает клиент, а сервер откликается на его запрос, посылая

ответ TRUE.

2. Сервер информирует DDEML о наличии новых данных. DDEML определяет, что

данное подключение является обязательным, и запрашивает данные, а затем переда-

ет их приложению-клиенту. Этот этап повторяется каждый раз при получении сер-

вером новых данных.

3. Клиент разрывает подключение, посылая сообщение XTYP_ADVSTOP, в ответ на

которое сервер возвращает NULL.

 

Рис.8.2. Цикл транзакции с обязательным ответом

Транзакциисполуобязательнымответом. В случае подключения с полуобяза-

тельным ответом DDEML также получает от сервера уведомление об изменении дан-

ных, но не отправляет ему сообщения с запросом данных. Вместо этого DDEML посы-

лает клиенту сообщение XTYP_ADVDATA с пустым дескриптором блока данных.

 


 

Сервер, который не поддерживает транзакций с обязательным и полуобязательным

ответом, должен установить флаг CBF_FAIL_ADVISES в функции DdeInitialize. Таким

образом он предотвратит получение нежелательных сообщений XTYP_ADVSTART и

XTYP_ADVSTOP.

Для получения нового значения элемента данных клиент должен выполнить тран-

закцию с необязательным ответом. На рис. 8.3 изображены этапы этого процесса.

1. Сервер объявляет о поступлении новых данных.

2. DDEML информирует клиента, но клиент игнорирует это уведомление. Уведомле-

ния будут посылаться клиенту всякий раз при изменении данных на сервере, однако

клиент может проигнорировать их всех.

3. Сервер вновь объявляет об изменениях в запрашиваемом элементе данных.

4. Клиент откликается, запрашивая данные (сообщение XTYP_REQUEST).

5. DDEML передает запрос серверу.

6. Сервер посылает запрашиваемые данные клиенту.

 

 

Рис.8.3. Цикл транзакции с полуобязательным ответом

Обработкапринудительныхикомандныхтранзакций. Некоторые серверы

предпочитают получать данные от клиента иным способом [12]. Клиент, который хочет

передать данные серверу, должен выполнить принудительную транзакцию - послать со-

общение XTYP_POKE. В ответ на это сообщение сервер проверяет тему и элемент дан-

ных и, при желании, читает объект данных.

Некоторые серверы также получают команды от своих клиентов, принимая их в

виде дескрипторов данных. Сервер блокирует объект, анализирует содержащуюся в нем

командную строку, а затем выполняет определенные действия. После анализа команд-

ной строки сервер должен освободить дескриптор данных, но при необходимости он

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

обычно ожидают немедленного выполнения команд и требуют подтверждения, сервер,

 


 

 

по возможности, должен выполнить команду из функции обратного вызова до того, как

будет возвращен результат.

В ответ на принудительную или командную транзакцию сервер возвращает одно из

трех значений:

DDE_PACK - Данные получены и подтверждены.

DDE_FBUSY - Сервер занят и не может обработать данные или инструкции; повторите

попытку позже.

DDE_FNOTPROCESSED - Данные или инструкции отклонены.

Флаги, установленные в функции DdeInitialize, позволяют отфильтровывать неже-

лательные сообщения о принудительных (флаг CBF_FAIL_POKES) или командных

(флаг CBF_FAIL_EXECUTES) транзакциях для серверов, не поддерживающих эти тран-

закции [12].

 

8.4.4. Завершение DDE-диалога

 

При необходимости прекратить DDE-диалог клиент или сервер вызывают либо

функцию DdeDisconnect (завершить указанный диалог), либо функцию DdeDisconnect-

List (завершить группу диалогов). В обоих случаях конкретному приложению или всем

приложениям передается сообщение XTYP_DISCONNECT. Синтаксис вызова функции

DdeDisconpect имеет следующий вид:

 

DdeDisconnect(hConv);

 

где параметр hConv представляет собой дескриптор диалога, возвращаемый функцией

DdeConnect. Функция DdeDisconnectList вызывается так:

 

DdeDisconnectList(hConvList);

 

где параметр hConvList представляет собой дескриптор, возвращаемый функцией Dde-

ConnectList.

Когда DDEML получает сообщение XTYP_DISCONNECT, все активные в данный

момент транзакции текущего диалога (или диалогов) прекращаются. Согласно догово-

ренности, диалоги могут завершаться только приложениями-клиентами. Однако при

особых обстоятельствах подключения могут разрываться и приложениями-серверами

(например, в случае их закрытия).

Как клиенты, так и серверы должны быть готовы в любой момент получить сооб-

щение о разрыве подключения. При этом они должны закрыть соответствующие струк-

туры данных. В случае закрытия приложения или если оно больше не собирается уста-

навливать подключения к другим приложениям, программа должна отменить

инициализацию всех DDEML-функций обратного вызова.

При вызове функции DdeUninitialize информация о сервисе удаляется из DDEML-

таблиц, все активные в данный момент диалоги прекращаются и происходит рассылка

сообщения XTYP_UNREGISTER всем DDEML-функциям обратного вызова. Этапы

процесса завершения диалога и отключения от DDEML показаны на рис.8.4.

 


 

Рис.8.4. Процесс закрытия клиента и сервера

 

При возникновении ошибки DDE-функция возвращает значение NULL или

FALSE. Более подробная информация об ошибке может быть получена с помощью

функции DdeGetLastError:

 

UINT DdeGetLastError(DWORD dwInstID);

 

Поскольку функция DdeGetLastError требует задания идентификатора экземпляра

приложения, она не может применяться для получения информации об ошибке в случае

невыполнения функции DdeInitialize. Поэтому она возвращает собственные, расширен-

ные коды ошибок.

DMLERR_NO_ERROR - Успешная инициализация.

DMLERR_DLL_USAGE - Программа зарегистрирована для DDE-мониторинга и не

может использовать DDEML для выполнения транзакций.

DMLERR_INVALID_PARAMETER - Параметр содержит недопустимую информацию.

DMLERR_SYS_ERROR - Произошла внутренняя ошибка DDEML.

 

8.4.5. Синхронные и асинхронные транзакции

 

DDEML-клиенты могут выбирать между выполнением синхронных и асинхрон-

ных транзакций [12]. Отличие между синхронными и асинхронными операциями прояв-

ляется только на уровне программы-клиента. С точки зрения программы-сервера, тран-

закции обоих типов выглядят одинаково.

Преимущество асинхронных транзакций заключается в том, что они выполняются

быстрее и проще программируются. Асинхронные транзакции применяются сильно за-

груженными программами, которые должны обрабатывать значительный объем данных

при взаимодействии с DDEML-сервером, или программами, которые вынуждены регу-

лярно взаимодействовать с медленным сервером и хотят избежать нежелательных пе-

риодов ожидания ответа.

 


 

 

В случае синхронных операций приложение-клиент ожидает ответа от сервера,

инициализировав транзакцию - либо путем запроса информации, либо путем передачи

команды для выполнения определенных операций. Если сервер заставляет клиента ожи-

дать дольше установленного времени, функция DdeClientTransaction отменяет транзак-

цию и завершает свою работу.

При синхронных транзакциях необходимо принимать меры для освобождения объ-

ектов данных. DDEML передает дескриптор данных в виде результирующего значения

функции DdeClientTransaction и не имеет возможности узнать о том, когда данные будут

освобождены. Клиент становится владельцем объектов данных, полученных при син-

хронной транзакции от функции DdeClientTransaction, и, в конце концов, должен вы-

звать функцию DdeFreeDataHandle, чтобы освободить их.

В случае асинхронных операций при вызове функции DdeClientTransaction вместо

длительности паузы следует задать значение TIMEOUT_ASYNC. В результате функция

DdeClientTransaction немедленно возвратит значение TRUE, а также идентификатор

транзакции в поле dwResult.

Пока приложение-клиент продолжает выполнять другие операции, DDEML осуще-

ствляет транзакцию в фоновом режиме. Затем, по завершении транзакции, DDEML по-

сылает сообщение XTYP_XACT_COMPLETE функции обратного вызова приложения-

клиента. В этом сообщении в параметре dwData1 содержится идентификатор транзак-

ции, что позволяет клиенту определить, какой из запросов выполнен.

DDEML обеспечивает также альтернативный механизм идентификации транзакций

по их сообщениям о завершении. Клиент может зарегистрировать свое значение типа

DWORD, связанное с каждой асинхронной транзакцией. Функция DdeSetUserHandle

принимает дескриптор диалога, идентификатор асинхронной транзакции и пользова-

тельское значение типа DWORD, сохраняя эти параметры внутри собственной структу-

ры данных. При получении сообщения XTYP_XACT_COMPLETE клиент читает ло-

кальный идентификатор с помощью функции DdeQueryConvInfo.

Ожидая завершения асинхронной транзакции, функция DdeClientTransaction вхо-

дит в цикл и производит опрос сообщений каждого из окон, что позволяет клиенту про-

должать реагировать на команды пользователя, ожидая ответа на транзакцию. Однако в

течение этого периода клиент не может выполнить другую DDEML-функцию.

Кроме того, попытка вызвать функцию DdeClientTransaction завершается неудачно,

если у того же самого клиента в данный момент выполняется другая, синхронная тран-

закция.

Чтобы отменить асинхронную операцию, не дожидаясь ее завершения, следует вы-

звать функцию DdeAbandonTransaction. При этом DDEML освобождает все ресурсы,

связанные с транзакцией, и отменяет результаты, возвращенные сервером. (Аналогич-

ный процесс происходит по истечении времени, отведенного на выполнение синхронной

транзакции.)

При асинхронной транзакции DDEML предоставляет клиентской функции обрат-

ного вызова дескриптор объекта данных. Когда функция обратного вызова возвращает

результат, DDEML резонно предполагает, что данные больше не нужны, и автоматиче-

ски освобождает объект данных. Если клиент хочет сохранить данные, он должен их

скопировать с помощью функции DdeGetData.

Как объяснялось ранее, обычная последовательность инициации диалога предпола-

гает, что клиент знает заранее, какие ему нужны cервисы и/или темы, Чтобы предоста-

вить возможность клиентам просмотреть все доступные темы, DDE-серверы иногда со-

держат для каждого сервиса тему, которая называется system.

С помощью этой темы обеспечивается поддержка набора стандартных элементов,

Кроме того, тема system позволяет клиенту получить информацию о конкретном сервисе

[12].

 

 


 

 

Строки, идентифицирующие стандартные системные элементы, определяются в

виде констант в файле DDEML.H. Три из них должны обязательно поддерживаться все-

ми серверными приложениями.

SZDDESYS_ITEM_FORMATS - Список строк, разделенных символами табуляции и

указывающих форматы буфера обмена, которые поддерживаются данным сервером.

(Имя элемента задается строкой "Formats".)

SZDDESYS_ITEM_SYSITEMS - Список элементов, поддерживаемых сервером в теме

system. (Имя элемента задается строкой "SysItems".)

SZDDESYS_ITEM_TOPICS - Список тем, поддерживаемых сервером. (Имя элемента

задается строкой "Topics".)

Кроме этих трех элементов темы system, DDEML-сервер поддерживает в каждой

теме еще один стандартный элемент.

SZDDE_ITEM_ITEMLIST - Список элементов темы, отличней от system. (Имя элемен-

та задается строкой "TopicItemList".)

В ответ на запрос этих элементов сервер должен соединить все имена темы, эле-

мента или формата в одну длинную строку, используя в качестве разделителей символы

табуляции. Из этой строки сервер создает объект данных и возвращает библиотеке

DDEML дескриптор этого объекта в качестве результирующего значения в ответ на со-

общение XTYP_REQUEST. Затем клиент выделяет данные из этого объекта, разбивает

список на составные части и отображает их.

 

§ 8.5.Обменинформациейпотехнологиисвязыванияивнедрениеобъектов

 

8.5.1. Общие положения

 

Технология OLE (Object Linking and Embedding - связывание и внедрение объек-

тов) представляет собой совершенно иной способ совместного использования данных

различными приложениями по сравнению с буфером обмена и технологией DDE. В ши-

роком смысле, технология OLE является формой межзадачного взаимодействия [12]. В

частности, она позволяет одному приложению подключать или встраивать в себя ин-

формацию, созданную другим приложением. При этом создается так называемый со-

ставнойдокумент, который еще называют OLE-документом.

Написанное вами OLE-приложение будет работать правильно даже в том случае,

если оно взаимодействует с сервером, предоставляющим данные в формате, который не

предусмотрен стандартами Microsoft. Технология OLE освобождает операционную сис-

тему от необходимости отслеживать все форматы данных - если сервер способен обра-

батывать эти данные, любой клиент сможет получить их.

OLE представляет собой набор протоколов и функций, предложенных корпорацией

Aldus в 1988 году для упрощения создания и поддержки составных документов. Со-

ставнымдокументом называется файл, который принадлежит одному приложению

(например, текстовому редактору), но содержит данные, созданные другими приложе-

ниями (например, графическим редактором). Блоки "чужих" данных в составном доку-

менте называются объектами. Приложение, которое получает объекты данных и фор-

мирует из них составные документы, называется ОLE-клиентом, а приложение,

экспортирующее объекты для использования их другими приложениями, - OLE-

сервером. Является приложение клиентом или сервером, зависит от его роли в конкрет-

ной схеме взаимодействия. Одно приложение может одновременно выступать в роли как

клиента, так и сервера [12].

Интегрировав технологию OLE в операционную систему Windows, Microsoft сде-

лала большой шаг в сторону ориентации работы пользователя на документы, а не на

приложения. Традиционно пользователь вызывал отдельное приложение для каждого

 

 


 

 

нового документа. Работа с данными иного формата обычно предполагала выход из од-

ного приложения и запуск другого. В среде, где работа ведется с приложениями, доку-

мент имел смысл только в той программе, в которой он был создан.

С другой стороны, в среде разработки документов несколько приложений могут

"скооперироваться" и создать единый документ. Ни одно из приложений не распознает

форматы всех объектов, содержащихся в документе, но при переходе от одного объекта

к другому система автоматически вызывает соответствующие приложения. Редактиро-

вание различных объектов осуществляется отдельно в их "родных" приложениях, а ба-

зовый документ автоматически получает обновленные данные от всех "программ-

пайщиков". Пользователь получает возможность свободно комбинировать звук, видео,

изображения, числа и текст в едином интегрированном документе. Можно демонстри-

ровать картинки в текстовом редакторе или прилагать видеоклипы к записям в базе дан-

ных.

Составные документы существовали в операционной системе Windows еще до по-

явления технологии OLE, но возможности работы с ними были очень ограничены. Поль-

зователь мог создавать составной документ, копируя данные из буфера обмена и встав-

ляя их в другом приложении. При этом объект данных перемещался из программы-

сервера в программу-клиент. Но если сервер впоследствии редактировал объект, опера-

ции копирования и вставки необходимо было повторять для всехдокументов, в которые

была внедрена копия этого объекта [12].

Для формирования среды разработки документов операционная система должна

иметь возможность координировать работу приложений. В частности, система должна

знать, какая из программ может работать с определенным форматом данных. По мере

того как пользователь будет перемещаться от объекта к объекту в составном документе,

система должна распознавать эти объекты и поддерживать связи с соответствующими

приложениями. В Windows эти сложные операции реализованы с помощью библиотек

OLE-функций. Они помогают создавать программы, осуществляющие обработку объек-

тов практически любого типа путем невидимого взаимодействия с приложениями, соз-

давшими эти объекты.

Объект представляет собой набор данных из одного приложения, которые тракту-

ются как единое целое. OLE-приложения создают составные документы, комбинируя

несколько объектов в одном файле. Пользователь видит одновременно все объекты со-

ставного документа в одном окне. Для программы-клиента каждый объект представляет

собой "черный ящик", заполненный непонятными данными. А она и не должна пони-

мать эти данные, поскольку для манипуляций с объектами программа-клиент вызывает

OLE-функции.

При импортировании объекта программа-клиент должна выбрать один из двух ва-

риантов: связывание или внедрение [12]. Если документ содержит все данные объекта,

то такой объект называется внедренным. Если документ содержит только ссылку, ука-

зывающую на данные в другом документе, то такой объект называется связанным. Оба

метода дают на экране один и тот же результат, но только в связанных объектах автома-

тически отображаются все обновления.

Связывание объектов еще имеет то преимущество, что файл результирующего до-

кумента получается гораздо меньшим по объему. Преимущество же внедренных объек-

тов заключается в их независимости: документ, содержащий только внедренные объек-

ты, может легко переноситься из одной системы в другую. Поскольку внедренные

объекты содержат внутри себя все необходимые данные, новая система не обязательно

должна содержать OLE-сервер. При желании пользователь может преобразовать связан-

ные объекты во внедренные.

Как уже говорилось выше, OLE-приложения могут относиться к одному из двух

типов: клиенты и серверы. Если вы внедряете изображение, созданное программой Paint,

 

 


 

 

в документ текстового редактора WordPad, Paint выступает в роли сервера, а WordPad - в

роли клиента. Редактор WordPad не обязан понимать данные, которые содержатся в гра-

фическом файле, - для отображения этих данных он вызывает OLE-функции. Если сис-

тема не может самостоятельно отобразить эти данные, она вызывает сервер, т.е. Paint,

который отображает данные в окне программы WordPad.

Такие приложения, как Word, WordPad, Excel и т.п., являются одновременно и кли-

ентами, и серверами. Эти приложения могут как принимать OLE-объекты, предостав-

ленные другими серверами, так и выступать в роли OLE-серверов по отношению к дру-

гим приложениям-клиентам. Редактор Write в Windows З.х функционирует только как

OLE-клиент и не располагает возможностями сервера. А вот программа Paint служит

только OLE-сервером и не способна исполнять роль клиента. Она может только редак-

тировать изображения и передавать их другим приложениям.

Поскольку Paint является автономным приложением и в то же время представляет

собой OLE-сервер, эта программа считается полнымсервером. В отличие от полных

серверов, мини-серверы не могут работать как автономные приложения и не содержат

возможностей для открытия и сохранения файлов. Они могут только предоставлять свои

услуги OLE-клиентам.

Серверы любого типа могут предоставлять несколько типов услуг. Например, Qua-

ttro Pro предлагает услуги Quattro Pro Graph и Quattro Pro Notebook, a Microsoft Word -

Microsoft Word Document и Microsoft Word Picture.

Тип данных, экспортируемых сервером, обобщенно называется классомобъекта.

Например, программа Paintbrush экспортирует объекты класса PBrush. Excel поддержи-

вает классы ExcelWorksheet и ExcelChart. Серверы регистрируют свои классы в систем-

ном реестре. Каждым классом может управлять только один сервер.

Для каждого класса объектов регистрируется также набор команд. OLE-командой

или, по терминологии разработчиков, глаголом (verb) называется определенное дейст-

вие, которое сервер может выполнять над объектом. Например, часто используются та-



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-04-02 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: