Difference between revisions of "Объект OLE"

From SunFlurry wiki
Jump to: navigation, search
m (1 revision imported)
Line 20: Line 20:
 
* Объекты, расположенные на формах. В этом режиме, объект добавляется на форму в момент ее создания в Студии, для таких объектов могут быть заданы визуальные события ''COM''.
 
* Объекты, расположенные на формах. В этом режиме, объект добавляется на форму в момент ее создания в Студии, для таких объектов могут быть заданы визуальные события ''COM''.
 
* Объекты, внедренные в электронные таблицы. Такие объекты также можно добавлять программно или при копировании частей таблицы с помощью функций типа [[Table.CopyByX|CopyByX]].
 
* Объекты, внедренные в электронные таблицы. Такие объекты также можно добавлять программно или при копировании частей таблицы с помощью функций типа [[Table.CopyByX|CopyByX]].
 +
 +
Некоторые аргументы OLE функций могут представлять собой массивы. В этом случае, программа должна передать список одинаковых по типу элементов (OLE не поддерживает списки с разными типами данных). Если OLE функция возвращает массив, он автоматически будет превращен в список.
 +
 +
Система обычно работает с простыми типами, максимальными по размеру и совместимости. Однако, не все OLE-объекты принимают такие аргументы, и при этом могут не указывать необходимый им тип в свойствах библиотеки. К примеру, OLE функция во втором аргументе ожидает массив из чисел без знака длиной 2 байта (одно слово), однако, тип этого аргумента указан как ''VT_VARIANT'' (т.е. произвольный тип). Если программа передаст функции список значений с числами, система не будет знать, какой тип чисел задавать в массиве и может создать массив из 32-битных целых чисел, который не будет принят вызываемой функцией. Чтобы обойти эту проблему, необходимо использовать вспомогательную функцию [[OLEVariant]], позволяющую из [[Объекты|объекта]] системы создать особый OLE ориентированный объект с твердо заданным типом данных. При этом тип данных указывается, как константа (см. [[Константы#Константы типов данных OLE|константы типов данных OLE]].
 +
 +
Как альтернативный вариант, при передаче числовых массивов в аргументе функции, тип данных в массиве может быть указан, как наименование первого элемента массива. При этом принимаются следующие типы данных:
 +
* '''I1''' -- числа -128..+127 (байт со знаком)
 +
* '''UI1''' -- числа 0..255 (байт без знака)
 +
* '''I2''' -- числа -32768..+32767 (слово со знаком)
 +
* '''UI2''' -- числа 0..65535 (слово без знака)
 +
* '''I4''' -- числа -2147483648..+2147483647 (32-битное число со знаком)
 +
* '''UI4''' -- числа 0..4294967295 (32-битное число без знака)
 +
* '''I8''' -- 64-битные числа со знаком
 +
* '''UI8''' -- 64-битные числа без знака
 +
* '''N''' -- числа со знаком 32 или 64 бита в зависимости от разрядности исполняемого процесса
 +
* '''UN''' -- числа без знака 32 или 64 бита в зависимости от разрядности исполняемого процесса
 +
 +
Ниже дан пример использования OLEVariant для задания типа массива данных (функция OLEVariant может использоваться не только для задания типов массивов, но и для обычных объектов):
 +
<pre>
 +
//OLE функция Foo требует во втором аргументе массив 32-битных чисел без знака
 +
//Создаем массив
 +
aList:=List.Create(1,2,3,4,5,6,7,8,9,10);
 +
 +
aOle.Foo("Параметр 1",OLEVariant(aList,_OLE_VT_ARRAY+_OLE_VT_UI4));
 +
</pre>
 +
 +
Тот же самый пример, однако, в массиве используется прямое указание на тип данных:
 +
<pre>
 +
//OLE функция Foo требует во втором аргументе массив 32-битных чисел без знака
 +
//Создаем массив
 +
aList:=List.Create(1,2,3,4,5,6,7,8,9,10);
 +
//Устанавливаем признак: 32-битные числа без знака
 +
aList.SetName(1,"UI4");
 +
 +
aOle.Foo("Параметр 1",aList);
 +
</pre>
 +
  
 
== Атрибуты и функции==
 
== Атрибуты и функции==
Line 38: Line 75:
 
|visual=0
 
|visual=0
 
|description=Функция создает новый объект OLE (COM) по строке идентификатора. Объект может быть доступен в любом потоке, не только в том, который создал объект. Вызовы к таким объектам осуществляются несколько медленнее.
 
|description=Функция создает новый объект OLE (COM) по строке идентификатора. Объект может быть доступен в любом потоке, не только в том, который создал объект. Вызовы к таким объектам осуществляются несколько медленнее.
 +
}}
 +
{{function entry
 +
|name=[[OLEVariant]]
 +
|form='''OLEVariant'''(''<Объект>'',''<Тип данных OLE (INT)>''):''<Объект, используемый при вызовах OLE функций (OLEVARIANT)>''
 +
|type=1
 +
|status=2
 +
|visual=0
 +
|description=Функция создает из объекта системы вспомогательный объект OLEVARIANT с заданным типом данных OLE. Функция может быть вызвана для любого объекта, однако, только следующие объекты имеет смысл превращать в объекты OLE: числа, строки, даты, другие OLE-объекты, списки.
 
}}
 
}}
 
