к оглавлению

Приложение А. Библиотека DDE, OLE и .OCX

Динамический Обмен Данными

Введение в DDE

Динамический обмен данными (Dynamic Data Exchange - DDE) - мощное средство системы Windows, которое позволяет пользователю осуществлять доступ к данным параллельно исполняемого Windows-приложения. В своей программе пользователь может работать с этими данными в их естественном формате (как они определены в “родном” приложении) и с теми значениями, которые данные имеют на текущий момент.

Суть DDE состоит в установлении “диалогов” (каналов связи) между двумя параллельно исполняемыми Windows-приложениями. Одно из приложений, предоставляя данные, выступает в роли DDE-сервера, другое, получая данные, выступает в роли DDE-клиента. Любое приложение может быть как DDE-клиентом, получая данные от некоторого приложения, так и DDE-сервером, предоставляя данные некоторому приложению. Между DDE-сервером и DDE-клиентом можно одновременно установить несколько “диалогов”.

Для того, чтобы стать DDE-сервером, Clarion-приложение должно:

Для того, чтобы стать DDE-клиентом, Clarion-приложение должно:

Прототипы процедур динамического обмена содержатся в файле DDE.CLW, который должен вставляться оператором INCLUDE в MAP структуру вашей программы. Процесс динамического обмена данными инициирует не связанные с экранными объектами DDE-события для ACCEPT-цикла того окна в программе-сервере, и программе-клиенте, которое установило канал связи между приложениями.

 

DDE События

DDE-процесс регулируется рядом не связанных с полем DDE-событий. Эти события направляются ACCEPT-циклу того окна и сервера, и клиента, которое установило канал связи между приложениями.

Если Clarion-приложение выступает в качестве сервера, то для него будут инициироваться следующие события:

EVENT:DDErequest

Клиент осуществил запрос элемента данных.

EVENT:DDEadvise

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

EVENT: DDEexecute

Клиент исполнил оператор DDEEXECUTE.

EVENT:DDEpoke

Клиент прислал незапрашиваемые данные

Если Clarion-приложение выступает в качестве клиента, то для него будут инициироваться следующие события:

EVENT:DDEdata

Сервер предоставил обновленный элемент данных.

EVENT: DDEclosed

Сервер закрыл канал связи DDE.

При возникновении DDE-события, используя приведенные ниже процедуры, можно выяснить причину этого события:

После того, как Clarion-программа создала DDE-сервер, внешние клиенты могут связаться с сервером и запросить данные. Каждый запрос данных сопровождается строкой (формат которой известен сервер-программе), где конкретизируется запрашиваемый элемент данных. Если значение требуемого элемента уже известно Clarion-серверу, то сервер автоматически снабжает этим значением клиента, без порождения какого-либо события. В противном случае для цикла ACCEPT окна сервера инициируется одно из событий EVENT:DDErequest или EVENT:DDEadvise.

После того, как Clarion-программа создала DDE-клиента, он может связываться с внешними серверами для получения данных. Если сервер первый раз предоставляет значение требуемого элемента, то клиент получает это значение автоматически, без порождения какого-либо события. Если клиент установил с сервером связь типа “горячей линии”, то всякий раз, когда сервер предоставляет клиенту обновленное значение элемента данных, для ACCEPT-цикла окна клиента инициируется событие EVENT:DDEdata.

DDE Процедуры

DDEACKNOWLEDGE (послать подтверждение приема с DDE сервера)

DDEACKNOWLEDGE( ответ )

DDEACKNOWLEDGE

Посылает подтверждение приема текущего оператора DDEPOKE или DDEEXECUTE, посланного на DDE сервер.

ответ Целочисленная константа, переменная или выражение, содержащее значение ноль (0) или единица (1), указывающее на отрицательное или положительное подтверждение.

Процедура DDEACKNOWLEDGE позволяет программе, являющейся DDE сервером, немедленно подтвердить прием незапрашиваемых данных, посланных из DDEPOKE, или команд, посланных из DDEEXECUTE. Это позволяет клиентскому приложению незамедлительно продолжить работу. Хотя оператор CYCLE после EVENT:DDEpoke или EVENT:DDEexecute также посылает клиенту положительное подтверждение, DDEACKNOWLEDGE позволяет посылать еще и отрицательное подтверждение.

Пример:

!Текст клиентского приложения содержит следующее:

WinOne WINDOW,AT(0,0,160,400)

END

SomeServer LONG

DDEChannel LONG

CODE

OPEN(WinOne)

DDEChannel = DDECLIENT('MyServer','System') !Открыть канал связи с приложением MyServer

DDEEXECUTE(DDEChannel,'[ShowList]') !Сынициировать его на выполнение какого-либо

!действия

!Текст приложения-сервера содержит следующий текст:

WinOne WINDOW,AT(0,0,160,400)

END

DDEChannel LONG

CODE

OPEN(WinOne)

DDEChannel = DDESERVER('MyServer','System') !Открыть канал

ACCEPT

CASE EVENT()

OF EVENT:DDEExecute

CASE DDEVALUE() !Проверить запрашиваемое действие

OF 'ShowList'

DDEACKNOWLEDGE(1) !Послать положительное подтверждение приема

DO ShowList !и предпринять действие

ELSE !Если запрашиваемое действие неопознано

DDEACKNOWLEDGE(0) !Послать отрицательное подтверждение приема

END

END

END

Смотри также: DDEPOKE, DDEEXECUTE

 

DDEAPP (получить имя сервер-приложения)

DDEAPP( )

Процедура DDEAPP возвращает строку, содержащую имя приложения того DDE-канала, который инициировал последнее по времени DDE-событие. Обычно - это имя, указываемое первым параметром в процедурах DDESERVER или DDECLIENT при установлении DDE-канала.

Возвращаемый тип данных: STRING

Пример:

ClientApp STRING(20)

WinOne WINDOW,AT(0,0,160,400)

STRING(@S20),AT(5,5,90,20),USE(ClientApp)

END

TimeServer LONG

DateServer LONG

FormatTime STRING(5)

FormatDate STRING(8)

CODE

OPEN(WinOne)

TimeServer = DDESERVER('SomeApp','Time') !Регистрация сервера

DateServer = DDESERVER('SomeApp','Date') !Регистрация сервера

ACCEPT

CASE EVENT()

OF EVENT:DDErequest

CASE DDECHANNEL()

OF TimeServer

ClientApp = DDEAPP() !Получить имя клиента

DISPLAY !и отобразить на экран

FormatTime = FORMAT(CLOCK(),@T1)

DDEWRITE(TimeServer,DDE:manual,'Time',FormatTime)

OF DateServer

ClientApp = DDEAPP() !Получить имя клиента

DISPLAY !и отобразить на экран

FormatDate = FORMAT(TODAY(),@D1)

DDEWRITE(DateServer,DDE:manual,'Date',FormatDate)

END

END

END

Смотри также: DDECLIENT, DDESERVER

 

DDECHANNEL (получить номер DDE-канала)

DDECHANNEL( )

Процедура DDECHANNEL возвращает целое число типа LONG, определяющее номер DDE-канала, который инициировал последнее по времени DDE-событие для клиент-или сервер-приложения. То же самое значение возвращается функциями DDESERVER или DDECLIENT при установлении DDE-канала.

Возвращаемый тип данных: LONG

Пример:

WinOne WINDOW,AT(0,0,160,400)

END

TimeServer LONG

DateServer LONG

FormatTime STRING(5)

FormatDate STRING(8)

CODE

OPEN(WinOne)

TimeServer = DDESERVER('SomeApp','Time') !Регистрация сервера

DateServer = DDESERVER('SomeApp','Date') !Регистрация сервера

ACCEPT

CASE EVENT()

OF EVENT:DDErequest

CASE DDECHANNEL() !проверить какой канал

OF TimeServer

FormatTime = FORMAT(CLOCK(),@T1)

DDEWRITE(TimeServer,DDE:manual,'Time',FormatTime)

OF DateServer

FormatDate = FORMAT(TODAY(),@D1)

DDEWRITE(DateServer,DDE:manual,'Date',FormatDate)

END

END

END

Смотри также: DDECLIENT, DDESERVER

 

DDECLIENT (возвратить номер канала DDE-клиента)

DDECLIENT( [ приложение ] [, раздел ] )

DDECLIENT Возвращает номер канала нового DDE-клиента.

приложение Строковая константа или переменная для указания имени сервер-приложения, с которым нужно установить связь. Обычно это – имя приложения. Если параметр не указан, то используется имя приложения первого из зарегистрированных DDE-серверов.

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

Процедура DDECLIENT возвращает номер канала нового DDE-клиента, которым идентифицируются приложение и раздел. Если приложение не было запущено на исполнение, то DDECLIENT возвращает нулевое значение (0).

Обычно, когда DDE-канал открывается клиентом, приложение - это имя сервер-приложения. Раздел - это строка, содержимое которой используется либо как имя доступного раздела приложения, когда это приложение регистрирует его в Windows, либо как некоторое значение, которое говорит приложению какие данные оно должно предоставить. Приложения и разделы, зарегистрированные на данный момент в Windows, можно просмотреть используя процедуру DDEQUERY.

Возвращаемый тип данных: LONG

Пример:

DDEReadVal REAL

WinOne WINDOW,AT(0,0,160,400)

ENTRY(@s20),USE(DDEReadVal)

END

ExcelServer LONG

CODE

OPEN(WinOne)

!Создать клиента Excel-таблицы:

ExcelServer = DDECLIENT('Excel','MySheet.XLS')

IF NOT ExcelServer !Если сервер не был запущен, то

MESSAGE('Please start Excel') !предложить пользователю запустить его

RETURN !и осуществить следующую попытку

END

DDEREAD(ExcelServer,DDE:auto,'R5C5',DDEReadVal)

ACCEPT

CASE EVENT()

OF EVENT:DDEdata !Когда обновленные данные поступают от Excel

PassedData(DDEReadVal) !обработать их

END

END

Смотри также: DDEQUERY, DDEWRITE, DDESERVER

 

DDECLOSE (завершить диалог с DDE-сервером)

DDECLOSE( канал )

DDECLOSE Закрывает открытый канал DDE.

канал Метка переменной типа LONG, указывающая номер канала - то значение, которое возвращают процедуры DDESERVER или DDECLIENT.

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

Выдаваемые сообщения об ошибках:

601 Invalid DDE Channel (Недопустимый DDE-канал)

602 DDE Channel Not Open (Канал DDE не открыт)

605 Time Out (Ошибка по тайм-ауту)

Пример:

WinOne WINDOW,AT(0,0,160,400)

END

SomeServer LONG

CODE

OPEN(WinOne)

SomeServer = DDECLIENT('SomeApp','MyTopic') !Канал клиента

ACCEPT

END

DDECLOSE(SomeServer)

Смотри также: DDECLIENT, DDESERVER

 

DDEEXECUTE (послать команду DDE серверу)

DDEEXECUTE( канал, команда )

DDEEXECUTE Посылает командную строку в открытый канал DDE-клиента.

