Динамический обмен данными в Visual FoxPro
« Назад Динамический обмена данными (Dynamic Data Exchange – DDE) осуществляется между клиентом и сервером. В качестве клиента выступает VFP, а в качестве сервера – иное Windows-приложение. Клиент может передавать серверу данные и команды и получать от сервера запрашиваемую информацию. Сеанс связи начинается с установления канала. После выполнения DDE-обмена канал следует закрыть. Обмен может быть синхронным или асинхронным. В первом варианте функция клиента, например пославшая команду, ожидает отклика в течение заданного времени, во втором исполнение приложения-клиента продолжается без задержки; получаемое сообщение обрабатывается специально определенной пользовательской функцией. Функции, осуществляющие настройку канала связи и обеспечивающие обмен данными, приведены в табл. 17.1. Таблица 17.1 Список DDE-функций
Функция DDEInitiate(cServiceName, cTopicName)устанавливает канал связи (DDE-канал) для динамического обмена данными между VFP и другим Windows-приложением (DDE-сервером). Возвращает номер канала. Функция вернет –1, если канал не может быть установлен. Природу ошибки определяет функция DDELastError( ) Параметры: cServiceName – служебное имя сервера (служба), которое в большинстве случаев является именем исполняемого файла без расширения. Список некоторых служб приведен в табл. 17.2. Таблица 17.2 Служебные имена DDE-серверов
cTopicName – имя темы (предмета связи). Имя темы должно быть известно приложению. Большинство DDE-серверов предоставляют тему с именем "System". Служба и предоставляемые ей темы приводятся в документации, прилагаемой к приложению. После установления канала обмена данными с DDE-сервером VFP, выступая как клиент, может запрашивать данные сервера посредством соответствующих функций. Приложение, с которым устанавливается DDE-канал, должно быть открыто. Программно это можно выполнить, потребив команду RUN или !, например: Run /n C:\Program Files\Microsoft Office\Office10\Excel Если оно закрыто, то VFP осведомится, нужно ли открыть приложение, и при положительном ответе попытается это сделать. Пример. Устанавливается DDE-канал между VFP и Microsoft Excel. Используется тема System. Run /n C:\Program Files\Microsoft Office\Office10\Excel nChannelNumber = DDEInitiate('Excel', 'System') if nChannelNumber != –1 then && Выполняются операции клиента && … && После их завершения канал закрывается DDETerminate(nChannelNumber) endif Функция DDETerminate(nChannelNumber | cServiceName)закрывает DDE-канал, установленный DDEInitiate( ). Возвращает .T., если канал удалось закрыть, или .F. – в противном случае. Параметры: nChannelNumber – номер закрываемого канала. cServiceName – служба DDE-сервера. Каналы после завершения обмена данными следует закрывать, экономя системные ресурсы. Все открытые каналы автоматически закрываются при завершении работы с VFP. Функция DDEAdvise(nChannelNumber, cItemName, cUDFName, nLinkType)устанавливает вид связи DDE-канала nChannelNumber: с уведомлением, без него или автоматическая связь. Возвращает .T., если вид связи установлен, или .F. – в противном случае. Параметры: cItemName – имя элемента. Например, имя "R1C1" при работе с Microsoft Excel означает ячейку в первом столбце и первой строке рабочего листа. cUDFName – строка, содержащая имя пользовательской процедуры, которая выполняется, если установлена связь с уведомлением или автоматическая, при изменении элемента cItemName. Когда процедура выполняется, она получает 6 описанных в табл. 17.3 параметров; та же таблица отображает и порядок их следования. Таблица 17.3 Параметры, передаваемые процедуры, заданной cUDFName
Пользовательская процедура должна иметь 6 параметров. В случае связи с уведомлением новые данные должны быть получены DDERequest( ); при автоматической связи они содержатся в параметре Data. Параметр Action равен 'ADVISE', когда связь обновляется сервером, и содержит 'TERMINATE', когда связь прерывается клиентом или сервером. nLinkType – тип связи; принимает следующие значения: 0 – связь без уведомления; 1 – связь с уведомлением; 2 – автоматическая связь. Если для nLinkType указан 0, то при изменении элемента пользовательская процедура, заданная параметром cUDFName, не выполняется. Разница между видами связи 1 и 2 в том, что в первом случае для Data возвращается пустая строка, а во втором – строка с новыми данными. В обоих случаях при изменении элемента cItemName пользовательская процедура выполняется. Пример (приводится в справке VFP). Устанавливается связь с двумя ячейками листа Microsoft Excel. Вид связи с ячейкой 'R1C1' – 1, в ячейкой 'R1C2' – 2. При обновлении данных в ячейках выполняется пользовательская процедура GetAdvise( ). Полученные от Microsoft Excel данные отображаются в окне VFP. Run /n C:\Program Files\Microsoft Office\Office10\Excel nChannelNumber = DDEInitiate('Excel', 'Лист1') if nChannelNumber != –1 then DDEAdvise(nChannelNumber, 'R1C1', "GetAdvise", 1) DDEAdvise(nChannelNumber, 'R1C2', "GetAdvise", 2) wait window 'Введите данные в первые две ячейки строки 1 Microsoft Excel' endif procedure GetAdvise parameters nChannelNumber, action, item, data, format, advise if action = 'ADVISE' then do case case item = 'R1C1' && Связь с уведомлением; для получения данных выполняем DDERequest( ) newValue = DDERequest(nChannelNumber, item) ? 'R1C1 – связь с уведомлением: ' + newValue case item = 'R1C2' && Автоматическая связь newValue = data ? 'R1C2 - автоматическая связь: ' + newValue endCase else DDETerminate(nChannelNumber) endif endProc Замечание. В нерусифицированном Microsoft Excel в DDEInitiate( ) вместо 'Лист1' следует употребить 'Sheet1'. Функция DDEEnabled([lExpression1 | nChannelNumber [, lExpression2]])изменяет или возвращает статус (активный или не активный) DDE-процесса. Возвращает при выполнении без параметров .T., если DDE-процесс глобально активен, или .F. – в противном случае. Параметры: lExpression1 – задает глобально (для всех DDE-каналов) статус DDE-процесса; .T. – активный; .F. – не активный. Возвращает .T. при удачном завершении или .F. – в противном случае. nChannelNumber – номер DDE-канала. Возвращает .T., если DDE-процесс для указанного канала активен, или .F. – в противном случае. lExpression2 – задает статус DDE-процесса для канала nChannelNumber. Когда DDE-процесс неактивен, то запросы клиента становятся в очередь до тех пор, пока процесс не будет активизирован. Функция DDESetService(cServiceName, cOption [, cDataFormat | lExpression])создает, освобождает или изменяет службы и установки DDE, когда в качестве сервера выступает VFP. Результат имеет логический тип. Функция, если действие выполнено, возвращает .T., или F. – в противном случае. Параметры: cServiceName – служба, которая создается, освобождается или изменяется или информация о которой возвращается. Имя службы VFP по умолчанию – "FoxPro". cOption – строка, задающая выполняемое функцией DDESetService( ) действие. Принимает приведенные в табл. 17.4 значения. Таблица 17.4 Значения параметра cOption
Замечание. Активизация установки выполняется, если lExpression = .T., а отмена, – если lExpression = . F.; Если параметр lExpression опущен, то выводится текущее значение установки ADVISE, EXECUTE, POKE или REQUEST, например: ? DDESetService('myService', 'EXECUTE') cDataFormat – формат данных, поддерживаемый сервером. Форматы, если их в строке cDataFormat несколько, разделяются запятыми, например: DDESetService('myService', 'FORMATS', 'CF_TEXT, CF_SYLK') Если cDataFormat опущен, то поддерживается только формат CF_TEXT. lExpression – задает статус установки ADVISE, EXECUTE, POKE или REQUEST. Служба VFP имеет одну тему – System. Ею поддерживаются следующие элементы: Topics - список доступных тем; Formats – список поддерживаемых форматов; Status – статус: "Занят" или "Готов". SysItems – список имен элементов. Функция DDESetTopic(cServiceName, cTopicName [, cUDFName])создает, освобождает или изменяет тему заданной DDE-службы. Результат имеет логический тип. Функция, если действие выполнено, возвращает .T., или F. – в противном случае. Параметры: cServiceName – служба, которая создается, освобождается или изменяется или информация о которой возвращается. cTopicName – создаваемая или освобождаемая тема. Если параметр cUDFName имеется, то тема создается, и освобождается – в противном случае. Если cTopicName – это пустая строка, то функция, заданная параметром cUDFName, выполняется для каждой темы, не имеющей явно указанной cUDFName-функции. cUDFName – строка, содержащая имя пользовательской функции, выполняемой, когда приложение клиента запрашивает тему. Если параметр опущен, то тема cTopicName освобождается. Функция, задаваемая cUDFName, должна содержать описанные в табл. 17.3 параметры. Значения параметров Item, Data и AdviseStatus зависят от значения параметра Action (табл. 17.5). Таблица 17.5 Параметр Action и соответствующие значения
Если пользовательская cUDFName-функция успешно обрабатывает запрос клиента, то она должна возвращать .T., или .F. – в противном случае. Если функция возвращает .F., если Action это: INITIATE, то тема отвергается; POKE, REQUEST или EXECUTE, то запрос игнорируется; ADVISE, то связь с уведомлением или автоматическая связь не выполняется. После создания темы каждый запрос клиента к теме приводит к выполнению cUDFName-функции. Результат функции (.T. или .F.) передается клиенту посредством DDEPoke( ). Причину неудачи вернет функция DDELastError( ). Пример (приводится в справке VFP). В качестве сервера употребляется VFP. Создается служба myService и тема DO, через которую клиент связывается со службой. В частности, в примере клиент передает следующую команду: wait window "Команда выполнена" При выполнении команды клиента используется макроподстановка. && VFP используется и как DDE-сервер и как DDE-клиент && Определяем новую службу и ее установки DDESetService('myService', 'DEFINE') DDESetService('myService', 'EXECUTE', .T.) DDESetTopic('myService', 'DO', 'DOTopic') && Устанавливаем DDE-канал gnChannel = DDEInitiate('myService', 'DO') DDEExecute(gnChannel, 'wait window "Команда выполнена"') DDETerminate(gnChannel) function DOTopic parameters gnChannel, gcAction, gcItem, gData, gcFormat, gnAdvise glResult = .F. && Необходимо вернуть .T., когда Action – это 'INITIATE'; && в противном случае DDE-канал не будет установлен do case case gcAction = 'INITIATE' glResult = .T. case gcAction = 'EXECUTE' &gData && Применяем макроподстановку glResult = .T. case gcAction = 'TERMINATE' wait window 'Сеанс завершен' nowait glResult = .T. endcase return glResult endFunc После выполнения этой программы будет установлена DDE-служба VFP, которая доступна другим приложениям. Функция DDESetOption(cOption [, nTimeoutValue | lExpression])изменяет или возвращает настройки DDE. Возвращает текущее значение TIMEOUT или SAFETY. Параметры: cOption – задает вид настройки. Принимает приведенные в табл. 17.6 значения. Таблица 17.6 Значения параметра cOption
nTimeoutValue – значение настройки TIMEOUT. lExpression – значение настройки SAFETY. Функция DDEExecute(nChannelNumber, cCommand [, cUDFName])посылает серверу команду клиента по DDE-каналу nChannelNumber. Функция, если опущен параметр cUDFName, возвращает .T., если сервер успешно выполнил команду, или .F. – в противном случае. Причиной неудачи может также быть и неверное указание канала. Если параметр cUDFName задан, то возвращается номер транзакции (нуль или положительное число), а в случае ошибки – число –1. Параметры: cCommand – строка, содержащая команду, посылаемую другому приложению. Формат команды определяется приложением, ее получающим. cUDFName – строка, задающая имя пользовательской функции, позволяющей асинхронный обмен данными. Если параметр опущен, то клиент (VFP) ожидает данные сервера в течение периода, заданного по умолчанию или DDESetOption( ). Если параметр задан, то VFP продолжает выполнение программы сразу после выполнения запроса. Когда сервер завершает выполнение посланной ему команды, cUDFName-функция исполняется. Всего такая функция должна иметь 6 перечисленных в табл. 17.7 параметров; порядок следования параметров в функции совпадает с указанным в табл. порядком. Таблица 17.7 Параметры cUDFName-функции
При необходимости отмена незавершенной транзакции выполняется DDEAbortTrans( ). Если транзакция сорвалась, то причину неудачи можно узнать, употребив DDELastError( ). Пример (приведен в справке VFP). DDEExecute( ) используется для максимизации окна Excel. Run /n C:\Program Files\Microsoft Office\Office10\Excel gnChanNum = DDEInitiate('Excel', 'Лист1') if gnChanNum != –1 glExecute = DDEExecute(gnChanNum, '[App.Maximize]') if glExecute then wait window 'Окно Excel распахнуто' endif DDETerminate(gnChanNum) && Закрываем канал gnChanNum endif Функция DDEPoke(nChannelNumber, cItemName, cDataSent
|
Номер ошибки |
Описание |
1 |
Служба занята |
2 |
Тема занята |
3 |
Канал занят |
4 |
Нет такой службы |
5 |
Нет такой темы |
6 |
Нет такого канала |
7 |
Недостаточно памяти |
8 |
Request-превышение времени ожидания |
9 |
Требуется перерыв |
10 |
Не выполнена функция DDEInitiate( ) |
11 |
Действие клиента выполнено во время транзакции сервера |
12 |
Execute-превышение времени ожидания |
13 |
Неверный параметр |
14 |
Медленная память |
15 |
Ошибка памяти |
16 |
Ошибка соединения |
17 |
Ошибка запроса |
18 |
Poke-превышение времени ожидания |
19 |
Нельзя вывести сообщение |
20 |
Множественные синхронные транзакции |
21 |
Сервер не работает |
22 |
Внутренняя DDE-ошибка |
23 |
Advise-превышение времени ожидания |
24 |
Неверный идентификатор транзакции |
25 |
Неизвестная ошибка |
Функция
DDEAbortTrans(nTransactionNumber)
завершает асинхронную DDE-транзакцию.
Возвращает .T., если транзакция функцией завершена, или .F. – в противном случае. Для определения причины неудачи используется DDELastError( ).
Параметр:
nTransactionNumber – номер транзакции, возвращаемый функцией DDEExecute( ), DDEPoke( ) или DDERequest( ), начавшей эту транзакцию.