От Delphi 4 к Delphi 5 часть 29

От Delphi 4 к Delphi 5
Перечислимые типы.


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

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

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


type

typeName
= (val1,..., valn);


где typeName имя перечислимого типа, val - идентификаторы.

Например, следующее объявление:


type

Suite = (Club, Diamond, Heart, Spade);


определяет перечислимый тип, названный Иск, его возможные величины являются Клуб, Алмаз, Сердце и Лопата. К сожалению, в Object Pascal нельзя использовать кириллицу.

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


type

TSound = (Click, Clack, Clock);


К сожалению, выражение Click является также именем метода определенного для TControl библиотеки Delphi VCL .

Так, если вы напишите в своем приложении следующий программный код:


procedure TForm1.DBGrid1Enter(Sender: TObject);

var Thing: TSound;

begin

...

Thing := Click;

...

end;


Вы получите ошибку компиляции; компилятор интерпретирует Click в пределах области процедуры как ссылку на метод, щелчок по форме. Вы можете работать по-другому, квалифицируя идентификатор таким образом, что если TSound объявляется в MyUnit, вы должны использовать:


Thing := MyUnit.Click;


Лучшим решением, тем не менее, является выбор имен с некоторым изменением, например:


type

TSound = (tsClick, tsClack, tsClock);

TMyColor = (mcRed, mcBlue, mcGreen, mcYellow, mcOrange);

Answer = (ansYes, ansNo, ansMaybe);


Т.е. вы сохраняете понятный смысл имени, но не вступаете в конфликт с системой.

Вы можете использовать значения (val1,..., valn) при объявлении переменных, например:


var MyCard: (Club, Diamond, Heart, Spade);


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


var Card1: (Club, Diamond, Heart, Spade);

var Card2: (Club, Diamond, Heart, Spade);


генерирует ошибку компиляции. Но объявление


var Card1, Card2: (Club, Diamond, Heart, Spade);


ошибку компиляции не дает.

Или можно объявить таким образом:


type Suit = (Club, Diamond, Heart, Spade);

var

Card1: Suit;

Card2: Suit;


Соответствие между значениями перечисляемого типа и порядковыми номерами этих значений устанавливается порядком перечисления: первое значение в списке получает порядковый номер 0, второе значение — порядковый номер 1 и т.д.

Максимальное число констант перечислимого типа составляет 65536 значений, поэтому фактически перечислимый тип задает некоторое подмножество целого типа Word и может рассматриваться как компактное объявление сразу группы целочисленных констант со значениями 0, 1 и т.д.

Пусть, например, в программе должна быть переменная Mode, в которой зафиксирован один из возможных режимов работы приложения: чтение данных, их редактирование, запись данных. Можно, конечно, определить переменной Mode тип Word и присваивать этой переменной в нужные моменты времени одно из трех условных чисел: 0 - режим чтения, 1 - режим редактирования, 2 - режим записи. Тогда программа будет содержать операторы вида


if (Mode = 1) then ...


Через некоторое время уже забудется, что означает значение Mode, равное 1, и разбираться в таком коде будет очень сложно. А можно поступить иначе: определить переменную Mode как переменную перечислимого типа и обозначить ее возможные значения как mRead, mEdit, mWrite . Тогда приведенный выше оператор изменится следующим образом:


if (Mode = mEdit) then ...


Конечно, такой оператор понятнее, чем предыдущий.

Переменная перечислимого типа может определяться предложением вида:


var <имя переменной> : (<значение 1>, ..., < значение n>);


Например


var Mode : (mRead, mEdit, mWrite);


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

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


type <имя типа> = (<значение 1>, ..., < значение n>);

Тогда можно ввести в программе несколько переменных этого типа. Например:

type TMode : (mRead, mEdit, mWrite);

var Mode1, Mode2 : TMode;


Для работы с перечислимыми типами имеется несколько системных подпрограмм, описанных в системном модуле Delphi.


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

Например:


type

Colors = (RED,BLUE,GREEN);