канал Целочисленная константа типа LONG или переменная, указывающие канал клиента - то значение, которое возвращает процедура DDECLIENT.

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

Процедура DDEEXECUTE позволяет программе DDE-клиента передавать команду серверу. Формат команды должен быть таким, чтобы сервер мог ее понять и исполнить. В качестве сервера может быть и не Clarion-программа. По принятому соглашению строка-команда заключается в квадратные скобки ([ ]).

DDE-сервер Clarion-приложения может воспользоваться процедурой DDEVALUE() для того, чтобы узнать какую команду послал клиент. Оператор CYCLE в конце обработки события DDE:EVENTexecute присылает клиенту положительное подтверждение приема посланной им команды. DDEACKNOWLEDGE может посылать как положительное, так и отрицательное подтверждение.

Выдаваемые сообщения об ошибках:

601 Invalid DDE Channel (Недопустимый DDE-канал)

602 DDE Channel Not Open (Канал DDE не открыт)

603 DDEEXECUTE Failed (Ошибка команды DDEEXECUTE)

605 Time Out (Ошибка по тайм-ауту)

Генерируемые события:

EVENT:DDEexecute Клиент прислал запрос-команду.

Пример:

!Фрагмент программы сервер-приложения:

WinOne WINDOW,AT(0,0,160,400)

END

SomeServer LONG

DDEChannel LONG

CODE

OPEN(WinOne)

!Открыть канал связи с Windows Program Manager:

DDEChannel = DDECLIENT('PROGMAN','PROGMAN')

!Создать группу для новой программы:

DDEEXECUTE(DDEChannel,'[CreateGroup(Clarion Applications)]')

!Отобразить ее на экран:

DDEEXECUTE(DDEChannel,'[ShowGroup(1)]')

!Создать новый элемент группы, используя вторую иконку в progman.exe

DDEEXECUTE(DDEChannel,'[AddItem(MYAPP.EXE,My Program,PROGMAN.EXE,2)]')

Смотри также: DDEACKNOWLEDGE, DDEVALUE

 

DDEITEM (получить имя элемента данных сервера)

DDEITEM( )

Для имевшего место DDE-события процедура DDEITEM возвращает строку с наименованием элемента динамического обмена между клиентом и сервером. Под элементом подразумевается либо элемент, запрошенный оператором DDEREAD, либо элемент данных, предоставленный DDEPOKE.

Возвращаемый тип данных: STRING

Пример:

WinOne WINDOW,AT(0,0,160,400)

END

Server LONG

FormatTime STRING(5)

FormatDate STRING(8)

CODE

OPEN(WinOne)

Server = DDESERVER('SomeApp','Clock') !Зарегистрировать сервер для моего раздела

ACCEPT

CASE EVENT()

OF EVENT:DDErequest

CASE DDEITEM()

OF 'Time'

FormatTime = FORMAT(CLOCK(),@T1)

DDEWRITE(Server,DDE:manual,'Time',FormatTime)

OF 'Date'

FormatDate = FORMAT(TODAY(),@D1)

DDEWRITE(Server,DDE:manual,'Date',FormatDate)

END

OF EVENT:DDEadvise

CASE DDEITEM()

OF 'Time'

FormatTime = FORMAT(CLOCK(),@T1)

DDEWRITE(Server,1,'Time',FormatTime)

OF 'Date'

FormatDate = FORMAT(TODAY(),@D1)

DDEWRITE(Server,60,'Date',FormatDate)

END

END

END

Смотри также: DDEREAD, DDEEXECUTE, DDEPOKE

 

DDEPOKE (послать незапрашиваемые данные DDE-серверу)

DDEPOKE( канал, элемент, значение )

DDEPOKE Посылает DDE-серверу незапрашиваемые данные через открытый канал DDE-клиента.

канал Целочисленная константа типа LONG или переменная, указывающие канал клиента - то значение, которое возвращает процедура DDECLIENT.

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

значение Строковая константа или переменная, в которых находятся данные, предназначенные для элемента.

Процедура DDEPOKE позволяет программе DDE-клиента пересылать незапрашиваемые данные серверу. Чтобы сервер смог распознать и обработать данные, параметры элемент и значение должны быть представлены в формате данных сервер-приложения. В качестве сервера может быть и не Clarion-программа.

DDE-сервер Clarion-приложения, чтобы выяснить что ему прислал клиент, может воспользоваться процедурами DDEITEM() и DDEVALUE(). Опреатор CYCLE в конце обработки события DDE:EVENTpoke присылает клиенту положительное подтверждение приема неиспрашиваемых данных. DDEACKNOWLEDGE может посылать как положительное, так и отрицательное подтверждение.

Выдаваемые сообщения об ошибках:

601 Invalid DDE Channel (Недопустимый DDE-канал)

602 DDE Channel Not Open (Канал DDE не открыт)

604 DDEPOKE Failed (Ошибка команды DDEPOKE)

605 Time Out (Ошибка по тайм-ауту)

Генерируемые события:

EVENT:DDEpoke Клиент прислал незапрашиваемые данные.

Пример:

WinOne WINDOW,AT(0,0,160,400)

END

DDEChannel LONG

CODE

OPEN(WinOne)

DDEChannel = DDECLIENT('Excel','System') !Открыть канал связи с Excel

DDEEXECUTE(DDEChannel,'[NEW(1)]') !Создать новую таблицу

DDEEXECUTE(DDEChannel,'[Save.As("DDE_CHART.XLS")]') !Сохранить ее в файле DDE_CHART.XLS

DDECLOSE(DDEChannel) !Завершить диалог

DDEChannel = DDECLIENT('Excel','DDE_CHART.XLS') !Установить канал связи с новой диашраммой

DDEPOKE(DDEChannel,'R1C2','Widgets') !Переслать в нее данные

DDEPOKE(DDEChannel,'R1C3','Gadgets')

DDEPOKE(DDEChannel,'R2C1','East')

DDEPOKE(DDEChannel,'R3C1','West')

DDEPOKE(DDEChannel,'R2C2','450')

DDEPOKE(DDEChannel,'R3C2','275')

DDEPOKE(DDEChannel,'R2C3','340')

DDEPOKE(DDEChannel,'R3C3','390')

DDEEXECUTE(DDEChannel,'[SELECT("R1C1:R3C2")]') !Подсветить переданные данные

DDEEXECUTE(DDEChannel,'[NEW(2,2)]') !и создать новую диаграмму

!Посылаем ряд команд по форматированию диаграммы и работы и нею

DDECLOSE(DDEChannel) !Закрыть канал после окончания работы

Смотри также: DDEACKNOWLEDGE, DDEITEM, DDEVALUE

 

DDEQUERY (просмотр зарегистрированных DDE-серверов)

DDEQUERY( [ приложение ] [, раздел ] )

DDEQUERY Возвращает список зарегистрированных на данный момент DDE-серверов.

приложение Строковая константа или переменная для указания имени опрашиваемого приложения. Для большинства приложений - это имя приложения. Если параметр не указан, то возвращается список всех приложений, которые зарегистрированы вместе с указанным разделом.

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

Процедура DDEQUERY возвращает строку, содержащую имена приложений и их разделов зарегистрированных на данный момент DDE-серверов.

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

Данные в возвращаемой строке представляются в формате приложение:раздел, где пары приложение, раздел отделяются - когда их больше одной - друг от друга символом запятой (например, ‘Excel:MySheet.XLS,ClarionApp:DataFile.DAT’).

Возвращаемый тип данных: STRING

Пример:

!Этот пример не обрабатывает DDEADVISE

WinOne WINDOW,AT(0,0,160,400)

END

SomeServer LONG

ServerString STRING(200)

CODE

OPEN(WinOne)

LOOP

ServerString = DDEQUERY() !Указать все зарегистрированные серверы

IF NOT INSTRING('SomeApp:MyTopic',ServerString,1,1)

MESSAGE('Open SomeApp, Please')

ELSE

BREAK

END

END

SomeServer = DDECLIENT('SomeApp','MyTopic') !Зарегистрировать клиента

ACCEPT

END

DDECLOSE(SomeServer)

 

DDEREAD (получить данные от DDE-сервера)

DDEREAD( канал, режим, элемент [, переменная ] )

DDEREAD Получает данные из ранее открытого канала DDE-клиента.

канал Целочисленная константа типа LONG или переменная, указывающие канал клиента - то значение, которое возвращает процедура DDECLIENT.

режим Символическое имя, определяющее тип канала передачи данных: DDE:auto, DDE:manual или DDE:remove (определены в файле EQUATES.CLW).

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

переменная Имя переменной, в которую будут занесены запрашиваемые данные. Если параметр не указан и установлен режим DDE:remove, то обрываются все связи с элементом.

Процедура DDEREAD дает возможность программе DDE-клиента читать данные из канала в переменную. Параметром режим определяется способ обновления данных. Значение параметра элемент в качестве строки передается сервер-приложению для указания элемента данных, который запрашивается клиентом. Формат и структура строки элемента зависит от сервер-приложения.

Если текущим режимом является DDE:auto, переменная обновляется сервером постоянно (“горячая” связь). Событие EVENT:DDEdata генерируется всякий раз, когда переменная обновлена с сервера.

Если текущим режимом является DDE:manual, переменная обновляется единожды, и больше не генерируется никаких событий. Для проверки на наличие каких-нибудь изменившихся значений (“холодная” связь), серверу должен быть послан другой запрос DDEREAD.

Если текущим режимом является DDE:remove, предыдущая “горячая” связь с переменной прекращается. При наличии режима DDE:remove и отсутствии параметра переменная все предыдущие “горячие” связи с разделом прекращаются независимо от того, какие переменные были связаны. Это означает, что клиент должен послать серверу другой запрос DDEREAD, предназначенный для проверки любых измененных значений.

Выдаваемые сообщения об ошибках:

601 Invalid DDE Channel (Недопустимый DDE-канал)

602 DDE Channel Not Open (Канал DDE не открыт)

605 Time Out (Ошибка по тайм-ауту)

Генерируемые события: Клиент-приложению посылаются следующие события:

EVENT:DDEdata

Сервер прислал обновленный элемент данных по “горячей” линии.

EVENT:DDEclosed

Сервер завершил диалог.

Пример:

WinOne WINDOW,AT(0,0,160,400)

END

ExcelServer LONG(0)

DDEReadVal REAL

CODE

OPEN(WinOne)

!Клиент Excel таблицы

ExcelServer = DDECLIENT('Excel','MySheet.XLS')

IF NOT ExcelServer !Если сервер не был запущен

MESSAGE('Please start Excel') !предложить пользователю запустить его

CLOSE(WinOne)

RETURN

END

!Запрос серверу на постоянное обновление:

DDEREAD(ExcelServer,DDE:auto,'R5C5',DDEReadVal)

ACCEPT

CASE EVENT()

OF EVENT:DDEdata !При поступлении от Excel обновленных данных

PassedData(DDEReadVal) ! вызвать процедуру их обработки

END

END

