Delphi 6 программирование

         

События от клавиатуры



17.6.2. События от клавиатуры

События от мыши получают любые потомки TControl. В отличие от этого события от клавиатуры получают только некоторые оконные компоненты (потомки TWinControi). Обработка событий связана со следующими свойствами этих компонентов:

type

TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft,

ssRight, ssMiddie, ssDoubie) ;

TKeyEvent = procedure (Sender: TObject; var Key: Word;

Shift: TShiftState) of object;

TKeyPressEvent = procedure (Sender: TObject;

var Key: Char) of object-property OnKeyDown: TKeyEvent;

property OnKeyUp: TKeyEvent;

property OnKeyPress: TKeyPressEvent;

Параметр Shift, как и в обработчиках событий от мыши, содержит уточняющие признаки. Параметр Key в обработчиках TKeyEvent содержит виртуальный код клавиши, а в обработчике TKeypressEv-ent - ASCII-символ. Обработчики OnKeyDown и опкеуор перехваты-вают нажатие большинства клавиш клавиатуры, в то время как обработчик QnKeypress - только нажатие алфавитно-цифровых клавиш. Получаемый им символ Key учитывает выбранный язык и нажатую клавишу Shift.

Виртуальные коды клавиш определены константами vk_xxx в файле source | rtl | win windows . pas каталога размещения Delphi. Фактически виртуальный код - это просто уникальный числовой идентификатор клавиши. Для буквенно-цифровых клавиш О...9 и A...Z виртуальный код совпадает с кодом, возвращаемым функцией ord(X), где х - соответствующий заглавный символ: ord('o'), ord( 'w') и т. д. К сожалению, уникальность кода не обеспечивается для клавиши Enter в зоне дополнительных числовых клавиш, которой присвоен код 13, - как и аналогичной клавише в основной зоне, а также для правых и левых сдвиговых клавиш Shift, Alt и Ctrl. Кроме того, клавиши О...9 и Del в зоне дополнительной клавиатуры сопровождаются уникальным кодом только при активном переключателе NumLock, в противном случае они повторяют коды соответствующих управляющих клавиш. Все остальные клавиши стандартной клавиатуры (за исключением Print Screen, клавиш смещения курсора и Tab, нажатие на которые не передается в обработчики TKeyEvent) имеют постоянно закрепленные за ними числовые коды, позволяющие легко установить факт нажатия или отпускания любой из них.

Поскольку параметр кеу в каждом обработчике определен как параметр-переменная, программист может изменить фактический код клавиши на нужный. Такая возможность может оказаться полезной для фильтрации нажатия каких-либо клавиш. При этом изменение кода происходит в обработчике формы, а в оконный элемент с фокусом ввода будет поступать уже измененный код. Чтобы форма получила событие до передачи его в элемент с фокусом ввода, следует поместить в свойство property KeyPreview: Boolean; формы значение True.



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



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);

override;

function IsClear(const V: TVarData): Boolean; override;

procedure Copy(var Dest: TVarData;

const Source: TVarData;

const Indirect: Boolean);

override;

procedure Cast(var Dest:

TVarData;

const Source: TVarData);

override;

procedure CastTo(var Dest: TVarData;

const Source: TVarData;

const AVarType: TVarType);

override;

procedure BinaryOp(var Left: TVarData;

const Right: TVarData;

const Operator: TVarOp); override;

procedure UnaryOp(var Right: TVarData;

const Operator: TVarOp);

override;

function CompareOp(const Left: TVarData;

const Right: TVarData;

const Operator: Integer): Boolean;

override;

procedure Streamin(var Dest: TVarData;

const Stream: TStream) ;

procedure StreamOut(const Source: TVarData;

const Stream: TStream) ;

end;

Обратите внимание: класс TComplexVariantType - интерфейсный (см. п. 9.4.1). Помимо общих для варианта методов он реализует также два метода, специфичных для интерфейса Ivarstreamabie -Streamin и StreamOut, с помощью которых значения нового интерфейса сохраняются в потоке и считываются из него.

Задача этого класса - дать единообразные команды, способные интерпретироваться объектом vcomplex как команды преобразования типа хранящихся данных, их сравнения, реализации над ними тех или иных операций, наконец, записи их в поток и чтения из него. Например, метод cast этого класса вызывается для преобразования других типов значений к комплексному типу, метод castTo - для обратного преобразования, метод BinaryOp реализует бинарную операцию, a Unarydp - унарную и т. д.

Еще раз подчеркну, что основная работа (например, по выполнению бинарных операций) реализуется методами класса TComplex-Data. Класс TCompiexVariantType перекрывает абстрактные методы своего родителя, подключая TComplexData к решению той или иной проблемы.

Поскольку для создания экземпляра нового варианта необходим уже готовый экземпляр (объект) класса TCompiexVariantType, он создается в секции инициализации модуля varcmpix и уничтожается в завершающей секции:

initialization

ComplexVariantType := TCompiexVariantType.Create;

finalization

FreeAndNil(ComplexVariantType);



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



11.7.2. Создание объекта отображения

На втором этапе создается объект отображения в память. Для этого используется такая функция:

function CreateFileMapping(hFile: THandle; IpFileMapping-Attributes: PSecurityAttributes; flProtect, dwMaximumSize-High, dwMaximumSizeLow: DWord; IpName: PChar): THandle;

Здесь hFile - дескриптор файла; ipFileMappingAttributes - указа-тель на структуру, в которой определяется, может ли создаваемый объект порождать дочерние объекты (обычно не может - nil); flProtect -определяет тип защиты, применяемый к окну отображения файла (см.ниже); dwMaximumSizeHigh, dwMaximumSizeLow - соответственно Старшие и младшие 32 разряда размера файла; если вы будете отображать файлы длинной до 4 ГбаЙТ, поместите В dwMaximumSizeHigh 0, а В dwMaximumSizeLow - длину файла; если оба параметра равны 0, размер окна отображения равен размеру файла; ipName - имя объекта отображения или nil.

Параметр flProtect задает тип защиты, применяемый к окну просмотра файла, и может иметь одно из следующих значений: page_readonly - файл можно только читать (файл должен быть создан или открыт В режиме fmOpenRead); PAGE_READWRITE - файл можно читать и записывать в него новые данные (файл открывается в режиме fmOpenReadWrite); PAGE_WRITECOPY - файл открыт для записи и чтения, однако обновленные данные сохраняются в отдельной защищенной области памяти (отображенные файлы могут разделяться программами, в этом режиме каждая программа сохраняет изменения в отдельной области памяти или участке файла подкачки); файл открывается В режиме fmOpenReadWrite или fmOpenWrite; этот тип защиты нельзя использовать в Windows 95/98. С помощью операции or к параметру fiprotect можно присоединить такие атрибуты:

sec_commit - выделяет для отображения физическую память или участок файла подкачки; sec_image - информация об атрибутах отображения берется из образа файла; sec_nocashe - отображаемые данные не кэшируются и записываются непосредственно на диск;

sec_reserve - резервируются страницы раздела без выделения физической памяти. Функция возвращает дескриптор объекта отображения или 0, если обращение было неудачным.



Страница Data Controls



4.8.2. Страница Data Controls

15 компонентов этой страницы предназначены для визуализации данных, их ввода и редактирования. Многие компоненты этой страницы введены еще в версии 1.



Страница FastNet



4.9.2. Страница FastNet

Компоненты этой страницы предоставляют программисту возможность использования различных протоколов для передачи деловых сообщений и данных по локальным и/или глобальным сетям, в том числе и по Интернет. В версиях 2, 3 и 4 они размещались на странице internet. В версии 1 таких компонентов нет. Для меж-ллатформенных программ вместо этих компонентов следует использовать компоненты страниц Indy (см. ниже).



Структура модуля



5.2.2. Структура модуля

Модули - это программные единицы, предназначенные для размещений фрагментов программ. С помощью содержащегося в них программного кода реализуется вся поведенческая сторона программы. Любой модуль имеет следующую структуру [ Более точное описание структуры модуля приводится в п. 12.1. ]: заголовок секция интерфейсных объявлений секция реализации терминатор Заголовок открывается зарезервированным словом Unit за которым следует имя модуля и точка с запятой. Секция интерфейсных объявлений открывается зарезервированным словом Interface, a секция реализации - словом implementation. Терминатором модуля, как и терминатором программы, является end с точкой. Следующий фрагмент программы является синтаксически правильным вариантом модуля:

unit Unit1;

interface

// Секция интерфейсных объявлений

implementation

// Секция реализации

end.

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

Щелкните по закладке Unit1 окна кода, и вы увидите такой текст:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls,

For.gif" >




TColorGrid выбор или отображение цвета



18.7.2. TColorGrid - выбор или отображение цвета

Компонент предназначен для выбора и/или отображения цветов из 16-цветной палитры. Выбирать/отображать можно два цвета: основной и фоновый. Основной выбирается щелчком левой кнопки мыши и отображается символами fg, фоновый выбирается правой кнопкой и отображается символами bg (если оба цвета совпадают, соответствующая клетка таблицы помечается символами fb).

Свойства компонента:

property Back.gif" >
Содержание
Вперед




TMainMenu gif" >



18.1.2. TMainMenu.gif" >



TNotebook набор страниц



18.6.2. TNotebook - набор страниц

Многостраничный контейнер TNotebook обычно работает в паре с TTabSet и предназначен для размещения других компонентов на нескольких перекрывающих друг друга страницах (панелях).

Свойства компонента:

property ActivePage: Strings; Определяет имя верхней страницы блокнота
property Pagelndex: Integers; Содержит индекс верхней страницы блокнота
property Pages: TStrings; Содержит набор строк с именами страниц