procedure TForm1.Button1Click(Sender: TObject);

var

S: string;

begin

S := 'Blue имеет порядковую величину ' + IntToStr(Ord(BLUE)) + #13#10;

S := S + 'Код ASCII для "c" - ' + IntToStr(Ord('c')) + ' decimal';

MessageDlg(S, mtInformation, [mbOk], 0);

end;

end.


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

procedure
Dec(var X[; N: Longint]);


Процедура Dec уменьшает переданную в качестве параметра переменную на единицу или на значение необязательного второго параметра, т.е. уменьшает на единицу или на число N переменную.


X
- переменная перечислимого типа (включая Int64 ), или указатель, если позволен расширенный синтаксис.


N
- выражение целого типа.


procedure TForm1.Button1Click(Sender: TObject);

var

IntVar: Integer;

LongintVar: Longint;

begin

Intvar := 10;

LongintVar := 10;

Dec(IntVar); { IntVar := IntVar - 1 }

Dec(LongintVar, 5); { LongintVar := LongintVar - 5 }

Edit1.Text:=IntToStr(IntVar);

Edit2.Text:=IntToStr(LongintVar);

end;

end.

procedure Inc(var X [ ; N: Longint ] );


Процедура Inc увеличивает переданную в качестве параметра переменную на единицу или на заданное значение.


X
- переменная перечислимого типа (включая Int64 ), или указатель, если позволен расширенный синтаксис.


N
- выражение целого типа.


var

IntVar: Integer;

LongintVar: Longint;

begin

Inc(IntVar); { IntVar := IntVar + 1 }

Inc(LongintVar, 5); { LongintVar := LongintVar + 5 }

end;


Функция Odd возвращает True, если параметр нечетное число.


function Odd(X: Longint): Boolean;


Например:


procedure TForm1.Button1Click(Sender: TObject);

begin

if Odd(5) then

Canvas.TextOut(10, 10, '5 нечетное.')

else

Canvas.TextOut(10, 10, 'Четное!');

end;

end.


Функция Pred возвращает значение, которое в определяемой типом данных последовательности стоит перед значением параметра; предшественник.


function Pred(X);

X
- выражение порядкового типа (включая Int64). Результат того же самого типа как предшественник X.


function Succ(X);

Succ
возвращает значение, преемника.

X - выражение порядкового типа (включая Int64). Результат того же самого типа как X - преемник X. Не используйте Succ в процедурах записи.

Запишите следующий программный код, для проверки этой функции:


type

Colors = (RED,BLUE,GREEN);

procedure TForm1.Button1Click(Sender: TObject);

var

S: string;

begin

S := 'Предшественник для числа 5, ' + IntToStr(Pred(5)) + #13#10;

S := S + 'Преемник числа 10, ' + IntToStr(Succ(10)) + #13#10;

if Succ(RED) = BLUE then

S := S + 'Красный цвет предшествненник синего.';

MessageDlg(S, mtInformation, [mbOk], 0);

end;

end.


На рисунке 2 показано выдаваемое сообщение по результатам работы этой программы.


function Low(X);

Low
возвращает самое низкое значение в диапазоне перечислимого типа, переданного как параметр.


function High(X);

High
возвращает самое высокое значение в диапазоне перечислимого типа данных.

Рассмотрим пример, использующий функции Low и High.

implementation

{$R *.DFM}

function Sum( var X: array of Double): Double;

var

I: Word;

S: Real;

begin

S := 0; {Имейте в виду, что открытый индекс области

массива всегда нулевой.}

for I := 0 to High(X) do S := S + X[I];

Sum := S;

end;

procedure TForm1.Button1Click(Sender: TObject);

var

{описание массива, содержащего четыре элемента}

List1: array[0..3] of Double;

{описание массива содержащего 13 элементов}

List2: array[5..17] of Double;

X: Word;

S, TempStr: string;

begin

for X := Low(List1) to High(List1) do

List1[X] := X * 3.4;

for X := Low(List2) to High(List2) do

List2[X] := X * 0.0123;