Смотри также: DDEQUERY, DDEWRITE, DDESERVER

 

DDESERVER (возвратить номер канала DDE- сервера)

DDESERVER( [ приложение ] [, раздел ] )

DDESERVER Возвращает номер канала нового DDE-сервера.

приложение Строковая константа или переменная для указания имени приложения. Обычно это - имя приложения. Если параметр не указан, то используется имя файла (без расширения) программы.

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

Процедура DDESERVER возвращает номер канала нового DDE-сервера, которым идентифицируются приложение и раздел. Номер канала определяет тот раздел, данные которого будут предоставляться приложением. Это дает возможность одному Clarion-приложению регистрироваться в качестве DDE-сервера нескольких разделов.

Возвращаемый тип данных: LONG

Пример:

DDERetVal STRING(20)

WinOne WINDOW,AT(0,0,160,400)

ENTRY(@s20),USE(DDERetVal)

END

MyServer LONG

CODE

OPEN(WinOne)

MyServer = DDESERVER('MyApp','DataEntered') !Регистрируется сервер

ACCEPT

CASE EVENT()

OF EVENT:DDErequest !Обслуживание однократного запроса данных

DDEWRITE(MyServer,DDE:manual,'DataEntered',DDERetVal) !Однократное предоставление данных

OF EVENT:DDEadvise !Обслуживание запроса на постоянное обновление

DDEWRITE(MyServer,15,'DataEntered',DDERetVal)

!Отслеживать изменения каждые 15 секунд

!и предоставить данные как только они обновились

END

END

Смотри также: DDECLIENT, DDEWRITE

 

DDETOPIC (получить имя раздела сервера)

DDETOPIC( )

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

Возвращаемый тип данных: STRING

Пример:

WinOne WINDOW,AT(0,0,160,400)

END

TimeServer LONG

DateServer LONG

FormatTime STRING(5)

FormatDate STRING(8)

CODE

OPEN(WinOne)

TimeServer = DDESERVER('SomeApp') !Регистрация сервера

ACCEPT

CASE EVENT()

OF EVENT:DDErequest

CASE DDETOPIC() !Получить имя запрошенного раздела

OF 'Time'

FormatTime = FORMAT(CLOCK(),@T1)

DDEWRITE(TimeServer,DDE:manual,'Time',FormatTime)

OF 'Date'

FormatDate = FORMAT(TODAY(),@D1)

DDEWRITE(DateServer,DDE:manual,'Date',FormatDate)

END

END

END

Смотри также: DDEREAD, DDECLIENT, DDESERVER

 

DDEVALUE (получить значение данных, посланных серверу)

DDEVALUE( )

Процедура DDEVALUE возвращает строку с данными, посланными DDE-серверу Clarion-приложения оператором DDEPOKE, либо командой, выполненной оператором DDEEXECUTE.

Возвращаемый тип данных: STRING

Пример:

WinOne WINDOW,AT(0,0,160,400)

END

TimeServer LONG

TimeStamp FILE,DRIVER(ASCII),PRE(Tim)

Record RECORD

FormatTime STRING(5)

FormatDate STRING(8)

Message STRING(50)

END

END

CODE

OPEN(WinOne)

TimeServer = DDESERVER('TimeStamp') !Зарегистрировать сервер

ACCEPT

CASE EVENT()

OF EVENT:DDEpoke

OPEN(TimeStamp)

Tim:FormatTime = FORMAT(CLOCK(),@T1)

Tim:FormatDate = FORMAT(TODAY(),@D1)

Tim:Message = DDEVALUE() !Получить данные

ADD(TimeStamp)

CLOSE(TimeStamp)

CYCLE !Подтвердить получение

END

END

Смотри также: DDEPOKE, DDEEXECUTE

 

DDEWRITE (предоставить данные DDE-клиенту)

DDEWRITE( канал, режим, элемент [, переменная ] )

DDEWRITE Передает данные в открытый канал DDE-сервера.

канал Целочисленная константа типа LONG или переменная, указывающие канал сервера - то значение, которое возвращает процедура DDESERVER.

режим Либо целочисленная константа или переменная для указания интервала времени (в секундах), в по истечению которого каждый раз производится опрос переменной для проверки изменения ее значения, либо символическое имя, определяющее тип канала передачи данных: DDE:auto, DDE:manual или DDE:remove (определены в файле EQUATES.CLW).

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

переменная Имя переменной предоставляющей данные. Если параметр не указан и установлен режим DDE:remove, то обрываются все каналы связи с элементом .

Процедура DDEWRITE дает возможность программе DDE-сервера предоставлять клиенту значение переменной. Значение параметра элемент представляет собой строку для указания предоставляемого элемента данных. Формат и структура строки элемента зависит от сервер-приложения. Параметром режим определяется способ обновления данных.

Если параметр режим принимает значение DDE:auto, то клиент-программа получает текущее значение переменной и на все последующие запросы этого (или любого другого) клиента внутренние библиотеки будут предоставлять тоже самое значение. Когда клиент запросил обмен данными по “горячей” линии, то Clarion-программа должна сама отслеживать любые изменения значения переменной и посылать клиенту обновленные данные посредством исполнения оператора DDEWRITE.

Если параметр режим принимает значение DDE:manual, то переменная обновляется только один раз. Когда клиент запросил обмен данными по “горячей” линии, то Clarion-программа должна сама отслеживать любые изменения значения переменной и посылать клиенту обновленные данные посредством исполнения оператора DDEWRITE. Для установки или получения величины интервала времени для связи DDE (по умолчанию пять секунд) может использоваться PROP:DDETimeOut.

Если параметр режим принимает целые положительные значения, то внутренние библиотеки по истечению указанного промежутка времени (в секундах) каждый раз проводят проверку значения переменной. Если значение изменилось, то внутренние библиотеки автоматически (дополнительные Clarion-операторы не нужны) передают клиенту обновленное значение. Следует отметить, что при этом - в зависимости от данных - возникают значительные накладные расходы, и использовать данный режим рекомендуется только по необходимости.

Если для параметра режим указано значение DDE:remove, то разрывается ранее установленная “горячая” линия связи с переменной. Если для параметра режим указано значение DDE:remove, а параметр переменная не указан, то разрываются все ранее установленные “горячие” линии связи с элементом, независимо от того, какие переменные были с ним связаны. Поэтому, для обнаружения изменения значения данных клиенту нужно снова послать серверу DDEREAD запрос.

Выдаваемые сообщения об ошибках:

601 Invalid DDE Channel (Недопустимый DDE-канал)

602 DDE Channel Not Open (Канал DDE не открыт)

605 Time Out (Ошибка по тайм-ауту)

Генерируемые события:

EVENT:DDErequest

Запрос клиента на элемент данных (“холодная линия”).

EVENT:DDEadvise

Запрос клиента на постоянное обновление элемента данных (“горячая” линия).

Пример:

DDERetVal STRING(20)

WinOne WINDOW,AT(0,0,160,400)

ENTRY(@s20),USE(DDERetVal)

END

MyServer LONG

CODE

OPEN(WinOne)

MyServer = DDESERVER('MyApp','DataEntered') !Зарегистрировать сервер

ACCEPT

CASE EVENT()

OF EVENT:DDErequest !Сервер для однократно запрашиваемых данных

DDEWRITE(MyServer,DDE:manual,'DataEntered',DDERetVal) !Однократное предоставление данных

OF EVENT:DDEadvise !Сервер запроса непрерывного обновления

DDEWRITE(MyServer,15,'DataEntered',DDERetVal)

!Проверка на изменение каждые 15 сек

!и предоставление измененных данных

END

END

Смотри также: DDEQUERY, DDEREAD, DDESERVER

 

Связывание и внедрение объектов

Введение в OLE

Механизм связывания и внедрения объектов (Object Linking and Embedding - OLE) позволяет “объекты” из одного приложения Windows связать или включить в “документ” (структуру данных) другого приложения. Приложение, создающее и поддерживающее объект, является приложением-сервером OLE, тогда как приложение, которое содержит объект, называется OLE контроллером (его иногда еще называют OLE клиентом). Объекты внедрения или связывания - это структуры данных, присущие приложению – серверу OLE (такие как график из электронной таблицы или рисунок из приложения - графического редактора). Этот объект помещается в окно-контейнер приложения контроллера. В приложении на языке Clarion окно контейнер и является управляющим элементом типа OLE.

Реализация OLE в Clarion для Windows позволяет, написанным на нем приложениям, служить OLE контроллером, связывая или включая объекты от любого приложения - OLE сервера. Реализация в Clarion OLE поддерживает также автоматизацию OLE, которая представляет собой способность OLE контроллера динамически управлять OLE сервером, используя его макроязык.

Связывание объектов

Связывание объектов в общем случае означает, что в OLE контроллере содержится “ссылка” на объект, будь то объект целой структурой данных (подобно файлу электронной таблицы) или компонентом такой структуры (как, например, диапазон ячеек в той же таблице). При связывании объекта с OLE контроллером контроллер содержит только информацию, необходимую для нахождения связанных данных. Эта информация может храниться или в поле BLOB или файле - комплексном хранилище (OLE Compound Storage file).

Внедрение объектов

Внедрение объектов означает, что OLE контроллер хранит весь объект целиком, независимо от приложения-сервера OLE. Внедренный в приложение-контроллер объект не существует в виде отдельного файла, к которому могло бы обращаться приложение-сервер. Приложение - OLE контроллер полностью содержит активный объект, который хранится либо в BLOB, либо в файле - комплексном хранилище (OLE Compound Storage file).

Поддержка объектов OLE

Любой OLE объект в приложении-контроллере, внедренный или связанный, поддерживается приложением-сервером, создавшим этот объект. Это означает, что когда пользователь хочет изменить этот объект, то для того чтобы сделать эти изменения, OLE контроллер активизирует приложение-сервер. Есть два способа активизации сервера: активизация “на месте” (in place) и активизация в “режиме открытия” (“open-mode”).

Активизация “на месте”

Активизация “на месте” означает, что пользователю кажется, будто бы он остается в приложении OLE контроллере, но меню и панель инструментов сервера объединяются с меню и инструментами контроллера, а текущим исполняемым приложением является приложение-сервер. Редактируемый объект имеет мерцающую рамку, чтобы обозначить то, что он находится в режиме редактирования.

Если в приложении сервере имеется одна или несколько панелей инструментов, то эта панель инструментов появляется либо в виде всплывающей панели, либо присоединенной к одному из краев рамки, либо в сочетании этих подходов. Это может приводить к “выпаданию” вниз объектов управления вашего окна, так что будьте внимательны при проектировании окна с OLE объектами.

Активизация в режиме открытия

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

Свойства контейнера объекта OLE

С контейнером объекта OLE связаны несколько свойств, относящихся только к объектам типа OLE (но не OCX).

Свойства-атрибуты

PROP:Create Атрибут CREATE (пробел, если нет такого атрибута). (только присвоение значения)

PROP:Open Атрибут OPEN (пробел, если нет такого атрибута). (только присвоение значения)