Ключевым свойством является Pages. С помощью его методов Add, Delete, Find и т. д. можно добавлять и удалять страницы, отыскивать Нужную и т. д. (см. класс TStrings).

Для компонента определено событие

property OnChange: TNotifyEvent;

которое возникает при смене страницы.





TOpenPictureDialog и TSavePictureDialog



18.5.2. TOpenPictureDialog и TSavePictureDialog - диалоги открытия и сохранения изображений

Специализированные диалоги для открытия и сохранения графических файлов TOpenPictureDialog И TSavePictureDialog отличаются от

TOpenDialog и TSaveDialog двумя обстоятельствами. Во-первых, в них предусмотрены стандартные фильтры для выбора графических файлов (с расширениями bmp, ico, wmf и emf) . Во-вторых, в окна диалога включены панели для предварительного просмотра выбираемого файла.

На Рисунок 18.39 показано стандартное окно компонента TOpenPictureDialog.





TPaintBox окно для рисования



18.4.2. TPaintBox - окно для рисования

Назначение компонента TPaintBox - дать вам простое окно с канвой для рисования произвольных изображений. Канва содержится в свойстве Canvas компонента, графические инструменты - в свойствах Font, pen и Brush, а собственно рисование осуществляется в обработчике события OnPaint. Особенности использования этих инструментов см. в п. 16.4. Например, следующий обработчик создаст окно, показанное на Рисунок 18.35:



TSpeedButton кнопка для инструментальных панелей



18.2.2. TSpeedButton - кнопка для инструментальных панелей

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

Для фиксации кнопка должна быть отнесена к какой-либо группе кнопок (эта группа может состоять из нее одной - вариант одиночной фиксируемой кнопки). Для этого используется свойство GroupIndex: Integer, которое не должно быть равно 0. Поведение кнопки определяется логическим свойством AllowAllup: если это свойство имеет значение True, утопленная кнопка отпускается только при нажатии любой другой кнопки, входящей в ту же группу; если AllowAllup=False, кнопку можно освободить повторным щелчком. Индикатором состояния кнопки служит логическое свойство Down, которое имеет значение True, если кнопка утоплена. Свойство доступно для записи, что позволяет изменять состояние кнопки программно.

Для кнопки TSpeedButton предусмотрено событие onDbiciick, которое возникает при двойном щелчке на утопленной кнопке.



Указатели



7.4.2. Указатели

Оперативная память ПК представляет собой совокупность ячеек для хранения информации - байтов, каждый из которых имеет собственный номер. Эти номера называются адресами, они позволяют обращаться, к любому байту памяти. Object Pascal предоставляет в распоряжение программиста гибкое средство управления динамической памятью - так называемые указатели. Указатель - это переменная, которая в качестве своего значения содержит адрес байта памяти. С помощью указателей можно размещать в динамической памяти любой из известных в Object Pascal типов данных. Лишь некоторые из них (Byte, Char, ShortInt, Boolean) занимают во внутреннем представлении один байт, остальные - несколько смежных. Поэтому на самом деле указатель адресует лишь первый байт данных.

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

var

p1 : ^Integer;

р2 : ^Real;

type

PerconPointer = "PerconRecord;

PerconRecord = record Name : String;

Job : String;

Next : PerconPointer ,

end;

Обратите внимание: при объявлении типа PerconPointer мы сослались на тип PerconRecord, который предварительно в программе объявлен не был. Как уже отмечалось, в Object Pascal последовательно проводится в жизнь принцип, в соответствии с которым перед использованием какого-либо идентификатора он должен быть описан. Исключение сделано только для указателей, которые могут ссылаться на еще не объявленный тип данных.

В Object Pascal можно объявлять указатель и не связывать его при этом с каким-либо конкретным типом данных. Для этого служит стандартный тип pointer, например:

var

р: Pointer;

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

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

Если, например,

var

pI1,pI2: ^integer;

pR: ^Real;

p: Pointer;

то присваивание

pI1 := pI2;

вполне допустимо, в то время как

pl1 :=pR;

запрещено, поскольку pI1 и pR указывают на разные типы данных. Это ограничение, однако, не распространяется на нетипизированные указатели, поэтому мы могли бы записать

p := pR;

pI1 := p;

и тем самым достичь нужного результата.



Условный оператор



5.4.2. Условный оператор

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

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

if <условие> then <оператор1> else <оператор2>;

где if/ then/ else - зарезервированные слова (если, то, иначе);

<условие> - произвольное выражение логического типа;

<оператор1>, <оператор2> - любые операторы языка Object Pascal.

Условный оператор работает по следующему алгоритму. Вначале вычисляется условное выражение <условие>. Если результат есть True (истина), то выполняется <оператор1>, а <оператор2> пропускается; если результат есть False (ложь), наоборот, <оператор1> пропускается, а выполняется <оператор2>. Например:

var

X, Y, Max: Integer;

begin .

if X > Max then

Y := Max else

Y := X;

….

end;

При выполнении этого фрагмента переменная y получит значение переменной х, если только это значение не превышает мах, в противном случае y станет равно мах.

Условными называются выражения, имеющие одно из двух возможных значений: истина или ложь. Такие выражения чаще всего получаются при сравнении переменных с помощью операций отношения =, <>, >, >=, <, <=. Сложные логические выражения составляются с использованием логических операций and (логическое И), or (логическое ИЛИ) и not (логическое НЕ). Например:

if (а > b) and (b <> 0) then ...

Примечание
Примечание

В отличие от других языков программирования в Object Pascal приоритет операций отношения меньше, чем у логинеёкйх" операции, по этому отдельные составные части сложного логического вьфажёния 5 заключаются в скобки. Например, такая запись предыдущего оператора будет неверной:

if a>b and b <> 0 then ...// Ошибка так как фактически (с учетом приоритета операции) компилятор будет транслировать такую строку:

if a>(b and b)<>0 then...

Часть else <оператор2> условного оператора может быть опущена. Тогда при значении True условного выражения выполняется <оператор1>, в противном случае этот оператор пропускается:

var

X, Y, Max: Integer;

begin

if X > Мах then Мах := X;

Y := X;

end;

В этом примере переменная y всегда будет иметь значение переменной х, а в мах запоминается максимальное значение X.

Поскольку любой из операторов <оператор1> и <оператор2> может быть любого типа, в том числе и условным, а в то же время не каждый из “вложенных” условных операторов может иметь часть else <оператор2>, то возникает неоднозначность трактовки условий. Эта неоднозначность в Object Pascal решается следующим образом:

любая встретившаяся часть else соответствует ближайшей к ней сверху по тексту программы части then условного оператора. Например:

var

a,b,c,d : Integer;

begin a := 1;

b := 2;

с := 3;

d := 4;

if a < b then // Да

if с < d then // Да

if с < 0 then // Нет

с := 0 // Этот оператор не выполняется

else

а : = b; // а равно 2

if а < b then // Да

if с < d then // Да

if с < 0 then // Нет

с := 0 // с равно 0

else // if с < О

else //if с < d

else // If a < b

а := b; // Этот оператор не выполняется

end;

Учебная программа INTTEST

Игра “Угадай число”: программа случайным образом выбирает целое число в диапазоне О... 1000 и запоминает его. Пользователь пытается угадать его и вводит свое число. Сравнив ввод с запомненным числом, программа сообщает - больше, меньше или равно введенное число запомненному. Ввод продолжается до угадывания, после чего программа предлагает сыграть еще раз.

Поскольку пользователь вводит только числа, изменим форму fmExample: как и в предыдущей программе intmult вместо компонента edinput типа TEdit поместим на форму одноименный компонент типа TMaskEdit. Выберите опцию File | New | Application, щелкните по компоненту edinput и удалите его с помощью клавиши Delete, затем поместите на его место компонент MaskEdit (страница Additional), назовите его edInput (свойство Name) и в его свойство

EditMask поместите строку

0999;1;

В секцию private описания класса fmExampie поместите объявление целочисленного поля х:

private

{ Private declarations }

X: Integer;

Для обработчика события OnActivate формы fmExampie Напишите такой код:

procedure TfmExample.For.gif" >




Задание названия раздела



21.3.2. Задание названия раздела

Название раздела используется в Help-службе следующим образом:

• оно появляется после активизации опции закладка в главном меню Help-службы;

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

На Рисунок 21.3 показано окно поиск справочной службы Delphi.



Записи



7.2.2. Записи

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

Структура объявления типа записи такова:

<имя типа> = record <сп.полей> end;

Здесь <имя типа> - правильный идентификатор; record/ end - зарезервированные слова {запись, конец); <сп.полей> - список полей; представляет собой последовательность разделов записи, между которыми ставится точка с запятой.

Каждый раздел записи состоит из одного или нескольких идентификаторов полей, отделяемых друг от друга запятыми. За идентификатором (идентификаторами) ставится двоеточие и описание типа поля (полей), например:

type

BirthDay = record Day, Month: Byte;

Year : Word end;

var

a,b : Birthday;

В этом примере тип BirthDay (день рождения) есть запись с полями Day, Month и Year (день, месяц и год); переменные а и в содержат записи типа BirthDay.

Как и в массиве, значения переменных типа записи можно присваивать другим переменным того же типа, например

а := b;

К каждому из компонентов записи можно получить доступ, если использовать составное имя, т. е. указать имя переменной, затем точку и имя поля:

a.day := 27;

b.year := 1939;

Для вложенных полей приходится продолжать уточнения:

type

BirthDay = record Day,Month: Byte;

Year : Word end;

var

с : record

Name : String;

Bd : BirthDay end;