{{function entry
 
{{function entry

Revision as of 13:17, 4 March 2021

  OLE (Объект OLE)
Статус разработки: Реализован
Создание объекта: Create

Объект OLE (Object Linking and Embedding) позволяет получить доступ к функциям операционной системы и других программ из программных модулей клиента, если эти программы поддерживают интерфейс COM (Component Object Model). Microsoft создали достаточно много терминов для OLE-объектов: OLE, COM, OCX, ActiveX, все они в каком-то роде означают один и тот же способ работы с внешними объектами. Самый большой минус такого способа работы заключается в том, что OLE-сервер не может контролировать время исполнения методов объектов. Это может привести к тому, что если в методе OLE-объекта есть ошибка, и метод зависнет или выдаст на экран модальное сообщение, OLE вызов никогда не вернет управление программе. Для визуального клиента это имеет меньшее значение, так как пользователь сможет перезапустить программу, однако, для консольных клиентов это весьма опасно, поэтому для консольных клиентов рекомендуется использовать функции сторожевого пса.

На данный момент система работает с COM интерфейсом в режиме STA (Single-Threaded Apartment). Это означает, что объект, созданный в одном потоке, не может быть доступен в других потоках. Windows позволяет вызов методов из других потоков, но это происходит с помощью стандартной очереди сообщений Windows, что идеально подходит для визуальный объектов, созданных в основном потоке системы, однако, неудобно для объектов, созданных в рабочих потоках, так как в рабочих потоках отсутствует обработчик очереди сообщений. Это ограничение можно обойти, создав OLE-объект в особом режиме. Ниже даны возможные режимы использования OLE-объектов в программных модулях или обработчиках событий:

  • Режим STA (однопоточный режим). OLE-объекты, созданные таким образом, делятся на две категории:
    • Визуальные OLE-объекты, находящиеся на формах или в электронных таблицах. Такие объекты позволяют вызовы из разных потоков, так как визуальный поток обрабатывает сообщения из очереди сообщений. Вызовы из других потоков для этой категории объектов будут обладать такими же минусами, как и вызовы к объектам, созданным в режиме "центрального потока" (см. ниже).
    • OLE-объекты, созданные программно. Методы таких объектов не могут быть вызваны из других потоков (только из потока, где эти объекты были созданы). Зачастую такие объекты создаются, чтобы выполнить определенную работу, и после этого удаляются, поэтому, это не вызывает проблем в работе.
  • Режим исполнения центрального потока. OLE-объекты создаются с помощью функции CreateThreadedOLE в специально выделенном для этого потоке, который в дальнейшем обслуживает все обращения из других потоков. Обращения происходят не с помощью использования стандартной очереди сообщений Windows, а с помощью более быстрой межпоточной синхронизации. Однако, так как все OLE-объекты, созданные в системе таким образом, обслуживает только один поток, может получиться ситуация (особенно с консольными серверами), когда выполнение вызова к объекту будет задержано, пока выполняется вызов из другого потока. В визуальных клиентах, где количество одновременно работающих потоков мало, это не будет являться реальным ограничением.
  • Режим исполнения индивидуального потока. Данный режим, который пока не создан, и необходимость в котором рассматривается, будет позволять для каждого созданного OLE-объекта иметь свой собственный поток исполнения методов. Минусами такого режима, может стать большое потребление ресурсов системы, однако, в случаях, когда объектов в системе немного, а вызовы к ним занимают продолжительное время, этот режим мог бы быть полезен.

В системе OLE-объекты могут присутствовать:

  • Объекты, созданные программно CreateOLE
  • Объекты, расположенные на формах. В этом режиме, объект добавляется на форму в момент ее создания в Студии, для таких объектов могут быть заданы визуальные события COM.
  • Объекты, внедренные в электронные таблицы. Такие объекты также можно добавлять программно или при копировании частей таблицы с помощью функций типа CopyByX.

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

Система обычно работает с простыми типами, максимальными по размеру и совместимости. Однако, не все OLE-объекты принимают такие аргументы, и при этом могут не указывать необходимый им тип в свойствах библиотеки. К примеру, OLE функция во втором аргументе ожидает массив из чисел без знака длиной 2 байта (одно слово), однако, тип этого аргумента указан как VT_VARIANT (т.е. произвольный тип). Если программа передаст функции список значений с числами, система не будет знать, какой тип чисел задавать в массиве и может создать массив из 32-битных целых чисел, который не будет принят вызываемой функцией. Чтобы обойти эту проблему, необходимо использовать вспомогательную функцию OLEVariant, позволяющую из объекта системы создать особый OLE ориентированный объект с твердо заданным типом данных. При этом тип данных указывается, как константа (см. константы типов данных OLE.

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

  • I1 -- числа -128..+127 (байт со знаком)
  • UI1 -- числа 0..255 (байт без знака)
  • I2 -- числа -32768..+32767 (слово со знаком)
  • UI2 -- числа 0..65535 (слово без знака)
  • I4 -- числа -2147483648..+2147483647 (32-битное число со знаком)
  • UI4 -- числа 0..4294967295 (32-битное число без знака)
  • I8 -- 64-битные числа со знаком
  • UI8 -- 64-битные числа без знака
  • N -- числа со знаком 32 или 64 бита в зависимости от разрядности исполняемого процесса
  • UN -- числа без знака 32 или 64 бита в зависимости от разрядности исполняемого процесса

Ниже дан пример использования OLEVariant для задания типа массива данных (функция OLEVariant может использоваться не только для задания типов массивов, но и для обычных объектов):

//OLE функция Foo требует во втором аргументе массив 32-битных чисел без знака
//Создаем массив
aList:=List.Create(1,2,3,4,5,6,7,8,9,10);

aOle.Foo("Параметр 1",OLEVariant(aList,_OLE_VT_ARRAY+_OLE_VT_UI4));

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

//OLE функция Foo требует во втором аргументе массив 32-битных чисел без знака
//Создаем массив
aList:=List.Create(1,2,3,4,5,6,7,8,9,10);
//Устанавливаем признак: 32-битные числа без знака
aList.SetName(1,"UI4");

aOle.Foo("Параметр 1",aList);


Атрибуты и функции

Идентификатор Статус Тип Визуальная Параметры Описание
CreateOLE Реализована Функция CreateOLE(<Идентификатор объекта OLE (STRING)>):<Новый объект OLE (OLE)> Функция создает новый объект OLE (COM) по строке идентификатора
CreateThreadedOLE Реализована Функция CreateThreadedOLE(<Идентификатор объекта OLE (STRING)>):<Новый объект OLE (OLE)> Функция создает новый объект OLE (COM) по строке идентификатора. Объект может быть доступен в любом потоке, не только в том, который создал объект. Вызовы к таким объектам осуществляются несколько медленнее.
OLEVariant Реализована Функция OLEVariant(<Объект>,<Тип данных OLE (INT)>):<Объект, используемый при вызовах OLE функций (OLEVARIANT)> Функция создает из объекта системы вспомогательный объект OLEVARIANT с заданным типом данных OLE. Функция может быть вызвана для любого объекта, однако, только следующие объекты имеет смысл превращать в объекты OLE: числа, строки, даты, другие OLE-объекты, списки.
SetTimeout Планируется Функция OLE.SetTimeout(<Время ожидания исполнения команд в мс. (INT)>):<Предыдущее время ожидания исполнения команд в мс. (INT)> Функция задает или получает для объекта максимальное время ожидания исполнения команд. По умолчанию при создании объекта, это время равно 0 (не ограничено). При истечении времени ожидания система произведет отсоединение от текущего OLE-объекта и выполнявшаяся функция вызовет исключение.
SetEventHandler Планируется Функция OLE.SetEventHandler(<Имя события OLE объекта (STRING)>,<Имя функции-обработчика события (STRING)>,<Тип вызова события (INT)>=0) Функция сопоставляет локальную или глобальную функцию с событием OLE-объекта. Исполнение функции может происходить в трех режимах, в зависимости от аргумента тип вызова события: 0 (по умолчанию) -- функция будет вызвана, как прерывающее событие в контексте текущей формы (работает только для визуальных форм), 1 -- для вызова функции будет создан отдельный поток (как это происходит при вызове функции ExecuteFunctionInSeparateThread) (работает для любого контекста, но создание нового потока для часто исполняемых событий может замедлить работу системы), 2 -- событие будет помещено в очередь ожидания и будет исполнено в момент вызова функции OLESleep (работает для любого контекста).
OLESleep Планируется Функция OLE.OLESleep(<Время ожидания появления события (INT)>) Функция ожидает появления OLE события (только для событий, сопоставленных в режиме 2, см. SetEventHandler). Событие исполняется, если оно ожидает в очереди на начало вызова функции или происходит в течение времени ожидания функции. Событие будет вызвано в текущем потоке и будет иметь доступ ко всем его переменным. При задании аргумента равным нулю, событие будет исполнено, только если оно ожидает в очереди на момент вызова функции, ожидания события не будет.