PROP:Document Атрибут DOCUMENT (пробел, если нет такого атрибута). (только присвоение значения)

PROP:Link Атрибут LINK (пробел, если нет такого атрибута). (только присвоение значения)

PROP:Clip Атрибут CLIP. Атрибут-переключатель. Присвоение нулевой строки (‘’) или 0 выключает его, ‘1’ или 1 - включает. (Только присвоение значения)

PROP:Stretch Атрибут STRETCH. Атрибут-переключатель. Присвоение нулевой строки (‘’) или 0 выключает его, ‘1’ или 1 - включает. (Только присвоение значения)

PROP:Autosize Атрибут AUTOSIZE. Атрибут-переключатель. Присвоение нулевой строки (‘’) или 0 выключает его, ‘1’ или 1 - включает. (Только присвоение значения)

PROP:Zoom Атрибут ZOOM. Атрибут-переключатель. Присвоение нулевой строки (‘’) или 0 выключает его, ‘1’ или 1- включает. (Только присвоение значения)

PROP:Compatibility Атрибут COMPATIBILITY (пробел, если нет такого атрибута) (только присвоение значения)

Необъявленные свойства

 

PROP:Blob Преобразует объект в/из переменную BLOB. (ЧТЕНИЕ/ЗАПИСЬ)

PROP:SaveAs Сохраняет объект в файле - комплексном хранилище. (Только ЗАПИСЬ). Для занесения объекта в комплексное хранилище используется синтаксис:имя_файла\!компонент’. Например:

?controlx{PROP:SaveAs} = ‘myfile\!objectx’

PROP:DoVerb Выполняет OLE doverb команду из следующего набора команд. (Только ЗАПИСЬ):

DOVERB:Primary (0)

Вызывает первичные действия объекта. Что это за действия, определяется самим объектом, а не контейнером. Если для объекта поддерживается активизация “на месте”, то обычно первичное действие это и делает.

DOVERB:Show (-1)

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

DOVERB:Open (-2)

Сообщает объекту о том, что он должен открыться для просмотра и редактирования в отдельном от контейнера окне (это относится объектам, поддерживающим активизацию “на месте”). Если объект активизацию “на месте” не поддерживает, то эта команда для него эквивалентна команде DOVERB:Show.

DOVERB:Hide (-3)

Сообщает объекту о том, что он должен убрать свой интерфейс пользователя. Эта команда применима только к объектам, активизируемым “на месте”.

DOVERB:UIActivate (-4)

Активизирует объект “на месте” наряду с его полным набором инструментальных средств, включая меню, панели инструментов и его имя в строке заголовка окна-контейнера.

DOVERB:InPlaceActivate (-5)

Активизирует объект “на месте” не включая набор инструментальных средств (меню и панели инструментов), которые необходимы пользователю для изменения внешнего вида и поведения объекта.

DOVERB:DiscardUndoState (-6)

Предписывает объекту уничтожить содержимое буфера изменений (UNDO), которые объект возможно поддерживает, не деактивируя при этом сам объект.

DOVERB:Properties (-7)

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

PROP:Deactivate Деактивизирует OLE объект, активизированный “на месте”. (ЧТЕНИЕ/ЗАПИСЬ/ВЫПОЛНЕНИЕ)

PROP:Update Предписывает объекту обновить самого себя. (ЧТЕНИЕ /ЗАПИСЬ/ ВЫПОЛНЕНИЕ)

PROP:CanPaste Можно ли объект помещать во внутренний буфер обмена? (Только ЧТЕНИЕ)

PROP:Paste Помещает объект из внутреннего буфера обмена в экранный контейнер. (ЧТЕНИЕ/ЗАПИСЬ/ВЫПОЛНЕНИЕ).

PROP:CanPasteLink Можно ли объект, находящийся во внутреннем буфере обмена поместить в контейнер в виде связи? (Только ЧТЕНИЕ)

PROP:PasteLink Помещает и связывает объект, находящийся во внутреннем буфере, в OLE контейнер. (ЧТЕНИЕ/ЗАПИСЬ/ВЫПОЛНЕНИЕ)

PROP:Copy Копирует объект из OLE контейнера во внутренний буфер. (ЧТЕНИЕ/ЗАПИСЬ/ВЫПОЛНЕНИЕ)

PROP:ReportException

Послать объекту OLE прерывание (для отладки) (Только ЗАПИСЬ).

PROP:OLE Определить находится ли в контейнере объект OCX или OLE? (Только ЧТЕНИЕ)

PROP:Language "Номер" языка, используемого для OLE или OCX. Номер US English 0409H, номера других языков могут быть вычислены в WINNT.H файле в MS Windows SDK (ЧТЕНИЕ/ЗАПИСЬ).

Пример:

PROGRAM

MAP

INCLUDE('OCX.CLW')

SelectOleServer PROCEDURE(OleQ PickQ),STRING

END

INCLUDE 'XL.CLW' !Константы, используемые Excel

INCLUDE 'ERRORS.CLW' !Включить коды ошибок

SaveLinks FILE,DRIVER('TopSpeed'),PRE(SAV),CREATE

Object BLOB

Record RECORD

LinkType STRING(1) !F = File, B = BLOB

LinkFile STRING(64) !Имя файла комплексного хранилища OLE и объектов

END

END

i LONG !Счетчики цикла

j LONG

ResultQ QUEUE !Очередь для хранения данных из OLEDIRECTORY

Name CSTRING(64)

CLSID CSTRING(64)

ProgID CSTRING(64)

END

MainWin WINDOW('OLE Demo'),AT(,,350,200),STATUS(-1,-1),SYSTEM,GRAY,RESIZE,MAX,TIMER(1)

MENUBAR

MENU('&File')

ITEM('e&xit'),USE(?exit)

END

MENU('&Objects')

ITEM('Create Object'),USE(?CreateObject)

ITEM('Paste Object'),USE(?PasteObject)

ITEM('PasteLink Object'),USE(?PasteLinkObject)

ITEM('Save Object to BLOB'),USE(?SaveObjectBlob),DISABLE

ITEM('Save Object to OLE File'),USE(?SaveObjectFile),DISABLE

ITEM('Retrieve Saved Object'),USE(?GetObject),DISABLE

END

MENU('&Activate')

ITEM('&Spreadsheet'),USE(?ActiveExcel)

ITEM('&Any OLE Object'),USE(?ActiveOLE),DISABLE

END

END

OLE,AT(5,10,160,100),COLOR(0808000H),USE(?ExcelObject)

MENUBAR

MENU('&Clarion App')

ITEM('&Deactivate Excel'),USE(?DeactExcel)

END

END

END

OLE,AT(170,10,160,100),USE(?AnyOLEObject),AUTOSIZE

MENUBAR

MENU('&Clarion App')

ITEM('&Deactivate Object'),USE(?DeactOLE)

END

END

END

END

CODE

OPEN(SaveLinks)

IF ERRORCODE() !Проверить, что Open без ошибок

IF ERRORCODE() = NoFileErr !Если файл не существует

CREATE(SaveLinks) !то создать его

IF ERRORCODE() THEN HALT(,ERROR()) END

OPEN(SaveLinks) !а затем открыть

IF ERRORCODE() THEN HALT(,ERROR()) END

ELSE

HALT(,ERROR())

END

END

OPEN(MainWin)

?ExcelObject{PROP:Create} = 'Excel.Sheet.5' !Создать объект - таблицу Excel

DO BuildSheetData !заполнить ее произвольными данными

IF RECORDS(SaveLinks) !Проверить существование сохраненной записи

SET(SaveLinks) !взять ее

NEXT(SaveLinks)

POST(EVENT:Accepted,?GetObject) !и отобразить

DO MenuEnable

ELSE

ADD(SaveLinks) !или добавить пустую запись

END

IF ERRORCODE() THEN HALT(,ERROR()) END

ACCEPT

CASE EVENT()

OF EVENT:CloseWindow

?ExcelObject{PROP:Deactivate} !Закрыть приложение - сервер

?AnyOLEObject{PROP:Deactivate}

OF EVENT:Timer

IF CLIPBOARD()

IF ?AnyOLEObject{PROP:CanPaste} !Допустима вставка из буфера обмена?

IF ?PasteObject{PROP:Disable}

ENABLE(?PasteObject)

END

ELSIF NOT ?PasteObject{PROP:Disable}

DISABLE(?PasteObject)

END

IF ?AnyOLEObject{PROP:CanPasteLink} !Допустима вставка из буфера обмена?

IF ?PasteLinkObject{PROP:Disable}

ENABLE(?PasteLinkObject)

END

ELSIF NOT ?PasteLinkObject{PROP:Disable}

DISABLE(?PasteLinkObject)

END

END

OF EVENT:Accepted

CASE FIELD()

OF ?Exit

POST(EVENT:CloseWindow)

OF ?CreateObject

OLEDIRECTORY(ResultQ,0) !Получить список установленных OLE серверов

?AnyOLEObject{PROP:Create} = SelectOleServer(ResultQ) !Дать пользоваптелю выбрать

?AnyOLEObject{PROP:DoVerb} = 0 !Активизировать OLE сервер в режиме “по умолчанию”

DO MenuEnable

OF ?PasteObject

?AnyOLEObject{PROP:Paste} !Вставить объект

SETCLIPBOARD('Paste Completed') !Поместить в буфер простой текст

DO MenuEnable

OF ?PasteLinkObject

?AnyOLEObject{PROP:PasteLink} !объект PasteLink

SETCLIPBOARD('PasteLink Completed') !Поместить в буфер простой текст

DO MenuEnable

OF ?SaveObjectBlob !Запомнить объект в поле BLOB

SAV:Object{PROP:Handle} = ?AnyOLEObject{PROP:Blob}

SAV:LinkType = 'B'

PUT(SaveLinks)

IF ERRORCODE() THEN STOP(ERROR()) END

OF ?SaveObjectFile !Сохранить в OLE Compound Storage file

?AnyOLEObject{PROP:SaveAs} = 'TEST1.OLE\!Object'

SAV:LinkFile = 'TEST1.OLE\!Object'

SAV:LinkType = 'F'

PUT(SaveLinks)

IF ERRORCODE() THEN STOP(ERROR()) END

OF ?GetObject

IF SAV:LinkType = 'F' !Сохранить в OLE Compound Storage file?

?AnyOLEObject{PROP:Open} = SAV:LinkFile

ELSIF SAV:LinkType = 'B' !Сохранить в BLOB?

?AnyOLEObject{PROP:Blob} = SAV:Object{PROP:Handle}

END

DISPLAY

OF ?ActiveExcel

?ExcelObject{PROP:DoVerb} = 0 !Запустить Excel “на месте

OF ?ActiveOLE

?AnyOLEObject{PROP:DoVerb} = 0 !Активизировать OLE сервер в режимепо умолчанию

OF ?DeactExcel

?ExcelObject{PROP:Deactivate} !Вернуться в Clarion программу

OF ?DeactOLE

?AnyOLEObject{PROP:Deactivate} !Вернуться в Clarion программу

END !CASE FIELD()