begin

if c.Bd.Year = 1989 then ... end.

Чтобы упростить доступ к полям записи, используется оператор присоединения with:

with <переменная> do <оператор>;

Здесь with, do - зарезервированные слова (с, делать);

<переменная> - имя переменной типа запись, за которой, возможно,

следует список вложенных полей; <оператор> - любой оператор Object Pascal.

Например:

с.Bd.Month := 9;

Это эквивалентно

with c.Bd do Month := 9;

или with с do with Bd do Month := 9;

или with с, Bd do Month := 9;

Object Pascal разрешает использовать записи с так называемыми вариантными полями, например:

type

For.gif" >




ПУСТАЯ ФОРМА И ЕЕ МОДИФИКАЦИЯ



3.1. ПУСТАЯ ФОРМА И ЕЕ МОДИФИКАЦИЯ

Как уже говорилось, окно формы содержит проект Windows-окна программы. Важно помнить, что с самого начала работы над новой программой Delphi создает минимально необходимый код, обеспечивающий ее нормальное функционирование в Windows. Таким образом, простейшая программа готова сразу после выбора опции File | New | Application, и нам остается просто запустить програм-му. Однако до этого советую выполнить две важные вещи: создать собственный рабочий каталог (папку) и нужным образом настроить Delphi.



РАЗМЕЩЕНИЕ НОВОГО КОМПОНЕНТА



3.2. РАЗМЕЩЕНИЕ НОВОГО КОМПОНЕНТА

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

Попробуем таким способом включить в окно программы компонент Label (Метка), предназначенный для размещения различного рода надписей. Убедитесь в том, что в палитре компонентов выбрана страница Standard, и щелкните мышью по кнопке (эта кнопка отображает компонент Label в палитре компонентов). Теперь щелкните мышью по форме так, чтобы компонент появился на форме и располагался левее и выше ее центра (Рисунок 3.1). Первоначальные размеры и положение компонента на форме легко изменяются мышью, поэтому добиваться полного сходства с рисунком необязательно.

Новый компонент имеет стандартное имя Label1, и надпись на нем повторяет это имя. Изменим эту надпись: с помощью строки Caption окна Инспектора объектов введите надпись: я программирую на Delphi. Как только вы начнете вводить новую надпись, вид ком-понента на форме начнет меняться, динамически отражая все изменения, производимые вами в окне Инспектора объектов.

Выделим надпись цветом и сделаем ее шрифт более крупным. Для этого щелкните мышью по свойству Font окна Инспектора объектов и с помощью кнопки в правой части строки раскройте диалоговое окно настройки шрифта. В списке size (Размер) этого окна выберите высоту шрифта 24 пункта [ Пункт - 1/72 дюйма, т. е. приблизительно 0,04 мм. Таким образом, 24 пункта означает высоту шрифта чуть более 9 мм. ], а с помощью списка Color (Цвет) выберите нужный цвет (например, красный), после чего закройте окно кнопкой ок.



РЕАКЦИЯ НА СОБЫТИЯ



3.3. РЕАКЦИЯ НА СОБЫТИЯ

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



НЕКОТОРЫЕ ИТОГИ



3.4. НЕКОТОРЫЕ ИТОГИ

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

Процесс создания Delphi-программы разбивается на две фазы: фазу конструирования формы и фазу кодирования. Конструирование формы осуществляется с помощью выбора компонентов из палитры и размещения их на форме. Программист может перемещать любой размещенный на форме компонент и изменять его размеры с помощью мыши. Чтобы придать компоненту нужные свойства, используется страница Properties Инспектора объектов. Чтобы компонент мог откликаться на то или иное событие, программист должен создать обработчик события и указать его имя на странице Events Инспектора объектов. Обработчик события оформляется в виде процедуры, имеющей составное имя. Первая часть имени представляет собой имя класса для формы, вторая часть отделяется от первой точкой и может быть произвольной. Если Delphi автоматически формирует заготовку для обработчика, то вторая часть имени представляет собой объединение имени компонента и имени события без предлога On. Тело процедуры ограничено словами begin... end и состоит из отдельных предложений (операторов) языка Object Pascal. В конце каждого предложения ставится точка с запятой. Свойства компонента могут изменяться на этапе прогона программы.

Динамическое изменение свойств компонента



3.3.3. Динамическое изменение свойств компонента

Поскольку кнопка Button1 в нашей программе способна “звучать”, полезно изменить ее надпись: вместо умалчиваемой надписи Button1, которую автоматически формирует Delphi по имени компонента, назовем кнопку, например, “Звук”. Проще всего это сделать с помощью окна формы и Инспектора объектов, т. е. на этапе конструирования формы (для этого нужно просто изменить свойство caption компонента Button1 в окне Инспектора объектов), но для более полного знакомства с Delphi мы рассмотрим другой способ - динамического[ К сожалению, эта процедура работает не всегда: если ваш ПК не оснащен звуковой картой, динамик будет молчать. В этом случае вместо MessageBeep (MB_OK) напишите просто Веер. Изменения на этапе конструирования называются статическими, а в ходе прогона программы - динамическими. ] изменения надписи на этапе прогона программы. Для этого создадим обработчик события OnCreate (По созданию) для формы и изменим в нем это свойство.

Событие OnCreate возникает после создания windows-окна, но до появления этого окна на экране. Чтобы создать обработчик этого события, раскройте список компонентов в верхней части окна Инспектора объектов, выберите компонент For.gif" >




Интерфейсный модуль



13.4.3. Интерфейсный модуль

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

Unit Complx;

Interface

type

TComplex = record Re, Im: Real;

end;

function AddC(x, y: TComplex): TComplex; stdcall;

External 'Cmplx' index 1;

function SubC(x, y: TComplex): TComplex; stdcall;

External 'Cmplx' index 2;

function MulC(x, y: TComplex): TComplex; stdcall;

External 'Cmplx' index 3;

function DivC(x, y: TComplex): TComplex; stdcall;

External 'Cmplx' index 4;

Implementation end.

Такой интерфейсный модуль существенно упрощает разработку основной программы: в нашем примере он обеспечивает такой же интерфейс к библиотеке cmpix, как описанный выше модуль cmpix к своим объектам.

При обращении к подпрограммам DLL, написанным на других языках программирования, может оказаться, что внешнее имя подпрограммы содержит символы, которые не могут содержаться в правильном идентификаторе Delphi. Например, язык C++ разрешает использовать в идентификаторах символ “@”. В этом случае (а также если вы хотите переименовать экспортируемую из DLL подпрограмму) именуйте подпрограмму любым правильным с точки зрения Delphi идентификатором и укажите истинное имя подпрограммы после слова name. Например:

function MyFunction: WordBool; stdcall;

external 'MyDLL' name '_MyFunction@12'



Изменение свойств формы



3.1.3. Изменение свойств формы

Итак, первый и самый простой шаг в Delphi-программировании вами уже сделан: вами создана нормальная Windows-программа. Разумеется, эта программа не реализует придуманного вами алгоритма, онавообще ничего путного не умеет делать, но это не беда! Впереди много времени и эта толстая книга, в которой как раз и рассказывается о том, как заставить вашу программу делать что-нибудь стоящее.

Теперь попробуем разобраться с тем, что такое модуль. В первом приближении мы можем считать модулем самостоятельный раздел программы, в чем-то подобный главе в книге. Модуль создается каждый раз, когда вы создаете новую форму (в программе может быть и, чаще, бывает не одна, а несколько - иногда несколько десятков форм и связанных с ними модулей). При компиляции программы Delphi создает файлы с расширениями pas, dfm и оси для каждого модуля: pas-файл содержит копию текста из окна кода программы, в файле с расширением dfm хранится описание содержимого окна формы, а в оси-файле - результат преобразования в машинные инструкции текста из обоих файлов. Файлы dcu создаются компилятором и дают необходимую базу для работы компоновщика, который преобразует их в единый загружаемый файл с расширением ехе.

Попробуем модифицировать программу, например, изменим заголовок ее окна. По умолчанию (т. е. без каких-либо усилий с нашей стороны) заголовок окна совпадает с заголовком формы: For.gif" >




Элементы программы



5.2.3. Элементы программы

Элементы программы - это минимальные неделимые ее части, еще несущие в себе определенную значимость для компилятора. К элементам относятся:

зарезервированные слова; идентификаторы; типы; константы; переменные; метки; подпрограммы; комментарии.

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

Идентификаторы - это слова, которыми программист обозначает любой другой элемент программы, кроме зарезервированного слова, идентификатора или комментария. Идентификаторы в Object Pascal могут состоять из латинских букв, арабских цифр и знака подчеркивания. Никакие другие символы или специальные знаки не могут входить в идентификатор. Из этого простого правила следует, что идентификаторы не могут состоять из нескольких слов (нельзя использовать пробел) или включать в себя символы кириллицы (русского алфавита).

Типы - это специальные конструкции языка, которые рассматриваются компилятором как образцы для создания других элементов программы, таких как переменные, константы и функции. Любой тип определяет две важные для компилятора вещи: объем памяти, выделяемый для размещения элемента (константы, переменной или результата, возвращаемого функцией), и набор допустимых действий, которые программист может совершать над элементами данного типа. Замечу, что любой определяемый программистом идентификатор должен быть описан в разделе описаний (перед началом исполняемых операторов). Это означает, что компилятор должен знать тот тип (образец), по которому создается определяемый идентификатором элемент.

Константы определяют области памяти, которые не могут изменять своего значения в ходе работы программы. Как и любые другие элементы программы, константы могут иметь свои собственные имена. Объявлению имен констант должно предшествовать зарезервированное слово const (от англ. constants - константы). Например, мы можем определить константы const