Str(Sum(List1):4:2, S);

{проводимые расчеты заключаются в следующем 0*3.4 + 1*3.4 +2*3.4 + 3*3.4 = 20.40}

S := 'Sum of List1: ' + S + #13#10;

{аналогично для второго массива 5*0.0123 + 6*0.0123 + и так далее…}

S := S + 'Sum of List2: ';

Str(Sum(List2):4:2, TempStr);

S := S + TempStr;

MessageDlg(S, mtInformation, [mbOk], 0);

end;

end.


Результат работы программы показан на рисунке 3.


Ограниченные типы или тип-диапазон.


Для порядковых типов можно задать диапазон их возможных значений для вводимого вами типа или переменной - это и будет ограниченный тип. Тип-диапазон задается границами своих значений внутри базового порядкового типа и описывается выражением вида:


<минимальное значение>..<максимальное значение>


где определено минимальное и максимальное значение типа-диапазона.

Например, если вы объявляете перечисленный тип


type TColors = (Red, Blue, Green, Yellow, Orange, Purple, White, Black);


{красный, синий, зеленый, желтый, апельсиновый, пурпурный, белый, черный}, то вы можете затем определить тип-диапазон таким образом:


type TMyColors = Green..White;


Здесь TMyColors включает величины: зеленый, желтый, апельсиновый, пурпурный и белый.

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


type

range = '0'..'14';

range1 = 1..7;

SomeNumbers = -128..127;

Caps = 'A'..'Z';


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


var

Alphabet : 'a'..'z';

Column : 1..12;

Day : 1..31;


В этих примерах переменная Alphabet может принимать только символы латинских букв в нижнем регистре, переменная Column принимает значения только целых чисел в диапазоне 1 - 12 (это могут быть, например, номера месяцев), переменная Day также принимает значения только целых чисел, но в диапазоне 1 - 31.

При определении типа-диапазона необходимо руководствоваться следующими правилами:

левое значение границы диапазона не должно превышать его правую границу;

два символа <<..>> рассматриваются как один символ, поэтому между ними недопустимы пробелы.

Тип-диапазон наследует все свойства своего базового типа, но с ограничениями, связанными с его меньшей емкостью. Так, по вполне понятным причинам процедуры Ord(X) и Pred(X) не всегда выполнимы.

Рассмотрим пример с использованием процедуры Inc :


type Percentile = 0..99;

var I: Percentile;

...

Inc(I);


Для данного примера компилятор выдает ошибку, так как величина 100 не входит в диапазон объявленного ограниченного типа. Как вы помните, процедура Inc увеличивает переданную в качестве параметра переменную на единицу или на заданное значение.

В стандартную библиотеку Object Pascal введены две функции, поддерживающие работу с типами-диапазонами: High(X) и Low(X).


Ограниченные типы могут использоваться, например, для объявления размеров массивов, но и самостоятельно. В компиляторе Object Pascal имеется опция, позволяющая включить проверку диапазона при присваивании значения переменной ограниченного типа. Ее значение {$R+} вы можете включить в том месте вашей программы, где вы хотите начать проверку диапазона, и выключить проверку, где захотите, опцией {$R-}. Можно также включить опцию проверки в окне Project Options на странице Compiler . Это надежнее, так как опция {$R+} работает только при возникновении ошибок диапазона, очевидных для компилятора, а установка опции проверки диапазона в окне Project Options действует в процессе выполнения (в режиме отладки) и при попытке присвоить переменной ограниченного типа значение, выходящее за пределы заданного диапазона, генерирует сообщение "Range check error ".

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


Компонент
Bevel.


Этот компонент предназначен для оформления вашего приложения. Bevel позволяет выделять группы элементов, отделять их друг от друга.

Свойство


type TBevelShape = (bsBox, bsFrame, bsTopLine, bsBottomLine, bsLeftLine, bsRightLine, bsSpacer);

property Shape: TBevelShape;


определяет контур компонента.

Свойство


type TBevelStyle = (bsLowered, bsRaised);