END !CASE EVENT0()

END !ACCEPT

BuildSheetData ROUTINE !Использовать для построения таблицы

!OLE автоматизацию

?ExcelObject{PROP:ReportException} = TRUE !Excel сообщит о любых ошибках

?ExcelObject{'Application.Calculation'} = xlManual !выключить автопересчет

LOOP i = 1 TO 3 !Заполнить таблицу значениями

LOOP j = 1 TO 3

?ExcelObject{'Cells(' & i & ',' & j & ').Value'} = Random(100,900)

END

?ExcelObject{'Cells(4,' & i & ').Value'} = 'Sum'

?ExcelObject{'Cells(5,' & i & ').FormulaR1C1'} = '=SUM(R[-4]C:R[-2]C)'

?ExcelObject{'Cells(6,' & i & ').Value'} = 'Average'

?ExcelObject{'Cells(7,' & i & ').FormulaR1C1'} = '=AVERAGE(R[-6]C:R[-4]C)'

END

!turn auto recalc back on

?ExcelObject{'Application.Calculation'} = xlAutomatic

DISPLAY

MenuEnable ROUTINE !Включить пункты меню

ENABLE(?ActiveOLE)

ENABLE(?SaveObjectBlob,?GetObject)

SelectOleServer PROCEDURE(OleQ PickQ)

window WINDOW('Choose OLE Server'),AT(,,122,159),CENTER,SYSTEM,GRAY

LIST,AT(11,8,100,120),USE(?List),HVSCROLL, |

FORMAT('146L~Name~@s64@135L~CLSID~@s64@20L~ProgID~@s64@'),FROM(PickQ)

BUTTON('Select'),AT(42,134),USE(?Select)

END

CODE

OPEN(window)

SELECT(?List,1)

ACCEPT

CASE ACCEPTED()

OF ?Select

GET(PickQ,CHOICE(?List))

IF ERRORCODE() THEN STOP(ERROR()) END

POST(EVENT:CloseWindow)

END

END

RETURN(PickQ.ProgID)

Свойства, влияющие на интерфейс

PROP:Object Взять изначальный интерфейс объекта. (ТОЛЬКО ЧТЕНИЕ)

В Visual Basic для панели инструментов и объекта-иерархической структуры для отображения пиктограмм на кнопках инструментов и в дереве используется объект “image-list” (список изображений). Для того, чтобы связать объект - изображение с инструментальной панелью, используется следующий оператор:

?toolbar{'ImageList'} = ?imagelist{prop:object}

PROP:SelectInterface Выбирает интерфейс, который следует использовать с данным объектом. (ТОЛЬКО ПРИСВОЕНИЕ)

?x{PROP:SelectInterface} = 'x.y'

?x{'z(1)'} = 1

?x{'z(2)'} = 2

имеет то же значение, что и

?x{'x.y.z(1)'} = 1

?x{'x.y.z(2)'} = 2

PROP:AddRef Увеличить счетчик обращений для интерфейса. (ТОЛЬКО ПРИСВОЕНИЕ)

PROP:Release Уменьшить счетчик обращений для интерфейса (ТОЛЬКО ПРИСВОЕНИЕ)

Библиотеки Clarion OLE/OCX и иерархия объектов:

Во время проектирования и реализации библиотеки Clarion OLE, отказ в доступе к вторичным объектам, созданных первичным объектом (например из excel: ExcelUse{'Application.Charts.Add'}), не считался проблемой, так как существовали другие способы получения доступа к объекту:

ExcelUse {'Application.Charts(Chart1).ChartWizard(' &?ex{'Range(A5:C5)'}&','&xl3DPie&',7,1,0,0,2,,,,)'}.

В то время был известен только один случай, когда это нельзя было использовать. Это возможно и на сегодняшний день, так как стандарты OLE регламентирует, что коллекция реализации объектов должна также реализовывать метод для доступа к объектам путем индексирования.

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

Вызывая метод, который возвращает IDispatchInterface преобразованный в специальное представление ( '`' сопровождающиеся множеством цифр). Это специальное представление признано в паре мест в библиотеке OLE.

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

x=y{'charts.add()')

y{x&'p(7)'}

где y – ole-объект, а x - cstring. Это пример метода, возвращающего интерфейс и затем этот интерфейс использован для доступа к методу p с параметром 7.

В этом контексте, дальнейшее осложнение возникает в формировании указателя подсчитывающего использование в OLE. Это означает, что если объект используется неоднократно, он должен иметь такой указатель-счетчик увеличивающийся перед использованием.

x=y{'charts.add()')

y{PROP:AddRef}=x

y{x&'p(7)'}

y{x&'p(7)'} ;последнее использование x

 

OLEDIRECTORY (получить список установленных OLE/OCX)

OLEDIRECTORY( список , флаг [, битность ] )

OLEDIRECTORY Получить список установленных OLE серверов или объектов OCX.

список Метка структуры QUEUE, в которую заносится список.

флаг Целочисленная константа или переменная, которая определяет, получить ли спсиок OLE серверов (флаг = 0) или список объектов OCX (флаг = 1).

битность Целочисленная константа или переменная, которая определяет, что следует получить список либо 16-битных, либо 32-битных элементов управления OCX. Если параметр равен единице (1), то возвращаются только 16-битные элементы управления OCX. Если параметр равен двум (2), то возвращаются только 32-битные элементы управления OCX. Если параметр равен трем (3), то возвращаются и 16-битные, и 32-битные элементы управления OCX. Если этот параметр пропущен или равен нулю, 16-битные программы возвращают 16-битные элементы управления OCX, а 32-битные программы - соответственно 32-битные элементы управления OCX.

Замечание: 16-ти битная поддержка не поддерживается данным релизом, должен использоваться исключительно 32-х битный режим.

С помощью OLEDIRECTORY получается список всех установленных OLE серверов или OCX объектов и заносится в очередь-список. Очередь-список должна иметь точно такую же структуру, что и очередь OleQ, объявленная в EQUATES.CLW:

OleQ QUEUE,TYPE

Name CSTRING(64) !Имя приложения - OLE сервера

CLSID CSTRING(64) !Уникальный идентификатор для операционной системы

ProgID CSTRING(64) !Регистрационное имя, как напр.: Excel.Sheet.5

END

Пример:

ResultQ QUEUE(OleQ). !Объявить ResultQ такую же как OleQ QUEUE в EQUATES.CLW

CODE

OLEDIRECTORY(ResultQ,0) !Получить список установленных OLE серверов

!поместить его в ResultQ

?OleControl{PROP:Create} = SelectOleServer(ResultQ)

!Процедура выбора пользователем OLE сервера:

SelectOleServer PROCEDURE(OleQ PickQ)

window WINDOW('Choose OLE Server'),AT(,,122,159),CENTER,SYSTEM,GRAY

LIST,AT(11,8,100,120),USE(?List),HVSCROLL, |

FORMAT('146L~Name~@s64@135L~CLSID~@s64@20L~ProgID~@s64@'),FROM(PickQ)

BUTTON('Select'),AT(42,134),USE(?Select)

END

CODE

OPEN(window)

SELECT(?List,1)

ACCEPT

CASE ACCEPTED()

OF ?Select

GET(PickQ,CHOICE(?List))

IF ERRORCODE() THEN STOP(ERROR()) END

POST(EVENT:CloseWindow)

END

END

RETURN(PickQ.ProgID)

 

Пользовательские объекты OLE (.OCX)

Введение

Пользовательские OLE объекты обычно имеют расширение .OCX. Поэтому обычно их называют объектами .OCX. Эти объекты подобны объектам .VBX в том смысле, что они самодостаточны и, будучи использованными в программе, выполняют определенную функцию. Однако, объекты .OCX не имеют ограничений присущих . VBX, поскольку построены по спецификациям Microsoft OLE 2, которые разработаны с учетом межязыковой совместимости (для языков, отличных от Visual Basic).

 

Свойства объектов .OCX

Название Описание

PROP:Create Атрибут CREATE (если атрибут отсутствует, то принимается равным пробелу). (ТОЛЬКО ПРИСВОЕНИЕ)

PROP:DesignMode Имеет ли объект контейнер для режима редактирования (имеется ли ограничительная рамка вокруг него)? (ТОЛЬКО ПРИСВОЕНИЕ)

PROP:Ctrl Это объект .OCX? (ТОЛЬКО ЧТЕНИЕ)

PROP:GrabHandles Высвечивает для объекта “зацепки” для изменения размеров. (ТОЛЬКО ПРИСВОЕНИЕ)

PROP:OLE Находится ли в контейнере объект OCX или OLE? (ТОЛЬКО ЧТЕНИЕ)

PROP:IsRadio Это OCX - кнопка радио (с зависимой фиксацией)? (ТОЛЬКО ЧТЕНИЕ)

PROP:LastEventName

Получить имя последнего события присланного объекту .OCX. (ТОЛЬКО ЧТЕНИЕ)

PROP:SaveAs Сохранить объект в файле - комплексном хранилище (OLE Compound Storage file). (ТОЛЬКО ПРИСВОЕНИЕ)

Синтаксис оператора для помещения объекта в файл – хранилище таков: ‘имя_файла\!компонент’ Например:

?controlx{PROP:SaveAs} = 'myfile\!objectx'

PROP:ReportException

Сообщение об исключительных ситуациях OLE (для отладки). (ТОЛЬКО ДЛЯ ЗАПИСИ)

PROP:DoVerb Выполняет OLE doverb команду из следующего набора команд. (Только ЗАПИСЬ)

DOVERB:Primary (0)

Вызывает первичные действия объекта. Что это за действия, определяется самим объектом, а не контейнером. Если для объекта поддерживается активизация “на месте”, то обычно первичное действие это и делает.

DOVERB:Show (-1)

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

DOVERB:Open (-2)

Сообщает объекту о том, что он должен открыться для просмотра и редактирования в отдельном от контейнера окне (это относится к объектам, поддерживающим активизацию “на месте”). Если объект активизацию “на месте” не поддерживает, то эта команда для него эквивалентна команде DOVERB:Show.

DOVERB:Hide (-3)

Сообщает объекту о том, что он должен убрать свой интерфейс пользователя. Эта команда применима только к объектам, активизируемым “на месте”.

DOVERB:UIActivate (-4)

Активизирует объект “на месте” наряду с его полным набором инструментальных средств, включая меню, панели инструментов и его имя в строке заголовка окна-контейнера.

DOVERB:InPlaceActivate (-5)

Активизирует объект “на месте” не включая набор инструментальных средств (меню и панели инструментов), которые необходимы пользователю для изменения внешнего вида и поведения объекта.

DOVERB:DiscardUndoState (-6)

Предписывает объекту уничтожить содержимое буфера изменений (UNDO), которые объект возможно поддерживает, не деактивируя при этом сам объект.

DOVERB:Properties (-7)

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

PROP:Language Номер языка, используемый для OLE Автоматизации или OCX Метода. Номер Американского Английского языка -0409-ый, номера же других языков могут быть вычислены с помощью данных, содержащихся в файле WINNT.H в MS Windows (ДЛЯ ЧТЕНИЯ/ДЛЯ ЗАПИСИ).

 