Kbyte = 1024;

Mbyte = Kbyte*Kbyte;

Gbyte = 1024*Mbyte;

чтобы вместо длинных чисел

1048576 (1024*1024) и 1073741824

(1024*1024*1024) писать, соответственно, Mbyte и Gbyte. Тип константы определяется способом ее записи и легко распознается компилятором в тексте программы, поэтому программист может не использовать именованные константы (т. е. не объявлять их в программе явно).

Переменные связаны с изменяемыми областями памяти, т. е. с такими ее участками, содержимое которых будет меняться в ходе работы программы. В отличие от констант переменные всегда объявляются в программе. Для этого после идентификатора переменной ставится двоеточие и имя типа, по образу которого должна строиться переменная. Разделу объявления переменной (переменных) должно предшествовать слово var. Например:

var

inValue: Integer;

byValue: Byte;

Здесь идентификатор inValue объявляется как переменная типа integer, а идентификатор byValue - как переменная типа Byte. Стандартный (т. е. заранее определенный в Object Pascal) тип integer определяет четырехбайтный участок памяти, содержимое которого рассматривается как целое число в диапазоне от -2 147 483 648 до+2 147 483 647, а стандартный тип Byte - участок памяти длиной 1 байт, в котором размещается беззнаковое целое число в диапазоне от 0 до 255 4 .[ Все приводимые в книге сведения относительно диапазона возможных значений и объема памяти стандартных типов относятся к Delphi 32. Для 16-разрядной версии 1 эти величины имеют другие значения, например, тип Integer в версии 1 занимает 2 банта и имеет диапазон значении от -32 768 до+32 767. ]

Метки - это имена операторов программы. Метки используются очень редко и только для того, чтобы программист смог указать компилятору, какой оператор программы должен выполнятся следующим. Метки, как и переменные, всегда объявляются в программе. Разделу объявлений меток предшествует зарезервированное сло-во label (метка). Например:

label

Loop;

begin

Goto Loop;

// Программист требует передать управление

// оператору, помеченному меткой Loop. .....

// Эти операторы будут пропущены

Loор:

// Оператору, идущему за этой меткой,

.....

// будет передано управление

end;

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

В Object Pascal есть два сорта подпрограмм: процедуры и функции. Функция отличается от процедуры только тем, что ее идентификатор можно наряду с константами и переменными использовать в выражениях, т. к. функция имеет выходной результат определенного типа. Если, например, определена функция

Function MyFunction: Integer;

и переменная var

X: Integer;

то возможен такой оператор присваивания:

Х := 2*MyFunction-l;

Имя процедуры нельзя использовать в выражении, т. к. процедура не имеет связанного с нею результата:

Procedure MyProcedure;

X := 2*MyProcedure-l; // Ошибка!



Класс TBrush



16.4.3. Класс TBrush

Объекты класса TBrush (кисти) служат для заполнения внутреннего пространства замкнутых фигур.

Свойства класса:

property Bitmap: TBitmap; Содержит растровое изображение, которое будет использоваться кистью для заполнения. Если это свойство определено, свойства Color и Style игнорируются
property Color: TColor; Цвет кисти
property Handle: Integer; Дескриптор кисти. Используется при не посредственном обращении к API- функциям Windows
property Style: TBrushStyle; Стиль кисти (см. Рисунок 16.3)


Клавиатура в MSDOS и Windows



17.6.3. Клавиатура в MS-DOS и Windows

Следует заметить, что Windows значительно “строже” относится к использованию клавиатуры, чем MS-DOS. Это может вызывать проблемы при переносе игровых приложений, а также приложений, созданных с помощью FoxPro или Clipper, в среду Delphi.

Если вы захотите сохранить устоявшиеся приемы использования клавиатуры в новой разработке (а я настоятельно рекомендую сделать это), вам, возможно, придется перехватывать сообщения Windows, так как только таким способом программа сможет опознать факт нажатия на системные клавиши Alt, Tab, Shift и т. п. Нажатие на остальные клавиши можно анализировать с помощью перехвата сообщений от клавиатуры в обработчиках Опкеуххх формы при установленном значении True в ее свойство Keypreview. Например, пусть акселератор Alt+X используется в существующей программе для закрытия модального диалогового окна. Чтобы сконструированное вами окно закрывалось по этой команде, напишите для него такой Обработчик события OnKeyDown:

procedure TFor.gif" >




Множества



7.2.3. Множества

Множества - это наборы однотипных логически связанных друг с другом объектов. Характер связей между объектами лишь подразумевается программистом и никак не контролируется Object Pascal. Количество элементов, входящих в множество, может меняться в пределах от 0 до 256 (множество, не содержащее элементов, называется пустым). Именно непостоянством количества своих элементов множества отличаются от массивов и записей.

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

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

type

digitChar = set of '0'..'9';

digit = set of 0. .9;

var

sl,s2,s3 : digitChar;

s4,s5,s6 : digit;

begin

si = ['1', '2', '3'];

s2 = ['3', '2', '1'];

s3 = ['2', '3'];

s4 = [0..3, 6];

s5 = [4, 5];

s6 = [3..9];

end.

В этом примере множества si и s2 эквивалентны, а множество S3 включено в s 2 , но не эквивалентно ему.

Описание типа множества имеет вид:

<имя типа> = set of <базовый тип>;

Здесь <имя типа> - правильный идентификатор; set, of - зарезервированные слова (множество, из); <базовый тип> - базовый тип элементов множества, в качестве которого может использоваться любой порядковый тип, кроме Word, Integer, Longint, Int64.

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

Над множествами определены следующие операции:

* пересечение множеств; результат содержит элементы, общие для обоих множеств; например, s4*s6 содержит [3], s4*s5 -пустое множество (см. выше);

+ объединение множеств; результат содержит элементы первого множества, дополненные недостающими элементами из второго множества:

S4+S5 содержит [0,1,2,3,4,5,6];

S5+S6 содержит [3, 4, 5, 6, 7, 8, 9] ;

разность множеств; результат содержит элементы из первого множества, которые не принадлежат второму:

S6-S5 содержит [3,6,7,8,9];

S4-S5 содержит [0,1, 2, 3, 6] ;

= проверка эквивалентности; возвращает True, если оба множества эквивалентны;

<> проверка неэквивалентности; возвращает True, если оба множества неэквивалентны;

<= проверка вхождения; возвращает True, если первое множество включено во второе;

>= проверка вхождения; возвращает True, если второе множество включено в первое;

in проверка принадлежности; в этой бинарной операции первый элемент - выражение, а второй - множество одного и того же типа; возвращает True, если выражение имеет значение, принадлежащее множеству:

3 in s 6 возвращает True;

2*2 in si возвращает False.

Дополнительно к этим операциям можно использовать две процедуры.

include - включает новый элемент во множество. Обращение к процедуре:

Include(S,I)

Здесь s - множество, состоящее из элементов базового типа TSet Base; I - элемент типа TSetBase, который необходимо включить во множество.

exclude - исключает элемент из множества. Обращение:

Exclude(S,I)

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

Учебная программа PRIMSET

В следующем примере, иллюстрирующем приемы работы с множествами, реализуется алгоритм выделения из первой сотни натуральных чисел всех простых чисел[ Простыми называются целые числа, которые не делятся без остатка на любые другие целые числа, кроме 1 и самого себя. К простым относятся 1, 2, 3, 5, 7, 11, 13 и т. д.. ]. В его основе лежит прием, известный под названием “решето Эратосфена”. В соответствии с этим алгоритмом вначале формируется множество BeginSet, состоящее из всех целых чисел в диапазоне от 2 до N. В множество primerset (оно будет содержать искомые простые числа) помещается 1. Затем циклически повторяются следующие действия:

взять из BeginSet первое входящее в него число Next и поместить его В PrimerSet; удалить из BeginSet число Next и все другие числа, кратные ему, Т. е. 2*Next, 3*Next И Т.Д.

Цикл повторяется до тех пор, пока множество BeginSet не станет пустым.

Эту программу нельзя использовать для произвольного N, так как в любом множестве не может быть больше 256 элементов.

procedure TfmExample.bbRunClick(Sender: TObject);

// Выделение всех простых чисел из первых N целых

const

N = 255; // Количество элементов исходного множества

type

SetOfNumber = set of 1..N;

var

n1,Next,i: Word; // Вспомогательные переменные

BeginSet, // Исходное множество

PrimerSet: SetOfNumber; // Множество простых чисел

S : String;

begin

BeginSet := [2..N];

// Создаем исходное множество

PrimerSet:= [1]; // Первое простое число

Next := 2; // Следующее простое число

while BeginSet о [ ] do // Начало основного цикла

begin

nl := Next; //nl-число, кратное очередному простому (Next)

// Цикл удаления из исходного множества непростых чисел:

while nl <= N do

begin

Exclude(BeginSet, nl);

n1 := nl + Next // Следующее кратное

end; // Конец цикла удаления

Include(PrimerSet, next);

// Получаем следующее простое, которое есть первое

// число, не вычеркнутое из исходного множества

repeat

inc(Next)

until (Next in BeginSet) or (Next > N)

end;

// Конец основного цикла

// Выводим результат:

S := '1';

for i := 2 to N do

if i in PrimerSet then

S := S+', '+IntToStr(i);

mmOutput.Lines.Add(S)

end;

Перед тем как закончить рассмотрение множеств, полезно провести небольшой эксперимент. Измените описание типа SetOfNumber следующим образом:

type

SetOfNumber = set of 1..1;

и еще раз запустите программу из предыдущего примера. На экран будет выведено 1, 3, 5, 7

