Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Dispid 1;





property I tern[Index: Integer]: OleVariant dispid 2;

procedure Remove(Index: Integer); dispid 3;

procedure Clear; dispid 4;

function Add(Item: OleVariant): Integer; dispid 5;

function _NewEnum: lUnknown; dispid -4;

End;

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

Следующих типов: Byte, Currency, Real, Double, Longint, Integer, Single, Smallint, AnsiString, WideString, TDateTime, Variant, OleVariant, WordBool или любой интерфейсный тип. За исключением директивы default, которую можно указать для свойства-массива, никакие другие директивы доступа в объявлении методов и свойств не допускаются.

Для доступа к объектам Автоматизации используются переменные типа вариант (см. следующую лекцию). Инициация такой переменной осуществляется вызовом функции CreateOleObject, определенной в модуле comobj. Эта функция возвращает ссылку на интерфейс IDispatch, с помощью которой можно обращаться к методам и свойствам класса Автоматизации так, как если бы они были методами и свойствами варианта. Например, следующая программа вызывает текстовый процессор MS Word, вставляет в пустую страницу две строки и сохраняет полученный документ на диске:

Uses ComObj;

Var

Word: Variant;

Begin

Word := CreateoieObject('Word.Basic');

Word.FileNew('Normal');

Word.Insert('Первая строка'#13);

Word.Insert('Вторая строка'#13);

Word.FileSaveAs('с:\temp\test.txf, 3);

End;

Параметром обращения к CreateoieObject является имя сервера Автоматизации, которое должно быть предварительно зарегистрировано в реестре Windows 32. Характерно, что методы сервера не известны на этапе компиляции программы, поэтому компилятор никак не контролирует правильность их вызовов. Названия методов не подчиняются правилам построения идентификаторов Delphi, и в них могут использоваться символы национальных алфавитов.

 

 


  • Лекция 10. ВАРИАНТЫ
    • ОСНОВНЫЕ СВОЙСТВА ВАРИАНТА
    • ПРЕОБРАЗОВАНИЕ ВАРИАНТОВ К ДАННЫМ ДРУГИХ ТИПОВ
    • ПОДПРОГРАММЫ ДЛЯ РАБОТЫ С ВАРИАНТАМИ
    • ВАРИАНТНЫЕ МАССИВЫ
    • ПОЛЬЗОВАТЕЛЬСКИЕ ВАРИАНТЫ
      • Размещение в варианте новых значений
      • Создание наследника TCustomVariantType
      • Создание вспомогательных методов

ОСНОВНЫЕ СВОЙСТВА ВАРИАНТА

Вариант (в Delphi 1 он отсутствует) - это тип variant, разработанный специально для тех случаев, когда на этапе компиляции программист не может сказать, какого типа данные будут использоваться в выражении или как параметры вызова подпрограмм. Переменная-вариант занимает в памяти дополнительные 2 байта, в которые помещается информация о действительном типе переменной. Эта информация позволяет компилятору создать код, который будет осуществлять необходимое преобразование типов на этапе прогона программы.

В переменную-вариант можно поместить:

  • целое или вещественное число;
  • логическое значение;
  • строку;
  • время и/или дату;
  • OLE-объект;
  • массив произвольной размерности и длины, содержащий элементы одного из перечисленных выше типов.

Варианты могут участвовать в целочисленных, вещественных, логических и время-дата выражениях при условии корректности соответствующих преобразований. Например, если варианту v присвоена строка '1.0', то выражение 1+v будет правильным вещественным значением 2,0. Однако если v:= 'текст', выражение 1+v вызовет исключение EVariantError.

В Delphi определены такие константы, указывающие тип помещенных в вариант данных:

Таблица 10.1. Типы возможных значений варианта

Имя Константа Смысл
varEmp.ty $0000 Нет данных
varNull $0001 Неизвестный тип параметра

 

varSmallInt $0002 Целый тип Smallint

 

varlnteger $0003 Целый тип Integer
varSingle $0004 Вещественный тип Single
varDouble $0005 Вещественный тип Double
varCurrency $0006 Вещественный тип Currency
varDate $0007 Тип дата-время
varOleStr $0008 OLE-строка в кодировке Unicode
varDispatch $0009 Указатель на OLE-объект
varError $000А Код ошибки
varBoolean $000В Тип WordBool
varVariant $000С Тип Variant (только для вариантных массивов)
varUnknow $0011 Неизвестный OLE-объект
varByte $0100 Целый тип Byte
varString $0100 Строковый тип
varArray $2000 Вариантный массив
varByRef $4000 Указатель на данные

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

TVarData = packed record

VType: Word;

Reservedly Reserved2, ReservedS: Word;

case Integer of

varSmallInt: (VSmallInt: Smallint);

varlnteger: (VInteger: Integer);

varSingle: (VSingle: Single);

varDouble: (VDouble: Double);

varCurrency: (VCurrency: Currency);

varDate:(VDate: Double);

varOleStr: (VOleStr: PWideChar);

varDispatch: (VDispatch: Pointer);

varError: (VError: WordBool);

varString: (VString: Pointer);

varArray: (VArray: PVarArray);

varByRef: (VPointer: Pointer);

End;

Как нетрудно убедиться, любая переменная вариантного типа представляет собой 16-байтную запись, содержащую 8-байтную вариантную часть, которая хранит либо собственно данные, либо их адрес (т. е. указатель на динамически размещ

К чему приводится Тип данных в варианте
varEmpty Целые Вещественные Дата- Время Строковые Логические
К дата- 'У: время 30.12. 1899 00:00:00 Преобразование в Double Преобразование в Double Без преобразования Преобразование в дату Преобразование в Double
К целым 0 Преобразование в соответствующий тип Округление до ближайшего целого Округление до ближайшего целого Преобразование в целый тип 0 для False, иначе-1 (255 для Byte)
.'К дата- 'У: время 30.12.1899 00:00:00 Преобразование в Double Преобразование в Double Без преобразования Преобразование в дату Преобразование в Double
К строковым Пустая строка Преобразование в символьный вид Преобразование в символьный вид Преобразование в символьный вид Без преобразования '0'для False,'-!' для True
К логическим False False для 0, иначе True False для 0, иначе True False для 0, иначе True False для 'False' и для '0', иначе True Без преобразования

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

ПРЕОБРАЗОВАНИЕ ВАРИАНТОВ К ДАННЫМ ДРУГИХ ТИПОВ

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

Таблица 10.2. Преобразование типов для вариантов

Здесь

К целым Отнесены varByte, varSmallInt, varlnteger/ varError;

К вещественным — varSingle, varDouble/ varCurrency;

К строковым -var String, varOleStr.

ПОДПРОГРАММЫ ДЛЯ РАБОТЫ С ВАРИАНТАМИ

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

Таблица 10.3. Подпрограммы для работы с вариантами

function VarAsType(const V: Variant; VarType: Integer): Variant; Преобразует данные варианта V к типу, определяемому параметром VarType
procedure VarCast(var Dest: Variant; const Source: Variant; Var Type: Integer); Преобразует данные варианта Source к типу,определяемому параметром VarType, и помещает результат в переменную Dest
procedure VarClear(var V: Variant);   Освобождает динамическую память, если она была связана с вариантом, и дает ему тип varEmpty
procedure VarCopy(var Dest: Variant; const Source: Variants; Копирует параметр Source в вариант Dest
function VarFrom-DateTime(DateTime: TDateTime):Variant; Возвращает вариант, содержащий данные DateTime типа дата-время
function VarIsEmpty(const V: Variant): Boolean; Возвращает True, если вариант V не содержит данных
function VarIsNull(const V: Vari ant): Boolean; Возвращает True, если вариант V содержит данные неопределенного типа (varNull) ',
function VarToDateTime(const V: Variant): TDateTime); Преобразует данные варианта V к типу дата-время
function VarToStr(const V: Vari ant): String; Преобразует данные варианта V к строке;
function VarType(const V: Variant): Integer; Возвращает тип хранящихся в варианте данных i

 

ВАРИАНТНЫЕ МАССИВЫ

Значением варианта может быть массив данных, такие варианты называются вариантными массивами. (Не путайте с обычным или динамическим массивом, элементами которого являются варианты!) Значениями элементов вариантного массива могут быть любые допустимые для варианта значения, кроме строк varstring. Значениями элементов вариантного массива могут быть и варианты, а это значит, что в таком массиве могут одновременно храниться данные разных типов (и в том числе строки). Например:

Var

V: Variant;

Begin

// Создаем одномерный вариантный массив с 5 элементами:

V:= VarArrayCreate([0, 4], varVariant);

// Наполняем его:

V[0]:= 1; //Тип целый

V[1]:= 1234.5678; //Тип вещественный

V[2]:= 'Hello world'; //Строковый тип

V[3]:= True; //Логический тип

//Пятым элементом исходного массива сделаем еще один массив:

V[4]:= VarArrayOf([l, 10, 100, 1000]);

Caption:= V[2]; //Hello world

IbOutput.Caption:= IntToStr(V[4][2]); //200

End;

Все действия с вариантными массивами осуществляются с помощью следующих процедур и функций:

Таблица 10.4. Подпрограммы для работы с вариантными массивами

function VarArrayCreate(const Bounds: array of Integer; VarType: Integer): Variant; Создает вариантный массив из элементов типа VarType с количеством и границами измерений, указываемых параметром Bounds
function VarArrayDimCount(const A: Variant): Integers; Возвращает количество измерений вариантного массива А или 0, если А не массив
function VarArrayHighBound(const A: Variant; Dim: Integer): Integer; Возвращает верхнюю границу индекса вариантного массива А по измерению Dim
function VarArrayLock(var A: Variant): Pointer;   Блокирует массив (предотвращает его возможные изменения размеров) и возвращает указатель на связанные с ним данные
function VarArrayLowBound(const A: Variant; Dim: Integer): Integers; Возвращает нижнюю границу индекса вариантного массива А по измерению Dim
function VarArrayOf(const Values: array of Variant): Variants;     Создает одномерный вариантный массив по перечню значений, содержащихся в открытом массиве Values. Нижняя граница индексов вариантного массива в этом случае равна 0
procedure VarArrayRedim(var A: Variant; HighBound: Integer);     Изменяет верхнюю границу индекса вариантного массива А на величину HighBound. Вызов про цедуры игнорируется, если массив был заблоки рован функцией VarArrayLock
function VarArrayRef(const A: Variant): Variants; Возвращает ссылку на вариантный массив. Ис пользуется при обращении к API-функциям
procedure VarArrayUnlock(var A: Variant) Отменяет действие функции VarArrayLock  

ПОЛЬЗОВАТЕЛЬСКИЕ ВАРИАНТЫ

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

Чтобы познакомиться со свойствами новых вариантов, воспользуемся одним из них - вариантом, способным хранить комплексные числа, преобразовывать их в другие типы и осуществлять над ними нужные действия. Как мы увидим дальше, создание пользовательского варианта может быть весьма трудоемким делом - все зависит от сложности хранимых в нем данных. Мы воспользуемся вариантом, созданным разработчиками Delphi и включенным в модуль

VarCmplx.

Создайте такой обработчик bbRunClick:

uses VarCmplx; // Эта ссылка обязательна!

procedure TfmExample.bbRunClick(Sender: TObject);

Var

VI, V2: Variants- begin

// Создаем два случайных комплексных числа:

VI:= VarComplexCreate(Trunc(Random*1000)/100,

Trunc(Random*1000)/100);

V2:= VarComplexCreate(Trunc(Random*1000)/100,

Trunc(Random*1000)/100);

with mmOutput.Lines do

Begin

// Пустая строка-разделитель

Add (' ');

Add('1-e число: '# 9+V1);

Add('2-е число: '#9+V2);

Add('Сложение'#9+(V1+V2));

Add('Вычитание'#9+(V1-V2));

Add('Умножение'# 9+(VI*V2));

Add('Деление'#9#9+(V1/V2))

End

End;

Небольшой комментарий: сложная конструкция Trunc (Random*1000) /100 понадобилась только для того, чтобы реальные и мнимые части комплексных чисел содержали по три значащих цифры.

Вид экрана работающей программы показан на рис. 10.1. Как видим, новый вариант легко справляется с поддержкой комплексных чисел: функция VarComplexCreate создает вариант, содержащий комплексное число, а дальнейшее поведение варианта -стандартное (он поддерживает математические операции и преобразование к строковому типу). Однако эта легкость обманчива: исходный текст модуля VarCmplx, который, собственно, и придал варианту дополнительные свойства (по умолчанию располагается в файле Source\Rtl\Common\VarCmplx.pas), содержит более 30000 байт..

На с. 229 показана структура записи TVarData. Два первых байта в этой записи (поле VType) хранят признак значения варианта, остальные 14 могут использоваться для размещения данных.

Рис. 10.1. Демонстрация комплексных вариантов

Создание пользовательского варианта проходит в три этапа.

  1. Сначала в записи rvarData размещаются новые данные или ссылка на них.
  2. Объявляется класс, который является прямым или косвеннымпотомком специального класса TCustomVariantType. В этомклассе предусматриваются все необходимые методы для реализации свойств варианта: присваивания ему новых значений, преобразования хранящихся значений к другим типам, выполнения необходимых математических действий.
  3. Создаются вспомогательные методы для объявления потомков нового класса и определения их типов.

В результате перечисленных шагов вы получаете полноценный вариант, обогащенный новыми свойствами: он может хранить не только те значения, которые перечислены в табл. 10.2, но и любые другие, в том числе свойства и методы! (В этом последнем случае наследником для исполняемого класса нового варианта вместо TCustomVariantType является TInvokeableVariantType или TPublishableVariantType.)

10.5.1. Размещение в варианте новых значений

Для размещения в варианте нового (не предусмотренного стандартным вариантом) значения нужно создать соответствующий класс и поместить в подходящее поле rvarData объект этого класса. Вот как, например, размещаются комплексные данные в модуле VarCmplx:

TComplexVarData = packed record

VType: TVarType;

Reserved1, Reserved2, Reserved3: Word;

VComplex: TComplexData;

Reserved4: Longint;

End;

Такая запись лишь сохраняет 16-байтную структуру TVarData, помещая в поле VComplex ссылку на объект класса TComplexData. Собственно комплексные числа хранятся в полях достаточно сложного класса:

Type

TComplexData = class(TPersistent) private

FReal, FImaginary: Double;

End;

В этом классе предусмотрены многочисленные методы, управляющие новыми данными. Так, простой вызов VarComplexCreate

приводит к срабатыванию нескольких методов, создающих объект VComplex и наполняющих его поля:

procedure VarComplexCreateInto (var ADest: Variant;

const AComplex: TComplexData);

Begin

VarClear(ADest);

TComplexVarData(ADest).VType:= VarComplex;

TComplexVarData(ADest).VComplex:= AComplex;

end; function VarComplexCreate(const AReal, AImaginary: Double):

Variant;

Begin

VarComplexCreateInto(Result,

TComplexData.Create(AReal, AImaginary));

End;

(CM. файл Source\Rtl\Common\VarCmplx.pas).

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

10.5.2. Создание наследника TCustomVariantType

Тип TCustomVariantType или его ближайшие Наследники TPublishableVariantType и TInvokeableVariantType Содержат методы и

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

Type

TComplexVariantType =

class(TPublishableVariantType, IVarStreamable) protected

function LeftPromotion(const V: TVarData;

const Operator: TVarOp;

out RequiredVarType: TVarType): Boolean; override;

function RightPromotion(const V: TVarData;

const Operator: TVarOp;

out RequiredVarType: TVarType): Boolean; override;

function Getlnstance(const V: TVarData): TObject; override;

Public

procedure Clear(var V: TVarData);







Дата добавления: 2015-10-18; просмотров: 496. Нарушение авторских прав; Мы поможем в написании вашей работы!




Кардиналистский и ординалистский подходы Кардиналистский (количественный подход) к анализу полезности основан на представлении о возможности измерения различных благ в условных единицах полезности...


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


Композиция из абстрактных геометрических фигур Данная композиция состоит из линий, штриховки, абстрактных геометрических форм...


Важнейшие способы обработки и анализа рядов динамики Не во всех случаях эмпирические данные рядов динамики позволяют определить тенденцию изменения явления во времени...

МЕТОДИКА ИЗУЧЕНИЯ МОРФЕМНОГО СОСТАВА СЛОВА В НАЧАЛЬНЫХ КЛАССАХ В практике речевого общения широко известен следующий факт: как взрослые...

СИНТАКСИЧЕСКАЯ РАБОТА В СИСТЕМЕ РАЗВИТИЯ РЕЧИ УЧАЩИХСЯ В языке различаются уровни — уровень слова (лексический), уровень словосочетания и предложения (синтаксический) и уровень Словосочетание в этом смысле может рассматриваться как переходное звено от лексического уровня к синтаксическому...

Плейотропное действие генов. Примеры. Плейотропное действие генов - это зависимость нескольких признаков от одного гена, то есть множественное действие одного гена...

Типовые ситуационные задачи. Задача 1.У больного А., 20 лет, с детства отмечается повышенное АД, уровень которого в настоящее время составляет 180-200/110-120 мм рт Задача 1.У больного А., 20 лет, с детства отмечается повышенное АД, уровень которого в настоящее время составляет 180-200/110-120 мм рт. ст. Влияние психоэмоциональных факторов отсутствует. Колебаний АД практически нет. Головной боли нет. Нормализовать...

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

Признаки классификации безопасности Можно выделить следующие признаки классификации безопасности. 1. По признаку масштабности принято различать следующие относительно самостоятельные геополитические уровни и виды безопасности. 1.1. Международная безопасность (глобальная и...

Studopedia.info - Студопедия - 2014-2024 год . (0.008 сек.) русская версия | украинская версия