Оконные функции

Оконные функции являются стандартным средством программирования под Windows во многих языках программирования. Оконная функция представляет собой процедуру или функцию, которую вы (программист) пишете для обработки особых ситуаций, относительно которых операционная система полагает, что программисту возможно необходимо отреагировать на нее. Оконная функция вызывается операционной системой всякий раз, когда нужно обработать такую ситуацию. Поэтому, оконная функция не выглядит частью логической последовательности выполнения программы, а кажется обособленной и “магической”, не имеющей логической связи с другими процедурами программы.

Язык Clarion для Windows не требует от вас писать собственные оконные функции для выполнения наиболее общих действий, как это имеет место в других языках программирования, поскольку эти действия отслеживаются функциями библиотеки времени выполнения и циклом ACCEPT. Однако, поскольку объекты OCX обычно написаны на других языках, в которых требуется написание своих оконных функций, вам понадобится их написать для обработки событий и других программных аспектов связанных с работой объектов OCX, использованных в программе на языке Clarion. Поскольку методы класса, имеют своим неявным первым параметром имя класса, они не могут быть использованы в качестве функции вызова.

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

 

Оконная функция - обработчик событий OCX

Прототип этого события должен выглядеть так:

OcxEventFuncName PROCEDURE(*SHORT,SIGNED,LONG),LONG

От операционной системы передаются следующие параметры:

*SHORT Параметр-указатель, который передается другим библиотечным функциям объекта OCX: OCXGETPARAM, OCXGETPARAMCOUNT и OCXSETPARAM в качестве первого параметра.

SIGNED Номер поля, присвоенный объекту. Это тот самый номер, который представляется мнемонической меткой соответствия данного объекта.

LONG Номер события, относящегося к OCX. Мнемонические имена для некоторых заранее определенных номеров событий содержатся в файле OCXEVENT.CLW .

Возвращаемое значение типа LONG сообщает операционной системе необходима ли некая дальнейшая обработка. Возврат нуля (0) означает необходимость дополнительных действий (таких как изменение значения USE-переменной или выключение радио кнопки), тогда как возврат любого другого значения говорит о том, что обработка события завершена.

Обработка событий, генерируемых объектом .OCX, должна выполняться быстро, поскольку некоторые события критичны ко времени. Поэтому у пользователя не должно быть возможности помешать выполнению этой функции (т.е. нельзя использовать процедуру MESSAGE или оператор ASK или другие операторы касающиеся обработки данного окна). Программный код функции - обработчика события должен выполнять только необходимые действия и как можно быстрее (обычно это подразумевает исключение обработки событий, связанных с мышью).

 

Функция - контроллер редактирования свойств OCX

Прототип этой функции должен выглядеть следующим образом:

OcxPropEditFuncName PROCEDURE(SIGNED,STRING),LONG

От операционной системы передаются следующие параметры:

SIGNED Номер поля, присвоенный объекту. Это тот самый номер, который представляется мнемонической меткой соответствия данного объекта.

STRING Название свойства, значение которого должно изменяться.

Возвращаемое значение типа LONG сообщает операционной системе допустимо ли редактирование значения свойства. Если возвращаемое значение равно (0), то процедура не разрешает изменение значения свойства и пользователь не может этого делать. Если процедура возвращает любое другое значение, то это означает возможность изменения пользователем данного свойства.

 

Функция - обработчик изменения свойств OCX

Прототип этой функции должен выглядеть следующим образом:

OcxPropChangeProcName PROCEDURE(SIGNED,STRING)

ПРИЛОЖЕНИЕ А Библиотека DDE, OLE, и .OCX 721

От операционной системы передаются следующие параметры:

SIGNED Номер поля, присвоенный объекту. Это тот самый номер, который представляется мнемонической меткой соответствия данного объекта.

STRING Название изменяемого свойства.

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

Пример:

! В этой программе используется OCX – календарь который Microsoft поставляет вместе с Access95

! (в составе MS Office Professional для Windows).

PROGRAM

MAP

INCLUDE('OCX.CLW')

EventFunc PROCEDURE(*SHORT Reference,SIGNED OleControl,LONG CurrentEvent),LONG

PropChange PROCEDURE(SIGNED OleControl,STRING CurrentProp)

PropEdit PROCEDURE(SIGNED OleControl,STRING CurrentProp),LONG

END

INCLUDE('OCXEVENT.CLW') !Константы, используемые событиями OCX

INCLUDE('ERRORS.CLW') !Константы кодов ошибок

GlobalQue QUEUE !Очередь событий и смены отображения

F1 STRING(255)

END

SaveDate FILE,DRIVER('TopSpeed'),PRE(SAV),CREATE

Record RECORD

DateField STRING(10)

END

END

MainWin WINDOW('OCX Demo'),AT(,,350,200),STATUS(-1,-1),SYSTEM,GRAY,MAX,RESIZE

MENUBAR

MENU('&File')

ITEM('Save Date to File'),USE(?SaveObjectValue)

ITEM('Retrieve Saved Date'),USE(?GetObject)

ITEM('E&xit'),USE(?exit)

END

MENU('&Object')

ITEM('About Box'),USE(?AboutObject)

ITEM('Set Date to TODAY'),USE(?SetObjectValueToday)

ITEM('Set Date to 1st of Month'),USE(?SetObjectValueFirst)

END

ITEM('&Properties!'),USE(?ActiveObj)

END

LIST,AT(237,6,100,100),USE(?List1),HVSCROLL,FROM(GlobalQue)

OLE,AT(5,10,200,150),USE(?OcxObject)

END

END

CODE

OPEN(SaveDate)

IF ERRORCODE() !Проверить успешность открытия

IF ERRORCODE() = NoFileErr !если файл не существует

CREATE(SaveDate) !создать его

IF ERRORCODE() THEN HALT(,ERROR()) END

OPEN(SaveDate) !и открыть

IF ERRORCODE() THEN HALT(,ERROR()) END

ELSE

HALT(,ERROR())

END

END

OPEN(MainWin)

?OcxObject{PROP:Create} = 'MSACAL.MSACALCtrl.7' !Объект OCX MS Access 95 календарь

IF RECORDS(SaveDate) !Проверить существование сохраненной записи

SET(SaveDate) !и взять ее

NEXT(SaveDate)

IF ERRORCODE() THEN STOP(ERROR()).

POST(EVENT:Accepted,?GetObject)

ELSE

ADD(SaveDate) !иначе добавить запись

IF ERRORCODE() THEN STOP(ERROR()).

END

IF ?OcxObject{PROP:OLE} !Это объект OLE ?

GlobalQue = 'An Object is in the OLE control'

ADD(GlobalQue)

IF ?OcxObject{PROP:Ctrl} !НЕ является ли объект OCX

GlobalQue = 'It is an OCX Object'

ADD(GlobalQue)

END

END

DISPLAY

OCXREGISTEREVENTPROC(?OcxObject,EventFunc) !Зарегистрировать функцию - обработчик событий

OCXREGISTERPROPCHANGE(?OcxObject,PropChange) !Зарегистрировать функцию - контроллер

OCXREGISTERPROPEDIT(?OcxObject,PropEdit) !Зарегистрировать функцию - редактор свойств

?OcxObject{PROP:ReportException} = 1 !Включить возможность сообщений об ошибках в OCX

ACCEPT

CASE EVENT()

OF EVENT:Accepted

CASE FIELD()

OF ?Exit

POST(EVENT:CloseWindow)

OF ?AboutObject

?OcxObject{'AboutBox'} !вывести окно About

OF ?SetObjectValueToday

?OcxObject{'Value'} = FORMAT(TODAY(),@D1) !Установить сегодняшнюю дату

OF ?SetObjectValueFirst

?OcxObject{'Value'} = MONTH(TODAY()) & '/1/' & SUB(YEAR(TODAY()),3,2)

OF ?SaveObjectValue !Сохранить значение в файле

SAV:DateField = ?OcxObject{'Value'}

PUT(SaveDate)

IF ERRORCODE() THEN STOP(ERROR()).

OF ?GetObject !Взять значение из файла

?OcxObject{'Value'} = SAV:DateField

OF ?ActiveObj

?OcxObject{PROP:DoVerb} = 0 !Открыть диалог свойств объекта

END

END

END

!Функция - обработчик событий

EventFunc PROCEDURE(*SHORT Reference,SIGNED OleControl,LONG CurrentEvent)

Count LONG

Res CSTRING(200)

Parm CSTRING(30)

CODE

IF CurrentEvent <> OCXEVENT:MouseMove !Пропустить события - перемещения мыши

Res = 'Event: ' & OleControl{PROP:LastEventName}

LOOP Count = 1 TO OCXGETPARAMCOUNT(Reference) !Цикл по всем параметрам

Parm = OCXGETPARAM(Reference,Count) !беря имя каждого параметра

Res = CLIP(Res) & ' - ' & Parm !и сцепляя их вместе

END

GlobalQue = Res !Поместить их в буфер глобальной QUEUE

ADD(GlobalQue) !и добавить элемент

DISPLAY

END

RETURN(True)

!функция - контроллер изменения свойств

PropChange PROCEDURE(SIGNED OleControl,STRING CurrentProp)

CODE

GlobalQue = 'PropChange: ' & CurrentProp & ' = ' & OleControl{CurrentProp}

!занести в глобальную QUEUE

ADD(GlobalQue) !добавить элемент для отображения

IF ERRORCODE() THEN STOP(ERROR()).

!функция редактирования свойств

PropEdit PROCEDURE(SIGNED OleControl,STRING CurrentProp)

CODE

!Спросить резрешения редактировать свойство:

IF MESSAGE('Allow?','Change',ICON:Question,BUTTON:Yes+BUTTON:No,BUTTON:Yes,1) = BUTTON:Yes

RETURN(1) !разрешить изменение

ELSE

RETURN(0) !запретить изменение

END

 

Вызов методов OLE Объекта

Как OLE Автоматизация к приложению OLE Сервера, так и OCX/ActiveX объекты создают методы (процедуры), которые могут быть вызваны для выполнения объектом заданных действий. Поскольку OCX являются OLE преемниками элементов управления VBX, большинство поставщиков OCX снабжают их примерами исходного кода, демонстрирующие использование синтаксиса Visual Basic (VB), а те, что могут использоваться в программах, написанных на C++, обычно также имеют примеры исходного кода на C++.

Перевод этих примеров в соответствующий код Clarion обычно требует некоторого знания синтаксиса VB или C++. В этом разделе продемонстрированы наиболее общие типы вызовов методов в примерах на VB, а также то, как они переводятся на язык Clarion.

 

Обзор Синтаксиса Метода

Для вызова любого OLE/OCX метода используется синтаксис описания свойства языка Clarion. Вы определяете тот элемент управления, которому принадлежит метод или свойство, как метку соответствия поля элемента управления OLE, а затем записываете вызов метода в константу типа string внутри фигурных скобок ({}).