Множества BeginSet и PrimerSet состоят теперь из одного элемента, а программа сумела поместить в них не менее семи!

Секрет этого прост: внутреннее устройство множества таково, что каждому его элементу ставится в соответствие один двоичный разряд (один бит); если элемент включен во множество, соответствующий разряд имеет значение 1, в противном случае - 0. В то же время минимальной единицей памяти является один байт, содержащий 8 бит, поэтому компилятор выделил множествам по одному байту, и в результате мощность каждого из них стала равна 8 элементам. Максимальная мощность множества - 256 элементов. Для таких множеств компилятор выделяет по 16 смежных байт.

И еще один эксперимент: измените диапазон базового типа на 1..256. Хотя мощность этого типа составляет 256 элементов, при попытке компиляции программы компилятор сообщит об ошибке: Sets may have at most 256 elements (Множества могут иметь не более 256 элементов) т. к. нумерация элементов множества начинается с нуля независимо от объявленной в программе нижней границы. Компилятор разрешает использовать в качестве базового типа целочисленный тип-диапазон с минимальной границей 0 и максимальной 255 или любой перечисляемый тип не более чем с 256 элементами (максимальная мощность перечисляемого типа - 65536 элементов).



Одноименные методы



9.2.3. Одноименные методы

В отличие от остальных версий Delphi в версиях 4...6 появилась возможность в рамках одного класса иметь несколько одноименных методов. Описанный выше механизм перекрытия родительского метода одноименным методом потомка приводит к тому, что потомок “не видит” перекрытый родительский метод и может обращаться к нему лишь с помощью зарезервированного слова inherited. В Delphi 4 введено зарезервированное слово overload (перезагрузить), с помощью которого становятся видны одноименные методы как родителя, так и потомка.

При обнаружении одноименного метода компилятор Delphi предупреждает о том, что у класса уже есть аналогичный метод с дру гими параметрами. Для подавления сообщений объявление одноименного метода можно сопровождать зарезервированным словом reintrpduce (вновь ввести).

Примечание
Примечание

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

В следующем примере в классе TFor.gif" >




Операторы повторений



5.4.3. Операторы повторений

В языке Object Pascal имеются три различных оператора, с помощью которых можно запрограммировать повторяющиеся фрагменты программ.

Счетный оператор цикла FOR имеет такую структуру:

for <параметр цикла> := <нач_знач> to <кон знач> do <оператор>;

Здесь for, to, do - зарезервированные слова (для, до, выполнить);

<параметр_цикла> - переменная типа Integer (точнее, любого по-, рядкового типа, см. гл. 7); <нач_знач> - начальное значение - выражение того же типа; <кон_знач> - конечное значение - выражение того же типа; <оператор> - произвольный оператор Object Pascal.

При выполнении оператора for вначале вычисляется выражение <нач_знач> и осуществляется присваивание <параметр_цикла> := <нач_знач>. После этого циклически повторяется:

проверка условия <параметр_цикла> <= <кон_знач>; если условие не выполнено, оператор for завершает свою работу; выполнение оператора <оператор>; наращивание переменной <параметр_цикла> на единицу.

Учебная программа INTSLJMM

В качестве иллюстрации применения оператора for рассмотрим программу, осуществляющую ввод произвольного целого числа n и вычисление суммы всех целых чисел от 1 до N.

Для нового приложения (опция File | New | Application) соз дайте такой обработчик bbRunСlick:

procedure TfmExample.bbRunClick(Sender: TObject);

var

i,N,Sum : Integer;

begin

try // Преобразуем ввод с контролем правильности:

N := StrToInt(edInput.Text);

except // Следующие операторы выполняются, если есть ошибка ShowMessage('Ошибка ввода целого числа');

dinput.SelectAll; // Выделяем неверный ввод

Exit // Завершаем работу обработчика

end;

edInput.Text :=' ';

edinput.SetFocus;

Sum := 0; // Начальное значение Sum

for i := 1 to N

do // Цикл формирования суммы

Sum := Sum+i;

mmOutput.Lines.Add('Сумма всех целых чисел '+'в диапазоне 1...'+IntToStr(N)+' равна '+IntToStr(Sum));

end ;

Комментарий к программе

Прежде всего обратите внимание на операторы

try // Преобразуем ввод с контролем правильности:

N := StrToInt(edinput.Text);

except // Следующие операторы выполняются, если есть ошибка ShowMessage("Ошибка ввода целого числа');

edinput.SelectAll; // Выделяем неверный ввод

Exit // Завершаем работу обработчика

end;

С помощью зарезервированных слов try (попробовать), except (исключение) и end реализуется так называемый защищенный блок. Такими блоками программист может защитить программу от краха при выполнении потенциально опасного участка (подробнее см. п. 14.1). В отличие от предыдущих программ мы не изменили компонент edinput, поэтому пользователь может ввести в нем произвольный текст. Если этот текст не содержит правильное представление целого числа, попытка выполнить оператор

N := StrToInt(edInput.Text);

в обычной программе привела бы к аварийному завершению программы. Чтобы этого не произошло, мы защитили этот оператор, расположив его за try и перед except. Если ошибки нет, все операторы, стоящие за except и до end, пропускаются и обработчик нормально срабатывает. Если обнаружена ошибка, возникает так называемая исключительная ситуация (исключение) и управление автоматически передается оператору, стоящему за except, - начинается обработка исключения. Вначале с помощью стандартной процедуры ShowMessage мы сообщаем пользователю об ошибке[ Если вы запустите программу из среды Delphi, исключение будет сначала перехвачено средой и на экране появится сообщение на английском языке о характере и месте возникновения ошибки. В этом случае закройте окошко с сообщением и нажмите F9 - программа продолжит свою работу, и вы увидите окно процедуры ShowMessage. ], затем с помощью edInput. SeiectAll выделяем ошибочный текст в компоненте edinput и, наконец, с помощью вызова стандартной процедуры Exit аварийно завершаем работу обработчика (но не программы!).

Отметим также два обстоятельства. Во-первых, условие, управляющее работой оператора for, проверяется перед выполнением оператора <оператор>: если условие не выполняется в самом начале работы оператора for, исполняемый оператор не будет выполнен ни разу. Другое обстоятельство - шаг наращивания параметра цикла строго постоянен и равен (+1). Существует другая форма оператора:

for <пар_цик>: = <нач_знач> downto <кон_знач> do <оператор>;

Замена зарезервированного слова to на downto означает, что шаг наращивания параметра цикла равен (-1), а управляющее условие Приобретает вид <параметр__цикла> = <кон_знач>.

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

Sum := 0;

if N >= 0 then

for i := 1 to N do

Sum := Sum + i

else

for i := -1 downto N do

Sum := Sum + i ;

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

Оператор цикла WHILE с предпроверкой условия:

while <условие> do <оператор>;

Здесь while, do - зарезервированные слова {пока [выполняется условие], делать), <условие> - выражение логического типа; <оператор> - произвольный оператор Object Pascal.

Если выражение <условие> имеет значение True, то выполняется <оператор>, после чего вычисление выражения <условие> и его проверка повторяются. Если <условие> имеет значение False, оператор while прекращает свою работу.

Учебная программа EPSILON

Программа отыскивает так называемое “машинное эпсилон” -такое минимальное, не равное нулю вещественное число, которое после прибавления его к 1,0 еще дает результат, отличный от 1,0. Замечу, что для хранения и преобразования дробных чисел в Object Pascal предназначены так называемые вещественные типы (см. гл. 7). В учебной программе используется один из этих типов - Real, занимающий 8 смежных байт и представляющий дробные (вещественные) числа в диапазоне от 10- 324 до 10+ 308 с точностью 15... 16 значащих цифр 10 .

У читателя, привыкшего к непрерывной вещественной арифметике, может вызвать недоумение утверждение о том, что в дискретной машинной арифметике всегда существуют такие числа o<x<eps, что i,o+x°i,o. Дело в том, что внутреннее представление типа Real может дать “лишь” приблизительно 10 19 возможных комбинаций значащих разрядов в отведенных для него 8 байтах. Конечно же, это очень большое число, но оно несопоставимо с бесконечным множеством вещественных чисел. Аппроксимация бесконечного непрерывного множества вещественных чисел конечным (пусть даже и очень большим) множеством их внутреннего машинного представления, и приводит к появлению “машинного эпсилон”.

Для нового приложения (опция File I New I Application) создайте такой обработчик bbRunСlick:

procedure TfmExample.bbRunClick(Sender: TObject) ;

var

Epsilon: Real;

begin

Epsilon := 1;

while l+Epsilon/2>l do

Epsilon := Epsilon/2;

IbOutput.Caption := 'Машинное эпсилон = ' +FloatToStr(Epsilon)

end;

Комментарий к программе

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

var

X : Integer; begin

X := 4/2; // Ошибка!Вещественный результат нельзя

// присвоить целой переменной

end;

Стандартная функция FloatToStr преобразует вещественное число в строку символов.

Оператор цикла REPEAT... UNTIL с постпроверкой условия:

repeat <тело цикла> Until <условие>;

Здесь repeat, until - зарезервированные слова (повторять [до тех пор}, пока [не будет выполнено условие]); <тело_цикла> - произвольная последовательность операторов Object Pascal; <условие> - выражение логического типа.

Операторы <тело_цикла> выполняются хотя бы один раз, после чего вычисляется выражение <условие>: если его значение есть False, операторы <тело_цикла> повторяются, в противном случае оператор repeat... until завершает свою работу.

Обратите внимание: пара repeat... unti1 подобна операторным скобкам begin ... end, поэтому перед until ставить точку с запятой необязательно.