property Style: TBevelStyle;


определяет стиль компонента (вдавленный или выпуклый). На рисунке 4 показаны свойства компонента Bevel.

Компонент ScrollBox.

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

Пользоваться этим компонентом достаточно просто. Поместите ScrollBox на форму и проведите размещение на управляющем элементе любых компонентов. Если очередной компонент выйдет за пределы рабочей области контейнера, то появятся полосы прокрутки (рисунок 5).

Свойство


property BorderStyle: TBorderStyle;
определяет:

если BorderStyle = bsNone, то компонент не имеет видимой границы обрамления;

если BorderStyle = BsSingle, то компонент имеет видимую границу обрамления.


Мультимедиа-приложения.


Рассмотрим пример создания мультимедиа-приложения, в котором используем свойства компонента Bevel.


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

Используя свой компьютер, вы можете получать качественное воспроизведение звука на внешних HiFi-колонках или встроенных в монитор, а также видеть прекрасную картинку, просматривая фильм.

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

Музыкальные произведения, звуковые эффекты и записи речевой информации хранятся на носителях информации в файлах специальных форматов, среди которых чаще всего применяется формат WAV (от слова wave — волна). Для хранения видеоинформации чаще всего используются файлы с расширением AVI ( Audio-Video-Information ). Обычно аудио- и видео-файлы очень большие по объему, поэтому они размещаются на лазерных дисках.

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

Для создания мультимедиа-приложения используется компонент Delphi, имя которого MediaPlayer со страницы System палитры компонентов. Внешне компонент выглядит как панель управления магнитофона, видеомагнитофона или музыкального центра с девятью кнопками.

Итак, приступим.

  1. Запустите Delphi.

  2. Используя свойство Caption, для компонента Form1 введите заголовок "CD-проигрыватель".
  3. Поместите на форму компонент Bevel. Установите в свойстве Style значение bsRaised.
  4. На компонент Bevel поместите Label, введите заголовок "Проигрыватель компакт-дисков". Выровняйте компоненты, чтобы Label1 был посередине Bevel1.
  5. Разместите на форме еще один компонент Bevel, оставьте без изменений установленное по умолчанию свойство Style равное bsLowered .
  6. Поместите на Bevel2 компонент MediaPlayer. Создайте мультимедиа приложение для проигрывания компакт-дисков.
  7. Для этого установите свойство Device Type в значение dtCDAudio, а свойству AutoOpen установите значение True.
  8. Используя комплексное свойство VisibleButtons, установите значения btStep = False, btBack = False, btRecord = False. Благодаря этим действиям с панели будут убраны все ненужные кнопки (рисунок 6) .
  9. После запуска приложения на компиляцию можете вставить компакт-диск в устройство CD-ROM и щелчком по кнопке Play осуществить воспроизведение ваших любимых мелодий.
  10. Можете добавить в свое приложение компонент Image и внедрить картинку. Размещение компонентов можно сделать как на рисунке 7, используя при этом всплывающее меню, вызываемое щелчком правой кнопкой мыши.



Литература:

    1. Марко Канту. Delphi 2 для Windows 95/NT. Москва. ООО "Малип". 1997г.
    2. Джон Матчо. Дэвид Р. Фолкнер. Delphi. Москва. БИНОМ. 1995г.
    3. Эндрю Возневич. Delphi. Освой самостоятельно. Москва. Восточная книжная компания. 1996г.
    4. К. Сурков, Д. Сурков, А. Вальвачев. Программирование в среде Delphi 2.0. Минск. 1997 г. ООО "Попурри".
    5. В.В.Фаронов. Delphi 5. Учебный курс. Москва. Издательство Нолидж. 2000 г.
    6. А. Я. Архангельский. Программирование в Delphi 5. Москва. ЗАО "Издательство Бином". 2000г.

Владимир Скуратов



(c) компьютерная газета


Компьютерная газета. Статья была опубликована в номере 40 за 2001 год в рубрике программирование :: delphi

©1997-2024 Компьютерная газета