Пример исходного кода, поставляемый с большинством OLE элементов управления, использует применяемый в VB/C++ синтаксис “точечного свойства”, чтобы задать имя элемента управления, а также вызываемый метод или устанавливаемое свойство. Для примера представлен следующий код VB:

ControlName.AboutBox

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

 

?Ole{'AboutBox'}

Этот текст отображает диалог “О программе” (“About”) для элемента управления ControlName. Этот текст VB примера можно встретить также в следующем виде:

Form1.ControlName.AboutBox

В этом случае просто задается диалог, содержащий объект ControlName. Аналог этого текста на языке Clarion выглядит так же.

Ссылка на объект OLE/OCX в тексте Clarion программы всегда осуществляется по метке соответствия поля элемента управления OLE. При этом не имеет значения, какое имя этот элемент управления имеет в модуле, написанном на VB, поскольку зарегистрированное имя объекта определено в атрибуте CREATE или OPEN элемента управления OLE. Таким образом, исполняемая библиотека Clarion для однозначной идентификации объекта, на который осуществляется ссылка, должна знать только метку соответствия используемого при этом поля.

Перевод такой языковой конструкции VB, как “With”

Многие примеры текста OLE/OCX, чтобы связать многократные присвоения свойств и/или вызовы метода с одним отдельным объектом, используют такую структуру VB, как With ... End With. В этом случае, объект определяется в выражении With, а все присвоения свойств и вызовы методов в пределах этой структуры начинаются с точечного разделителя, а затем уже следует имя устанавливаемого свойства или вызываемого метода. Например, следующий код VB:

With Form1.VtChart1

'displays a 3d chart with 8 columns and 8 rows data

.chartType = VtChChartType3dBar

.columnCount = 8

.rowCount = 8

For column = 1 To 8

For row = 1 To 8

.column = column

.row = row

.Data = row * 10

Next row

Next column

'use the chart as the backdrop of the legend

.ShowLegend = True

End With

переводится на язык Clarion следующим образом:

!отображает трехмерную таблицу с 8 столбцами и 8 строками данных

?Ole{'chartType'} = VtChChartType3dBar

?Ole{'columnCount'} = 8

?Ole{'rowCount'} = 8

LOOP column# = 1 TO 8

LOOP row# = 1 TO 8

?Ole{'column'} = column#

?Ole{'row'} = row#

?Ole{'Data'} = row# * 10

END

END

!использует диаграмму в качестве фона для надписи

?Ole{'ShowLegend'} = True

Поскольку в языке Clarion отсутствует прямой эквивалент такой структуре VB, как With ... End With, то при каждом присвоении свойства или вызове метода необходимо только явным образом назвать метку соответствия поля элемента управления OLE. Одиночная кавычка (‘), присутствующая в исходном коде VB, означает начало строки комментария.

VB разрешает использование вложенных структур With ... End With, так, чтобы найти имя объекта, вам возможно придется затем “пропутешествовать” в обратном направлении. Приведенный ниже пример демонстрирует использование вложенных With структур VB:

With MyObject

.Height = 100 ' Эквивалентно MyObject.Height = 100.

.Caption = "Hello World" ' Эквивалентно MyObject.Caption = "Hello World".

With .Font

.Color = Red ' Эквивалентно MyObject.Font.Color = Red.

.Bold = True ' Эквивалентно MyObject.Font.Bold = True.

End With

End With

что переводится на язык Clarion следующим образом:

?Ole{'Height'} = 100 ! MyObject.Height = 100

?Ole{'Caption'} = 'Hello World' ! MyObject.Caption = "Hello World"

?Ole{'Font.Color'} = Red ! MyObject.Font.Color = Red

?Ole{'Font.Bold'} = True ! MyObject.Font.Bold = True

 

Передача параметров OLE/OCX Методам

Также, как и в Clarion, в VB существует всего два способа передачи параметров: по значению и по адресу (по ссылке). Такие ключевые слова VB, как ByVal и ByRef, присутствующие в коде VB, определяют эти два метода передачи. Термины эти в VB означают то же самое, что и в Clarion - при передаче параметра по значению передается копия содержимого переменной, при передаче параметра по ссылке (в VB этот способ используется по умолчанию) передается непосредственно адрес переменной, так что принимающий метод может изменять ее содержимое.

Использование Круглых скобок

В синтаксисе VB круглые скобки, в которые заключается список передаваемых параметров, могут либо использоваться, либо нет. Если метод VB не возвращает значение, или вы не собираетесь использовать возвращаемое значение, параметры в VB могут передаваться и без круглых скобок, как показано ниже:

VtChart1.InsertColumns 6,3

Если же возвращаемое значение Вам необходимо, то параметры в VB передаются заключенными внутрь круглых скобок, как показано ниже:

ReturnValue = VtChart1.InsertColumns (6,3)

Синтаксис Clarion, однако, всегда требует, чтобы передаваемые параметры были заключены в круглые скобки. Поэтому оба вышеприведенных примера переводятся следующим образом:

?Ole{'InsertColumns(6,3)'}

ReturnValue = ?Ole{'InsertColumns(6,3)'}

Передача Параметров По Значению

В этом случае параметры передаются объектам OLE/OCX в виде строк (кроме Булевых параметров). Поскольку OLE/OCX объекты предполагают приведение поступающих на их вход данных к правильным типам данных путем использования механизма VARIANT (подобно преобразованию типов данных в Clarion), это позволяет достичь большей совместимости при минимальных трудозатратах. Любая строка, требующая знака двойной кавычки (“) должна включать две их (“ “).

Параметры по значению могут быть переданы в методы объекта OLE/OCX как константы или как переменные. Приведенные выше примеры передают параметры как константы. В этих константах, если только они не заключены в двойные кавычки, не могут присутствовать пробелы (например, “Значение с пробелами”).

Существует два способа передачи переменной по значению из Clarion в OLE/OCX метод: связывание в константу типа string, которая используется при вызове метода, или же использование BIND на имя переменной и размещение этого имени переменной непосредственно в константе типа string, которая используется при вызове метода. Например, можно переписать используемую в вышеприведенном примере передачу значений переменных в состыкованной строке:

ColumnNumber = 6

NumberOfColumns = 3

?Ole{'InsertColumns(' & ColumnNumber & ',' & NumberOfColumns & ')'}

!Same as ?Ole{'InsertColumns(6,3)'}

ОПИСАНИЕ ЯЗЫКА

Второй способ передачи переменных по значению - это связать их (BIND) и перечислить их имена в константе типа string таким образом, как показано ниже:

BIND('ColumnNumber',ColumnNumber)

BIND('NumberOfColumns',NumberOfColumns)

?Ole{'InsertColumns(ColumnNumber,NumberOfColumns)'}

!Same as ?Ole{'InsertColumns(6,3)'}

Этот метод делает текст программы более удобочитаемым, однако перед передачей значений все передаваемые переменные должны быть связаны (BIND).

Передача Параметров По Адресу (Ссылке)

Параметры, передаваемые по адресу, могут быть переданы методам объекта OLE/OCX только путем задания имен переменных в строке константы. Поэтому необходимо использовать оператор BIND на имена этих переменных и поместить эти имена непосредственно в константе типа string, которая передается методу с предшествующим имени переменной знаком амперсанд, говорящим о том, что переменная передается по ссылке. Например, можно следующим образом переписать вышеприведенный пример для передачи значений переменных по адресу:

ColumnNumber = 6

NumberOfColumns = 3

BIND('ColumnNumber',ColumnNumber)

BIND('NumberOfColumns',NumberOfColumns)

?Ole{'InsertColumns(&ColumnNumber,&NumberOfColumns)'}

Параметры, передаваемые по адресу, передаются объектам OLE/OCX как тип данных связанной переменной (кроме Булевых параметров). Переменные фактически передаются в виде временных строковых переменных, которые автоматически распознаются библиотекой Clarion. Таким образом, любые изменения, внесенные OLE/OCX методом в значение переданной переменной, отображаются и в обратном направлении, на оригинал переданной переменной.

Булевы Параметры

Булевы параметры (1/0 или Истина/Ложь) могут передаваться как по значению, так и по адресу. При передаче по значению Вы можете применять либо передачу константы (1 или 0, или же такие слова, как TRUE или FALSE), как показано в следующем примере:

Ole{'ODBCConnect(&DataSource,1,&RetVal)'}

?Ole{'ODBCConnect(&DataSource,TRUE,&RetVal)'}

либо передачу имени переменной (после его предварительного связывания (BIND)) внутри вызова “bool()”, как это показано ниже:

BoolParm = 1

BIND('BoolParm',BoolParm)

?Ole{'ODBCConnect(&DataSource,bool(BoolParm),&RetVal)'}

Bool() представляет собой конструкцию, которая сообщает синтаксическому анализатору, что это значение передается как Булевское. Конструкция Bool() может быть использована только внутри строки вызова OLE/OCX метода.

Для передачи по ссылке необходимо внутри конструкции bool() просто пристыковать спереди к имени переменной символ амперсанд, как это показано ниже:

BIND('BoolParm',BoolParm)

?Ole{'ODBCConnect(&DataSource,bool(&BoolParm),&RetVal)'}

Поименованные Параметры

В VB имеется два способа передачи параметров: позиционно или в качестве “поименованного аргумента”. Позиционные параметры подразумевают, что при вызове метода Вы должны либо передать параметр, либо оставить пустыми позиции, соответствующие пропущенным параметрам в разделенном запятыми списке. А так как некоторым методам может передаваться большое количество параметров, то это может привести к возникновению очень длинной строки, состоящей из одних только запятых, в то время как передать методу Вам нужно всего лишь один или два параметра. В VB эта проблема решена путем разрешения программистам “называть” параметры, что позволяет при вызове метода передать только те немногие параметры, которые выбраны безотносительно к их положению или порядку следования в списке параметров.

Поименованные параметры в VB универсальным образом не поддерживаются, так что поставщик OLE/OCX должен предоставить специально предназначенные для их поддержки методы. В файле помощи на OLE/OCX должно быть объявлено, поддерживаются ли поименованные параметры, или же с этой целью Вы можете использовать Окно Просмотра Объектов VB.

Для присвоения значения имени параметра, синтаксисом VB для поименованных параметров предусмотрено использование сочетания символов := . Например, для следующего выражения VB:

OpenIt(Name:=, [Exclusive]:=, [ReadOnly]:=, [Connect]:=)

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

Db = ?Ole{'OpenIt("MyFile",False,False,"ODBC;UID=Fred")'}

что переводится на язык Clarion (с использованием позиционных параметров) как:.730 CLARION ОПИСАНИЕ ЯЗЫКА

Db = ?Ole{'OpenIt("MyFile",False,False,"ODBC;UID=Fred")'}

Можно вызвать тот же самый метод на VB, используя поименованные параметры, как это показано ниже (подчеркнутый символ представляет собой в VB символ продолжения строки):

Db = OpenIt(Name:="MyFile",Exclusive:=False,ReadOnly:=False, _ Connect:="ODBC;UID=Fred")