Замечу, что для правильного выхода из цикла условие выхода должно меняться внутри операторов, составляющих тело цикла while или repeat... until. Следующие циклы никогда не завершатся “естественным” способом:

while True do begin

end;

и

repeat

until False;

Для гибкого управления циклическими операторами for, while и repeat в состав Object Pascal включены две процедуры без параметров:

break - реализует немедленный выход из цикла; действие процедуры заключается в передаче управления оператору, стоящему сразу за концом циклического оператора;

continue - обеспечивает досрочное завершение очередного прохода цикла; эквивалент передачи управления в самый конец циклического оператора.

Введение в язык этих процедур практически исключает необходимость использования операторов безусловного перехода goto (см. ниже п. 5.4.5).



Определение ключевых слов



21.3.3. Определение ключевых слов

Help-служба позволяет искать разделы по связанным с ними ключевым словам. В диалоговом окне Поиск (см. выше Рисунок 21.3) предусмотрены строка (1) для ввода ключевых слов и возможность выбора их из списка (2). Для любого раздела можно назначить сколько угодно ключевых слов и наоборот - с любым ключевым словом можно связать сколько угодно разделов.

Для определения ключевого слова в начале раздела (до первого символа текста раздела) ставится сноска, помеченная латинской буквой “К” или “k”. Например: к открыть;текст файл;ASCII;текст

Все связанные с разделом ключевые слова помещаются в текст сноски и отделяются от “К” одним пробелом, а друг от друга символом “;”. Группы связанных по смыслу ключевых слов объединяются во фразы, которые отделяются друг от друга пробелами. Help-служба ищет и отображает в списке выбора названия всех разделов, ключевые слова которых перечислены в одной фразе. Например, если для приведенной выше сноски пользователь ввел слово файл, будут представлены названия разделов, связанных со словами файл, ASCII и текст.

Помимо основной таблицы ключевых слов в Help-службе может быть определена дополнительная таблица. Слова из дополнительной таблицы не показываются в окне Поиск. Их использование возможно только вмакрокомандах ALink и TestALink (СМ. П. 21.7). Для вставки ключевых слов в дополнительную таблицу используется сноска, помеченная латинской буквой “А”: А таблица/слово



Палитра компонентов



2.1.3. Палитра компонентов

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

Как и панель кнопок, палитра компонентов может настраиваться. Для этого используется специальный редактор, окно которого появляется на экране после щелчка правой кнопкой мыши на любой пиктограмме в палитре компонентов и выбора опции properties (Свойства) (Рисунок 2.5).

Нет смысла удалять какой-то из компонентов, а создавать новые мы с вами пока еще не умеем, поэтому я не рекомендую вам экспериментировать с редактором палитры. Тем не менее один совет все-таки дам. В стандартном наборе страниц палитры компонентов есть страница Samples, содержащая довольно часто используемые компоненты. В то же время ее закладка в палитре закрыта двумя небольшими кнопками “прокрутки” закладок палитры. Имеет смысл поменять ее местами с менее используемой страницей, например, со страницей ADO. Вы можете “перетащить” строку Samples в окне Pages редактора палитры вверх и “положить” ее на строку ADO. После такой перестановки закладка Samples станет доступна в любой момент. Если, к тому же, вы не планируете использовать в своих проектах технологию ADO для доступа к базам данных, перетащите строку ado в самый конец списка.



Полиморфизм



9.1.3. Полиморфизм

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

В Object Pascal полиморфизм достигается не только описанным выше механизмом наследования и перекрытия методов родителя, но и их виртуализацией (см. ниже), позволяющей родительским методам обращаться к методам своих потомков.



Секция WINDOWS



21.4.3. Секция WINDOWS

Секция [windows] определяет используемый в справочной службе набор дополнительных окон. Каждое указанное в секции окно характеризуется своим типом, цветом, размерами, заголовком. Только имена перечисленных в секции окон могут указываться в ссылках и сносках “>” RTF-файлов.

В строке create a window named следует задать имя окна. Замечу, что, если указать имя main, установки, производимые далее, будут относиться к основному окну справочной службы (именно таким способом мне, например, удалось получить нужный заголовок основного окна). С помощью списка Based on this standard window можно выбрать один из трех возможных стандартных типов окна:

procedure - окно предназначено для вывода текстов процедур; оно позиционируется в правом верхнем углу экрана и при значительной ширине может своим правым краем выйти за пределы экрана;

Reference - обычное справочное окно; позиционируется в левом верхнем углу, занимает приблизительно 2/3 экрана по высоте и ширине;

Error message - окно предназначено для вывода сообщений об ошибках, позиционируется по центру экрана, занимает почти всю высоту экрана и 3/4 его ширины.

Замечу, что все три типа создают стандартные Windows-окна с “толстой” рамкой и заголовком, т. е. их положение и размеры пользователь может изменять по своему усмотрению, так что выбор типа не носит решающего характера. Кроме того, с помощью кнопки Auto sizer на странице position (см. ниже) можно визуально настроить положение и размеры окна.

Страница General

window type - позволяет выбрать одно из ранее определенных окон; все дальнейшие установки на странице General будут осуществляться для указанного в этой строке окна; подобные строки есть на всех других страницах окна window Properties;

Add - вызывает окно Рисунок 21.8 для добавления нового окна к списку окон;

Remove - удаляет окно из списка;

include - включает ASCII-текстовьгй файл со списком окон;

Title bar text - определяет заголовок окна;

comment - содержит произвольный комментарий; здесь, например, можно указать функциональность окна; текст комментария не включается в результирующий файл;

Auto-size height - если переключатель выбран, окно автоматически изменяет высоту в зависимости от разрешения экрана;

Maximize window - окно максимизируется по размеру экрана;

Keep Help window on top - окно всегда появляется поверх остальных окон.

Страница Position определяет положение и размеры окна в момент его появления на экране. тор - отступ левого верхнего угла от верхнего края экрана;

Left - отступ левого верхнего угла от левого края экрана;

Height - высота окна;

width - ширина окна;

Adjust for user screen resolution - если переключатель выбран, координаты задаются относительно виртуального экрана с разрешением 1024х1024; если не выбран, координаты указываются в пикселях;

Auto-sizer - после щелчка по этой кнопке появляется окно с кнопками ОК и Cancel для визуальной настройки его размеров и положения;

Default position - после щелчка по этой кнопке окну задаются умалчиваемые размеры.

Страница Buttons

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

Contents - кнопка Содержание;

Index - кнопка Индекс;

Find - кнопка Поиск;

Help Topics - кнопка Разделы;

Print - кнопка Печать;

Back.gif" >




Создание окна просмотра



11.7.3. Создание окна просмотра

Наконец, на третьем этапе создается окно просмотра, т. е. собственно отображение данных в адресное пространство программы:

function MapViewOfFile(hFileMappingObject: THandle; dwDesiresAccess: DWord; dwFileOffsetHigh, dwFileIffsetLow, dwNumberOfBytesToMap: DWord): Pointer;

Здесь hFileMappingObject -дескриптор объекта отображения; dwDesiresAccess - определяет способ доступа к данным и может иметь одно из следующих значений: file_map_write - разрешает чтение и запись, При ЭТОМ В функции CreateFileMapping должен использоваться атрибут page_readwrite; file_map_read - разрешает только чтение, в функции CreateFileMapping должен использоваться атрибут

PAGE_READONLY или PAGE_READWRITE; FILE_MAP_ALL_ACCESS - тоь же, что и file_map_write; file_map_copy - данные доступны для записи и чтения, однако обновленные данные сохраняются в отдельной защищенной области памяти; в функции CreateFileMapping должен использоваться атрибут page_writecopy; dwFileOffsetHigh, dwFileIffsetLow -определяют соответственно старшие и младшие разряды смещения от начала файла, начиная с которого осуществляется отображение;

dwNumberOfBytesToMap - определяет длину окна отображения (0 - длина равна длине файла). Функция возвращает указатель на первый байт отображенных данных или nil, если обращение к функции оказалось неуспешным.



Создание вспомогательных методов



10.5.3. Создание вспомогательных методов

Несмотря на интенсивное использование классов TCompiexData и TCompiexVariantType, эти классы в конечном счете остаются скрытыми от пользователя нового варианта за счет набора вспомогательных методов, таких как VarComplexCreate, VarIsComplex, VarAsComplex и т. п., которые преобразуют обычные процедурные вызовы в вызовы методов и обращения к свойствам соответствующих классов.



Стандартные классы исключений



16.1.3. Стандартные классы исключений

В Delphi определены стандартные классы исключений, перечисленные в табл. 16.1. Именно эти имена, а также имена пользовательских классов (см. п. 16.1.5) могут использоваться в обработчиках исключении.

Таблица 16.1