что переводится на язык Clarion как:

 

Db = ?Ole{'OpenIt(Name="MyFile",Exclusive=False,ReadOnly=False, ' & | 'Connect="ODBC;UID=Fred")'}

или же Вы можете передать параметры в VB в другом порядке:

Db = OpenIt(Connect:="ODBC;UID=Fred", _

Name:="MyFile", _

ReadOnly:=False, _

Exclusive:=False")

что переводится на язык Clarion как:

Db = ?Ole{'OpenIt(Connect="ODBC;UID=Fred",Name="MyFile",' & |

'Exclusive=False,ReadOnly=False')'}

 

Библиотечные процедуры OCX

OCXREGISTERPROPEDIT (установить контроллер свойств)

OCXREGISTERPROPEDIT( объект , процедура )

OCXREGISTERPROPEDIT

Установить функцию - контроллер редактирования свойств.

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

процедура Имя функции редактирования свойств объекта.

Процедура OCXREGISTERPROPEDIT устанавливает процедуру – контроллер редактирования свойств объекта. Она управляет редактированием свойств, запрещая или разрешая редактирование.

Пример:

OCXREGISTERPROPEDIT(?OleControl,CallbackFunc)

Смотри также: Оконные функции

 

OCXREGISTERPROPCHANGE (установить функцию - редактор)

OCXREGISTERPROPCHANGE( объект , процедура )

OCXREGISTERPROPCHANGE

Устанавливает процедуру - редактор свойств объекта.

объект Целочисленное выражение, содержащее номер поля или мнемоническая метка соответствия OLE-объекта к которому относится действие.

процедура Имя процедуры изменения свойств объекта.

Процедура OCXREGISTERPROPCHANGE устанавливает процедуру – редактор свойств объекта. Эта процедура вызывается, когда происходит изменение свойств объекта.

Пример:

OCXREGISTERPROPCHANGE(?OleControl,CallbackProc)

Смотри также: Оконные функции

 

OCXREGISTEREVENTPROC (установить процедуру обработки событий)

OCXREGISTEREVENTPROC( объект , процедура )

OCXREGISTEREVENTPROC

Устанавливает для объекта OCX процедуру обработки событий.

объект Целочисленное выражение, содержащее номер поля или мнемоническая метка соответствия OLE-объекта к которому относится действие.

процедура Имя процедуры - обработчика событий для объекта.

Процедура OCXREGISTEREVENTPROC устанавливает для объекта OCX процедуру обработки событий. К этой процедуре происходит обращение при передаче операционной системой любого события относящегося к данному объекту.

Смотри также: Оконные функции

 

OCXUNREGISTERPROPEDIT (отменить функцию - контроллер свойств)

OCXUNREGISTERPROPEDIT( объект )

OCXUNREGISTERPROPEDIT

Деинсталлирует процедуру - контроллер свойств.

объект Целочисленное выражение, содержащее номер поля или мнемоническая метка соответствия OLE-объекта к которому относится действие.

Процедура OCXUNREGISTERPROPEDIT деинсталлирует процедуру – контроллер свойств для объекта.

Пример:

OCXUNREGISTERPROPEDIT(?OleControl)

Смотри также: Оконные функции

 

OCXUNREGISTERPROPCHANGE (отменить редактор свойств)

OCXUNREGISTERPROPCHANGE( объект )

OCXUNREGISTERPROPCHANGE

Деинсталлирует процедуру - редактор свойств.

объект Целочисленное выражение, содержащее номер поля или мнемоническая метка соответствия OLE-объекта к которому относится действие.

Процедура OCXUNREGISTERPROPCHANGE отменяет процедуру - редактор свойств объекта.

Пример:

OCXUNREGISTERPROPCHANGE(?OleControl)

Смотри также: Оконные функции

 

OCXUNREGISTEREVENTPROC (отменить процедуру обработки событий)

OCXUNREGISTEREVENTPROC( объект )

OCXUNREGISTEREVENTPROC

Деинсталлирует процедуру - обработчик OCX-события.

объект Целочисленное выражение, содержащее номер поля или мнемоническая метка соответствия OLE-объекта к которому относится действие.

OCXUNREGISTEREVENTPROC отменяет процедуру обработки OCX-событий для объекта.

Пример:

OCXUNREGISTEREVENTPROC(?OleControl)

Смотри также: Оконные функции

 

OCXGETPARAMCOUNT (получить число параметров для события)

OCXGETPARAMCOUNT( указатель )

OCXGETPARAMCOUNT

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

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

Процедура OCXGETPARAMCOUNT возвращает число параметров, связанных с текущим событием для объекта OCX. Использование этой процедуры допустимо, только когда установлена функция - обработчик событий для объекта OCX.

Возвращаемый тип данных: USHORT

Пример:

OEvent PROCEDURE(Reference,OleControl,CurrentEvent) !Процедура обработки событий

Count LONG

Res CSTRING(200)

Parm CSTRING(30)

CODE

IF CurrentEvent <> OCXEVENT:MouseMove !Отключить события по перемещению мыши

Res = 'Control ' & OleControl & ' Event ' & OleControl{PROP:LastEventName} & ':'

LOOP Count = 1 TO OCXGETPARAMCOUNT(Reference) !Цикл по всем параметрам

Parm = OCXGETPARAM(Reference,Count) !получим имя каждого параметра

Res = CLIP(Res) & ' ' & Parm !и соединим их

END

GlobalQue = Res !Поместим в глобальную очередь

ADD(GlobalQue) !добавить элемент для последнего

! отображения

END !всех событий OCX и их

RETURN(True) !параметров

Смотри также: Оконные функции, OCXGETPARAM

 

OCXGETPARAM (получить строку параметра)

OCXGETPARAM( указатель ,номер )

OCXGETPARAM Возвращает значение параметра, связанного с текущим событием, относящимся к объекту OCX.

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

номер Номер выбираемого параметра.

Процедура OCXGETPARAM возвращает значение параметра с указанным номером для текущего события, связанного с объектом OCX. Использование этой процедуры допустимо, только когда установлена функция - обработчик событий для объекта OCX.

Возвращаемый тип данных: STRING

Пример:

OEvent PROCEDURE(Reference,OleControl,CurrentEvent) !Процедура обработки событий

Count LONG

Res CSTRING(200)

Parm CSTRING(30)

CODE

IF CurrentEvent <> OCXEVENT:MouseMove !Отключить события по перемещению мыши

Res = 'Control ' & OleControl & ' Event ' & OleControl{PROP:LastEventName} & ':'

LOOP Count = 1 TO OCXGETPARAMCOUNT(Reference) !Цикл по всем параметрам

Parm = OCXGETPARAM(Reference,Count) !получение имени каждого параметра

Res = CLIP(Res) & ' ' & Parm !и соединение их

END

GlobalQue = Res !Положить в буфер глобальной очереди

ADD(GlobalQue) !и добавить элемент в очередь

END !всех событий OCX и их параметров

RETURN(True)

Смотри также: Оконные функции, OCXSETPARAM, OCXGETPARAMCOUNT

 

OCXSETPARAM (установить строку параметра)

OCXSETPARAM( указатель ,номер ,значение )

OCXSETPARAM Устанавливает значение параметра, относящегося к текущему событию, связанному с OCX.

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

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

значение Строковая константа или переменная, содержащая устанавливаемое значение.

OCXSETPARAM присваивает для текущего события значение параметру, указанному номером . Это допустимо только для параметров, которые передаются “по адресу” (относительно устанавливаемых параметров смотрите руководство по конкретному объекту OCX). Если модификация параметра недопустима, то она игнорируется. Использование этой процедуры допустимо, только когда установлена функция – обработчик событий для объекта OCX.

Пример:

OEvent PROCEDURE(Reference,OleControl,CurrentEvent) !Процедура обработки событий

Count LONG

Res CSTRING(200)

Parm CSTRING(30)

CODE

IF CurrentEvent <> OCXEVENT:MouseMove !Отключить события по перемещению мыши

Res = 'Control ' & OleControl & ' Event ' & OleControl{PROP:LastEventName} & ':'

LOOP Count = 1 TO OCXGETPARAMCOUNT(Reference) !Цикл по всем параметрам

Parm = OCXGETPARAM(Reference,Count) !взять имя каждого параметра

Res = CLIP(Res) & ' ' & Parm !и соединить их вместе

OCXSETPARAM(Reference,1,'1') !Изменить значение параметра

END

GlobalQue = Res !Занести строку в очередь

ADD(GlobalQue) !и добавить ее в очередь

END !всех событий OCX и их

RETURN(True) !параметров

Смотри также: Оконные функции, OCXGETPARAM

 

OCXLOADIMAGE (получить графический объект)

OCXLOADIMAGE( имя )

OCXLOADIMAGE Возвращает графический объект.

имя Строковое выражение, содержащее имя файла или ресурса, который следует загрузить.

Процедура OCXLOADIMAGE возвращает графический объект. Этот объект можно присвоить любому экранному объекту, который использует графический объект (например, “VB imagelist”).

Возвращаемый тип данных: STRING

Пример:

!добавить изображение в объект ImageList:

?imagelist{'ListImages.Add(,,' & OCXLOADIMAGE('CLOCK.BMP') & ')'}

к оглавлению

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

НОВОСТИ ФОРУМА

Форум Рыцари теории эфира


Рыцари теории эфира
 10.11.2021 - 12:37: ПЕРСОНАЛИИ - Personalias -> WHO IS WHO - КТО ЕСТЬ КТО - Карим_Хайдаров.
10.11.2021 - 12:36: СОВЕСТЬ - Conscience -> РАСЧЕЛОВЕЧИВАНИЕ ЧЕЛОВЕКА. КОМУ ЭТО НАДО? - Карим_Хайдаров.
10.11.2021 - 12:36: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от д.м.н. Александра Алексеевича Редько - Карим_Хайдаров.
10.11.2021 - 12:35: ЭКОЛОГИЯ - Ecology -> Биологическая безопасность населения - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> Проблема государственного терроризма - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> ПРАВОСУДИЯ.НЕТ - Карим_Хайдаров.
10.11.2021 - 12:34: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вадима Глогера, США - Карим_Хайдаров.
10.11.2021 - 09:18: НОВЫЕ ТЕХНОЛОГИИ - New Technologies -> Волновая генетика Петра Гаряева, 5G-контроль и управление - Карим_Хайдаров.
10.11.2021 - 09:18: ЭКОЛОГИЯ - Ecology -> ЭКОЛОГИЯ ДЛЯ ВСЕХ - Карим_Хайдаров.
10.11.2021 - 09:16: ЭКОЛОГИЯ - Ecology -> ПРОБЛЕМЫ МЕДИЦИНЫ - Карим_Хайдаров.
10.11.2021 - 09:15: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Екатерины Коваленко - Карим_Хайдаров.
10.11.2021 - 09:13: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вильгельма Варкентина - Карим_Хайдаров.
Bourabai Research - Технологии XXI века Bourabai Research Institution