Класс Родитель Обрабатываемое исключение
EAbort Exception Реализует “тихую” (без какого-либо сообщения) обработку любого исключения
EAbstractErrpr Exception Программа пытается вызвать абстрактный метод
EAccessViolation Exception Программа пыталась обратиться к не принадлежащей ей области памяти или использует недействительный указатель
EAppletException Exception Ошибка связана с созданием управляющих панелей в апплет-приложениях
EArrayError Exception Возникает из-за различного рода ошибок при работе с массивами (неверный индекс, попытка вставить элемент в массив фиксированной длины или в отсортированный массив и т. п.)
EAssertionFaild Exception Возбуждается отладочной процедурой Assert, когда тстируемое ею логическое выражение имеет значение False.
EBitsError Exception Программа пыталась обратиться к свойству Bits объекта TBits с индексом меньше нуля или больше максимально допустимого значения
EBrokerException Exception Объект-брокер не может найти сервер
ECacheError Exception Ошибка в наборе данных для компонента Tde-cisionCube
EClassNotFound EFilerError Для компонента, читаемого из потока данных, не найден соответствующий класс. Обычно возникает"в случае, когда в форму вставлен нестандартный компонент, а в библиотеке компонентов Delphi нет связанного с ним класса
ECommonCalendar-Error Exception Возникает в объектах класса TCommonCalendar и его потомках, когда вводится неверная дата
EComponentError Exception Возникает при различных манипуляциях программы с компонентом (программа не может зарегистрировать компонент, переименовать его или когда для его работы требуется интерфейс СОМ, который компонентом не поддерживается)
EControlC Exception Возникает при нажатии Ctrl-C при работе приложения в режиме консолиЛ
EConvertError Exception Ошибка преобразования в функциях StrToint или StrToFloat
ECorbaDispatch Exception Возникает в программах, использующих технологию corba, при ошибках, связанных с несовпадением интерфейсов сервера и брокера данных
ECorbaException Exception Возникает в программах, использующих технологию CORBA
ECorbaUser-Exception ECorbaException Возникает как определяемая пользователем реакция на ошибки интерфейса
EDatabaseError Exception Возникает, когда компонент обнаруживает ошибку в базе данных
EDateTimeError Exception Возбуждается компонентом TDateTimePicker при попытке ввода неверной даты или времени
EDBClient EDatabaseError Ошибка связана с неправильной работой Tcli-entDataSet
EDBEditError Exception Возникает, когда компонент пытается использовать данные, несовместимые с заданной маской
EDBEngineError EDatabaseError Связана с ошибками BDE
EDimensionMar-Error Exception Возникает, когда используемый в кубе решений набор данных не имеет агрегатных полей
EDimIndexError Exception Связана с нарушением размерности массива данных для куба решений
EDivByZero EIntError Ошибка целочисленного деления на ноль
EDSWriter Exception Ошибка при подготовке провайдером пакета данных для набора данных
EExternal-Exception EStream-Error Возникла ошибка, код которой не является предопределенным в Delphi
EFCreateError EStream-Error Ошибка при создании файла. Например, попытка создать файл на устройстве, предназначенном только для чтения, или в несуществующем каталоге
EFilerError EStream-Error Программа пытается повторно зарегистрировать в потоке один и тот же класс
EFOpenError EStream-Error Ошибка открытия потока данных. Например, попытка открыть несуществующий файл
EHeapException Exception Ошибка связана с неправильными операциями над динамической памятью
ElBClientError ElBError Ошибка связана с функционированием IBX-клиента
ElBError EDatabaseError Общая ошибка технологии IBX
ElBInterbase-Error ElBError Ошибка связана с функционированием сервера в технологии IBX
EInOutError Exception Любая ошибка в файловых операциях. Поле ErrorCode объекта этого класса содержит код ошибки
EInterpreterError Exception Возникает, когда компонент класса TDataBlockinterpeter не может интерпретировать данные блока данных
EIntError Exception Любая ошибка в целочисленных вычислениях
EIntfCastError Exception Попытка недопустимого приведения типов в OLE-объектах
EIntOverflow EIntError Ошибка целочисленного переполнения: программа пытается присвоить целочисленной переменной значение, выходящее из 32-двоичных разрядов
EInva1i dArgument EMatchError Возбуждается математическими функциями при выходе аргумента из допустимого диапазона
EInvalidCast Exception Программа пытается осуществить недопустимое преобразование типов с помощью оператора as
EInvalidGraphic Exception Программа пытается загрузить в контейнер изображение из файла, который имеет недопустимый формат (допустимыми форматами являются растр, метафайл, курсор, пиктограмма)
EInvalidGraphic-Operation Exception Программа пытается выполнить недопустимую графическую операцию
EInvalidGrid-Operation Exception Программа пытается выполнить недопустимую операцию над таблицей (например, обратиться к несуществующему столбцу или РЯДУ)
EInvalidImage EFilerError Программа пытается прочитать ресурс изображения из файла, в котором этого ресурса нет
EInvalidOp EMatchError Ошибка в операциях с плавающей точкой (недопустимая инструкция, переполнение стека сопроцессора и т. п.)
EInvalidOpera-tion Exception Не имеющий окна компонент пытается выполнить операцию, требующую дескриптора окна
EInvalidPointer EHeap-Exception Попытка использовать недействительный указатель
EListError Exception Эта ошибка связана с неверными действиями программы по отношению к разного рода спискам. Например обращение к элементу списка с индексом меньше нуля или больше максимально допустимого
ELowCapacity-Error Exception Ошибка возникает при попытке выделения памяти на устройстве, у которого нет нужной свободной памяти.
EMatchError Exception Любая ошибка при выполнении вычислений с плавающей точкой.
EMenu.gif" >


Страница dbExpress



4.8.3. Страница dbExpress

7 компонентов, представленных на этой странице, поддерживают технологию dbExpress прямого доступа к некоторым промышленным серверам баз данных. Все компоненты страницы впервые введены в версии 6.



Страница WebServices



4.9.3. Страница WebServices

Компоненты этой страницы поддерживают технологию SOAP Simple Object Access Protocol) для создания служб Web. Служба Web - это программа, запускаемая сервером Web в ответ на клиентское требование. Служба должна подготовить отклик, который она возвращает серверу, а тот - клиенту.



TFontDialog диалог выбора шрифта



18.5.3. TFontDialog - диалог выбора шрифта

Компонент TFontDialog создает и обслуживает стандартное окно выбора шрифта (Рисунок 18.41). Свойство

TFontDialogDevice = (fdScreen, fdPrinter, fdBoth) ;

property Device: TFontDialogDevice;

определяет тип устройства, для которого выбирается шрифт:

fdScreen - экран; fdPrinter - принтер; fdBoth - шрифты, поддерживаемые и экраном, и принтером.



TImageList хранилище изображений



18.3.3. TImageList - хранилище изображений

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

Компонент не имеет собственной канвы и поэтому не может самостоятельно отображать хранимые в нем картинки, которые могут быть растрами (bmp) или пиктограммами (ico). Его метод Draw получает канву от другого компонента и рисует изображение в клиентской области этого компонента. В компоненте есть множество специальных свойств и методов, упрощающих обслуживание набора картинок. Для получения дополнительной информации обратитесь к встроенной справочной службе. Пример использования компонента см. в п. 18.2.13.



Тип датавремя



7.1.3. Тип дата-время

Тип дата-время определяется стандартным идентификатором TDateTime и предназначен для одновременного хранения и даты, и времени. Во внутреннем представлении он занимает 8 байт и подобно currency представляет собой вещественное число с фиксированной дробной частью: в целой части числа хранится дата, в дробной - время. Дата определяется как количество суток, прошедших с 30 декабря 1899 года, а время - как часть суток, прошедших с 0 часов, так что значение 36444,837 соответствует дате 11.10.1999 и времени 20:05. Количество суток может быть и отрицательным, однако значения меньшие -693594 (соответствует дате 00.00.0000 от Рождества Христова) игнорируются функциями преобразования даты к строковому типу.

Над данными типа TDateTime определены те же операции, что и над вещественными числами, а в выражениях этого типа могут участвовать константы и переменные целого и вещественного типов.

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

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



Function Date: TDateTime;

Function DateToStr(D: TDateTime): String;

Function DateTimeToStr(D: TDateTime): String ;

Function For.gif" >



TMaskEdit специальный редактор



18.2.3. TMaskEdit - специальный редактор

Специализированный редактор TMaskEdit предназначен для ввода текста, соответствующего некоторому шаблону, задаваемому свойством EditMask: String. Если это свойство не задано, TMaskEdit работает как обычный редактор TEdit. Свойство IsMasked: Boolean доступно только для чтения и содержит True, если строка шаблона задана. Свойство EditText: string содержит текст до наложения на него маски шаблона (т. е. то, что ввел пользователь), а свойство Text: String может (в зависимости от шаблона см. ниже) содержать либо исходный текст, либо результат наложения на него маски шаблона.

Шаблон состоит из трех частей, отделенных друг от друга символами “;”. Первая часть задает маску ввода, вторая - это символ “О” или “I”, определяющий, записывается ли в Text результат наложения маски или исходный текст (“О” - исходный текст). В третьей части указывается символ, который в окне редактора будет стоять в полях, предназначенных для ввода символов (текст в редакторе может содержать символы маски; например, для ввода семизначного номера телефона текст в начале ввода может выглядеть так: (095)ХХХ-ХХ-ХХ где доступные для ввода пользователя поля указаны символом “X” -последним символом в шаблоне).

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

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

Символ Поле...
L должно содержать букву

с может содержать любой символ

1 может содержать букву

0 должно содержать цифру

А должно содержать букву или цифру

9 может содержать цифру

а может содержать букву или цифру

# может содержать цифру, “+”, “-”

С должно содержать любой символ

Специальные символы:
\ Следующий символ - литерал. Позволяет вставить в маску литералы из символов описателей полей ввода и специальных символов
: На это место вставляется символ-разделитель Windows для часов, минут, секунд
/ На это место вставляется символ-разделитель Windows для полей даты
; Разделитель частей шаблона
! Подавляет все ведущие пробелы
> Все следующие за ним поля ввода преобразуют буквы к заглавным
< Все следующие за ним поля ввода преобразуют буквы к строчным
<> Отменяет преобразование букв

Примеры:

Маска Вид в редакторе Свойство EditText Свойство Text
(095)000-0000;0;х (095)ххх-хххх 123456 1234567
(095)0000000;1;х (095)ххх-хххх 7 12345 (095)1234567
(095)\0\00-0000;1; . (095)00.-.... 1234567 (095)0012345

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

Остальные свойства компонента повторяют соответствующие свойства TEdit. В частности, установка в свойство passwordchar любого символа, кроме #0, обеспечивает секретность ввода: в этом случае все вводимые в компоненте символы заменяются символом PasswordChar.



TMediaPlayer медиаплейер



18.4.3. TMediaPlayer - медиаплейер

Компонент TMediaPlayer представляет собой набор кнопок (Рисунок 18.36), предназначенных для управления различными мультимедийными устройствами (компакт-дисками, звуковыми картами и т. п.).



TPopupMenu gif" >



18.1.3. TPopupMenu.gif" >




TSpinButton спаренная кнопка



18.7.3. TSpinButton - спаренная кнопка

В отличие от компонента TUpDown (см. п. 18.3.7) компонент TSpinButton не связан с регулированием числовой величины и может использоваться просто как пара кнопок: верхняя (up) и нижняя (Down). Для компонента следует написать обработчики его событий onup-click и onDownclick, в которых реализуется реакция программы на щелчок по той или иной кнопке.

Рисунки на кнопках определяются свойствами upGlyph и DownGiyph. Каждый рисунок может содержать 1, 2 или 3 изображения: 1-е - для нормальной кнопки, 2-е - для запрещенной, 3-е - для нажатой.





TTabbedNotebook набор страниц с закладками


18.6.3. TTabbedNotebook - набор страниц с закладками

Компонент TTabbedNotebook представляет собой объединение TTabSet и TNotebook в готовый многостраничный блокнот с заклад-ками. В отличие от TTabSet закладки в TabbedNotebook могут располагаться в несколько рядов.

Свойства ActivePage, Pagelndex И Pages компонента совпадают c одноименными свойствами компонента TNotebook. Свойство property TabsPerRow: Integer; определяет количество закладок в одном ряду.

С помощью метода function GetIndexFor.gif" >

Умалчиваемые параметры



8.2.3. Умалчиваемые параметры

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

<имя>:<тип> = <значение>

Например,

Procedure P(a: array of Integer; S: String = '');

В этом случае два следующих обращения идентичны:

Р([1,2,3], ' ');

Р([1,2,3]);

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

Procedure P(a: array of Integer; S: String = '';

В: Integer = 0) ;

Допустимые обращения:

Р([1,2,3]);

Р([1,2,3], 'Строка');

Р(1,2,3],",1)



Вариантные массивыпараметры



8.3.3. Вариантные массивы-параметры

В Delphi 32 при передаче подпрограмме массивов переменной длины и размерности удобно использовать вариантные массивы (см. п. 7.4.3). В следующем примере с помощью функции GetAr-rayAverage определяется среднее арифметическое значение всех элементов вариантного массива произвольной длины и размерности не выше 5:

function GetArrayAverage (const V: Variant): Double;

{Возвращает среднее арифметическое значение массива произвольной длины и размерности или очень маленькую отрицательную величину, если V - не вариант или если его размерность больше 5} var

i,j,k,l,m: Integer;

Sum: Double;

NItem: Integer;

begin

Result := -1E-309;

if ((VarType(V) and VarArray) <> VarArray) or

(VarArrayDimCount(V) > 5) then Exit;

Sum := 0;

NItem := 0;

// Подсчитываем количество элементов массива

for k := 1 to VarArrayDimCount(V) do

NItem := NItem+VarArrayH'ighBound(V, k)-VarArrayLowBound(V,k) ;

// Подсчитываем сумму элементов case VarArrayDimCount(V) of

1: for i "VarArrayLowBound(V,1) to VarArrayHighBound(V,1) do

Sum := Sum+V[i] ;

2: for i =VarArrayLowBound(V,1) to VarArrayHighBound(V,1) do

for j :=VarArrayLowBound(V,2) to VarArrayHighBound(V,2) do

Sum := Sum+V[i,j] ;

3: for i: =VarArrayLowBound(V,1) to VarArrayHighBound(V,1) do

for j: =VarArrayLowBound(V,2) to VarArrayHighBound(V,2) do

for k: =VarArrayLowBound(V,3) to VarArrayHighBound(V,3) do

Sum := Sum+V[i,j,k] ;

4: for i: =VarArrayLowBound(V,1) to VarArrayHighBound(V,1) do

for j: =VarArrayLowBound(V,2) to VarArrayHighBound(V,2) do

for k :=VarArrayLowBound(V,3) to VarArrayHighBound(V,3) do

for l: =VarArrayLowBound(V,4) to VarArrayHighBound(V,4) do

Sum := Sum+V[i,j,k,1];

5: for i:=VarArrayLowBound(V,1) to VarArrayHighBound(V,1) do

for j :=VarArrayLowBound(V,2) to VarArrayHighBound(V,2) do

for k: =VarArrayLowBound(V,3) to VarArrayHighBound(V,3) do

for 1 :=VarArrayLowBound(V,4) to VarArrayHighBound(V,4) do

for m:= VarArrayLowBound(V,5) to VarArrayHighBound(V,5) do

Sum := Sum+V[i,j,k,1,m];

end;

Result := Sum/NItem

end;

В подобного рода подпрограммах ограничение на размерность вариантного массива определяется, как правило, количеством вариантов в предложении case.



Выделение и освобождение динамической памяти



7.4.3. Выделение и освобождение динамической памяти

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

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

var pI,pJ: ^Integer;

pR: ^Real;

begin

New (pI) ;

New (pR) ;

end;

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

pJ^ := 2; // В область памяти pJ помещено значение 2

pl^ := 2*pi; // В область памяти pR помещено значение 6.28

Таким образом, значение, на которое указывает указатель, т. е. собственно данные, размещенные в куче, обозначаются значком ^, который ставится сразу за указателем. Если за указателем нет значка ^ , то имеется в виду адрес, по которому размещены данные. Имеет смысл еще раз задуматься над только что сказанным: значением любого указателя является адрес, а чтобы указать, что речь идет не об адресе, а о тех данных, которые размещены по этому адресу, за указателем ставится ^ (иногда об этом говорят как о разыменовании указателя).

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

рR^ := Sqr(pR") + I^ - 17;

Разумеется, совершенно недопустим оператор

pR := Sqr(pR") + I^ - 17;

так как указателю pR нельзя присвоить значение вещественного выражения. Точно так же недопустим оператор

pR ^ := Sqr(pR) ;

поскольку значением указателя pR является адрес и его (в отличие от того значения, которое размещено по этому адресу) нельзя возводить в квадрат. Ошибочным будет и такое присваивание:

pR^' := pJ;

так как вещественным данным, на которые указывает pR, нельзя присвоить значение указателя (адрес).

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

Dispose(pJ);

Dispose(pR);

вернут в кучу память, которая ранее была закреплена за указателями pJ и pR (см. выше).

Замечу, что процедура Dispose (pPtr) не изменяет значения указателя pPtr, а лишь возвращает в кучу память, ранее связанную с этим указателем. Однако повторное применение процедуры к свободному указателю приведет к возникновению ошибки периода исполнения. Освободившийся указатель программист может пометить зарезервированным словом nil. Помечен ли какой-либо указатель или нет, можно проверить следующим образом:

const

pR: ^Real = NIL;

begin

if pR = NIL then

New (pR) ;

Dispose(pR) ;

pR := NIL;

end;

Никакие другие операции сравнения над указателями не разрешены.

Приведенный выше фрагмент иллюстрирует предпочтительный способ объявления указателя в виде типизированной константы с одновременным присвоением ему значения nil. Следует учесть, что начальное значение указателя (при его объявлении в разделе переменных) может быть произвольным. Использование указателей, которым не присвоено значение процедурой New или другим способом, не контролируется Delphi и вызовет исключение.

Как уже отмечалось, параметром процедуры New может быть только типизированный указатель. Для работы с нетипизированными указателями используются Процедуры GetMem И FreeMem:

GetMem(P, Size); // резервирование памяти;

FreeMem(P, Size); // освобождение памяти.

Здесь р - нетипизированный указатель; size - размер в байтах требуемой или освобождаемой части кучи.

Примечание
Примечание

Испoльзoвaние прцeдyp GetMem/FreeMemMem, как и вообще вся работа диамияесжой памятью, требует особой осторожности и тщателвного солюдения простого правила: освобождать нужно ровно столько пайти, сколько её было зарезервировано, и именно с того адреса, с которого она была зарезёрвирована.



Дополнительные возможности APIфункций



16.4.4.1. Дополнительные возможности API-функций

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

Некоторые текстовые функции API



type TLogFont = record

If Height: Integer;

IfWidth: Integer; IfEs-

capment: Integer; IfOri-

entation: Integer; IfWeight: Integer;

If Italic: Byte; IfUnder-

line: Byte; IfStrikeOut:

Byte; IfCharSet: Byte;

IfOutPrecision: Byte;

IfClipPrecision: Byte;

IfQuality: Byte; IfPitchAndFamily: Byte;

1fFaceName: PChar ;

end;

function CreateFont(Font:

TLogFont): hFont;

Создает новый шрифт на основе данных в параметре Font. Назначение полей структуры TLogFont см. после таблицы
function DrawText(DC:hDC; pText: PChar; varRect:'TRect; For.gif" >


СТРАНИЦА STANDARD



4.1. СТРАНИЦА STANDARD

На странице Standard палитры компонентов сосредоточены стандартные для Windows интерфейсные элементы, без которых не обходится практически ни одна программа.

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

MainMenu.gif" >