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

         

ТИПИЗИРОВАННЫЕ ФАЙЛЫ



11.4. ТИПИЗИРОВАННЫЕ ФАЙЛЫ

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

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

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

Function FilePos

(var F): Longint;

Возвращает текущую позицию в файле, т. е. номер компонента, который будет обрабатываться следующей операцией ввода-вывода
Function FileSize

(var F): Longint;

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

seek (FileVar, FileSize(FileVar));

Procedure Seek(var F; N: Longint) ; Смещает указатель файла F к требуемому компоненту: n - номер компонента файла (первый компонент файла имеет номер 0)
Procedure Read(var

F, VI,..., Vn) ;

Читает данные из типизированного файла f:

v< - переменные такого же типа, что и компоненты файла

Procedure

Write(var F,P1, ...,Pn)

Записывает данные в типизированный файл

р: Pi - выражения такого же типа, что и компоненты файла



НЕТИПИЗИРОВАННЫЕ ФАЙЛЫ



11.5. НЕТИПИЗИРОВАННЫЕ ФАЙЛЫ

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

При инициации нетипизированного файла процедурами Reset или Rewrite можно указать длину записи нетипизированного файла в байтах. Например, так:

var

F: File;

begin

AssignFile(F,'myfile.dat');

Reset(f,512);

end.

Длина записи нетипизированного файла указывается вторым параметром при обращении к процедурам Reset или Rewrite, в качестве которого может использоваться выражение типа Longint. Если длина записи не указана, она принимается равной 128 байтам.

Object Pascal не накладывает каких-либо ограничений на длину записи нетипизированного файла за исключением требования положительности и ограничения максимальной длины 2 Гбайт (для Delphi 1 длина записи ограничивается 65535). Для обеспечения максимальной скорости обмена данными рекомендуется задавать длину, которая была бы кратна длине физического сектора дискового носителя информации (512 байт). Однако операции обмена данными с дисковыми устройствами в среде Windows кэшируются, т. е. осуществляются через промежуточный буфер памяти, поэтому обычно задают Recsize = 1, что позволяет обмениваться с файлом блоками любой длины начиная с одного байта.

При работе с нетипизированными файлами могут применяться все процедуры и функции, доступные типизированным файлам, за исключением Read и write, которые заменяются соответственно высокоскоростными Процедурами BlockRead И BlockWrite:

Procedure BlockRead(var F: File; var Buf; Count: Integer [;

var AmtTransferred: Integer]) ;

Procedure BlockWrite(var F: File; var Buf; Count: Integer [;

var AmtTransferred: Integer]);

Здесь Buf - буфер: имя переменной, которая будет участвовать в обмене данными с дисками; count - количество записей, которые должны быть прочитаны или записаны за одно обращение к диску;

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

За одно обращение к процедурам может быть передано до count*RecSize байт, где RecSize - длина записи нетипизированного файла. Передача идет начиная с первого байта переменной Buf. Программист должен позаботиться о том, чтобы длина внутреннего представления переменной Buf была достаточной для размещения всех count*Rec3ize байт при чтении информации с диска. Если при чтении указана переменная недостаточной длины или если в процессе записи на диск не окажется нужного свободного пространства, возникнет ошибка ввода-вывода, которую можно заблокировать, указав необязательный параметр AmtTransferred.

После завершения процедуры указатель смещается на count записей. Процедурами Seek, FilePos И FileSize можно обеспечить доступ к любой записи нетипизированного файла.



СРЕДСТВА WINDOWS ДЛЯ РАБОТЫ С ФАЙЛАМИ



11.6. СРЕДСТВА WINDOWS ДЛЯ РАБОТЫ С ФАЙЛАМИ

Операционная система Windows имеет собственные средства работы с файлами, которые становятся доступны программе Delphi после ссылки на модуль Windows. Поскольку файловые средства Object Pascal реализуют подавляющее большинство программных запросов, в табл. 11.4 приводится лишь краткая информация о назначении соответствующих API-функций. За подробной информацией обращайтесь к справочной службе в файлах WIN32. hlp или WIN32SDK.HLp (для версии б

Эти файлы расположены В каталоге Programs Files | Common Files |

Borland Share | MSHelp).

Таблица 11.4. Средства Windows для работы с файлами

AreFileApisANSI Определяет, будут ли файловые операции использовать кодовую страницу ansi
CopyFile Копирует содержимое одного файла в другой
CreateDirectory Создает новый каталог на диске Создает новый каталог на диске
CreateDirectoryEx Создает новый или открывает существующий файл
CreateFile Связывает асинхронный ввод/вывод с файлом, что дает возможность получить извещение о завершении асинхронной операции
CreateIoCompletionPort Определяет, переопределяет или уничтожает определение логического устройства ms-dos
DefineDosDevice DeleteFile Уничтожает файл (в табл. 8.1 указан более удобный интерфейс вызова этой API-функции) операций
FileIOCompletionROutine Связывает асинхронный ввод/вывод с подпрограммой для слежения за окончанием асинхронных
FindClose Освобождает память, выделенную функциям Find FirstFile - FindNextFile
FindCloseChangeNotification Освобождает память, выделенную функциям Find-FirstChangeNotification FindNextChangeNotification
FindFirstChangeNotification Требует от Windows известить программу об изменении состояния каталога
FindFirstFile Ищет первый файл из группы файлов
FindNextChangeNotifi-

cation

Требует от Windows известить программу об очередном изменении состояния каталога
FindNextFile Ищет следующий файл
FlushFileBuffers Очищает файловый буфер
GetBinaryType Определяет, является ли файл исполняемым и, если является, возвращает его тип
GetCurrentDirectory Возвращает умалчиваемый каталог
GetDiskFreeSpace Возвращает свободное дисковое пространство в байтах
GetDriveType Возвращает тип диска (сменный, удаленный и т. п.)
GetFileAttributes Возвращает атрибуты файла
GetFileInformationBy Handle Возвращает системную информацию о файле
GetFileSize Возвращает размер файла в байтах
GetFileType Возвращает тип файла
GetFullPathName По короткому имени файла в формате ms-dos и windows 16 возвращает его полное имя в формате windows 32
GetLogicalDrives Возвращает битовую 32-разрядную маску, определяющую текущий диск
GetLogicalDriveStrings Возвращает список всех дисков, зарегистрированных в Windows
GetQueuedCompletion Status Требует от Windows выполнения асинхронного ввода/вывода и приостанавливает работу программы до завершения операций
GetShortPathName Возвращает короткое имя файла в формате MS-DOS^Windows 16)
GetSystemDirectory Возвращает имя системного каталога Windows для размещения библиотек, драйверов, шрифтов и т. п.
GetTempFileName Возвращает уникальное имя файла для временного хранения данных
GetTempPath Возвращает маршрут поиска каталога, предназначенного для хранения временно используемых файлов
Ge tVolumeIn fo rmat ion Возвращает информацию о файловой подсистеме в целом и об указанном каталоге
GetWindowsDirectory Возвращает полное имя каталога Windows для размещения прикладных программ, файлов инициализации, файлов помощи и т. п.
LockFile Защищает файл от доступа к нему из других программ
LockFileEx Устанавливает способ использования файла другими программами
MoveFile Переименовывает файл или каталог (с подкаталогами)
MoveFileEx Переименовывает файл
OpenFile Открывает существующий файл
QueryDosDevice Получает информацию об именах дисков (устройств), используемых в MS-DOS
ReadFile Читает данные из файла
ReadFileEx Реализует асинхронное чтение данных из файла
RemoveDirectory Удаляет пустой каталог
SearchPath Ищет файл в заданном каталоге (каталогах)
SetCurrentDirectory Устанавливает умалчиваемый каталог
SetEndOfFile Перемещает файловый указатель в конец файла
SetFileApisToANSI Предписывает Windows использовать кодовую страницу

ANSI при файловых операциях

SetFileApisToOEM Предписывает Windows использовать кодовую страни .

MS-DOS при файловых операциях

SetFileAttributes Устанавливает атрибуты файла
SetFilePointer Перемещает файловый указатель на нужную позицию
SetHandleCount Устанавливает количество файлов, одновременно используемых программой
SetVolumeLabel Устанавливает новую метку тома (носителя информации)
UnlockFile Снимает с файла защиту, установленную функцией LockFile
UnlockFileEx Снимает с файла защиту, установленную функцией LockFileEx
WriteFile Записывает данные в файл
WriteFileEx Реализует асинхронную запись в файл


Создание/открытие файла



11.7.1. Создание/открытие файла

Вначале файл создается обращением к функции

function FileCreate(FileName: String): Integer;

или открывается с помощью

function FileOpen(const FileName:

String; Mode: LongWord): Integer;

В обеих функциях FileName - имя файла, возможно, с маршрутом доступа. Параметр Mode определяет режим доступа к файлу и может принимать одно из следующих значений: fmOpenRead - только чтение; fmOpenWrite - только Запись; fmOpenReadWrite - чтение и запись. с помощью операции or эти константы можно комбинировать с одной из следующих регулирующих совместный доступ к файлу нескольких Программ: fmShareExclusive - совместный доступ Запрещен; fmShareDenyWrite - Другим Программам запрещается запись; fmShareDenyRead - другим программам запрещается чтение; fmSchareDenyNone - совместный доступ неограничен. Обе функции возвращают дескриптор созданного (открытого) файла или 0, если операция оказалась неуспешной.



ОТОБРАЖЕНИЕ ФАЙЛОВ В ПАМЯТЬ



11.7. ОТОБРАЖЕНИЕ ФАЙЛОВ В ПАМЯТЬ

Для работы с файлом динамической подкачки страниц виртуальной памяти в Windows 32 используется механизм отображения файлов в адресное пространство программы. Соответствующие функции API доступны любой программе и могут применяться к любому файлу (кстати, таким способом загружается в адресное пространство процесса исполняемый файл). В результате отображения программа может работать с файловыми данными как с данными, размещенными в динамической памяти. Такая возможность не только в большинстве случаев повышает скорость работы с данными, но и предоставляет программисту уникальные средства обработки сразу всех записей файла. Например, он может единственным оператором проверить входит ли заданный образец поиска в любую строку текстового файла. Отображение файла осуществляется в три приема.



ОБЪЕКТНАЯ МОДЕЛЬ РАБОТЫ С ФАЙЛАМИ



11.8. ОБЪЕКТНАЯ МОДЕЛЬ РАБОТЫ С ФАЙЛАМИ

В Delphi используется абстрактный класс TStream (поток данных), который является основой для работы с файлами как с объектами. В случае объектов совершенно не важно, что именно является носителем информации - дисковый ли файл, ленточный носитель или оперативная память. В специализированных потомках TStream определены стандартные методы Read, write и seek, открывающие полный доступ к файловому объекту. Сам объект создается конструктором и уничтожается деструктором.

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

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

В следующем примере файл с именем, хранящимся в Editl.Text,

копируется В файл Edit2 . Text.

procedure TFor.gif" >



TComboBox раскрывающийся список выбора



18.1.11. TComboBox - раскрывающийся список выбора

Комбинированный список TComboBox представляет собой комбинацию списка TListBox и редактора TEdit, и поэтому большинство его свойств и методов заимствованы у этих компонентов. Существуют пять модификаций компонента, определяемые его свойством style:

csSimple, csDropDown, csDropDownList, csOwnerDrawFixed И csOwner DrawVariabie. В первом случае список всегда раскрыт, в остальных он раскрывается после нажатия кнопки справа от редактора (Рисунок 18.7). В модификации csDropDownList редактор работает в режиме отображения выбора и его нельзя использовать для ввода новой строки (в других модификациях это возможно). Модификации csOwnerDrawFixed и csOwnerDrawVariable используются программной прорисовки элементов списка. Используемые для этого свойства и методы полностью совпадают со свойствами и методами TListBox аналогичного назначения.

Фактически “своими” у компонента являются лишь свойства и события, связанные с раскрытием списка:

property DropDownCount: Integer;

property DroppedDown: Boolean;

property OnDropDown: TNotifyEvent;



TMonthCalendar календарь



18.3.11. TMonthCalendar - календарь

Как видно из рисунка слева, компонент предназначен для выбора или отображения даты. Он очень похож на календарь, который появляется В компоненте TDateTimePicker (при значении dmComboBox В свойстве DateMode), но в отличие от последнего может отображать одновременно несколько смежных месяцев - в зависимости от своих размеров.

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



property CalColors: TMonthCalColors; С компонентом связан объект класса

TMonthCalColors, имеющий такие свойства:Back.gif" >



TSplitter компонент для изменения размеров



18.2.11. TSplitter - компонент для изменения размеров

Компонент TSplitter предназначен для ручного (с помощью мыши) управления размерами контейнеров TPanel1, TGroupBox или подобных им во время прогона программы. Визуально он представляет собой небольшую вертикальную или горизонтальную полосу, располагающуюся между двумя соседними контейнерами или на “свободной” стороне одного их них.

Непременным условием правильной работы компонента является выравнивание контейнера (контейнеров), размерами которого (которых) он управляет, вдоль одной из сторон окна или охватывающего контейнера. Для примера на Рисунок 18.14 показаны две панели, разделенные компонентом TSpiitter. Нижняя панель имеет Align = alBottom, верхняя в этом случае может иметь выравнивание alBottom или alciient. Между ними помещен TSplitter с выравниванием alBottom.

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

property Beveled: Boolean; Управляет трехмерным изображением компонента. Если False, компонент виден как узкая полоска фона между разделяемыми им компонентами него
NaturalNumber = 1..High(Integer) ; Содержит минимальный размер любого из компонентов, которые разделяет TSplitter.
property MinSize: Natural-Number; Если выравнивание aiLeft или aiRight - минимальная ширина компонента слева и справа от TSplitter, еСЛИ alTop или alBottom -минимальная высота компонента выше или ниже отнего

Для компонента определено событие onMoved, которое вызывается при любом перемещении компонента мышью.



СТРУКТУРА МОДУЛЕЙ



12.1. СТРУКТУРА МОДУЛЕЙ

Модуль имеет следующую структуру:

Unit <имя>;

interface

<интерфейсная часть> implementation

<исполняемая часть> initialization < нициирующая часть> finalization <завершающая часть>

end.

Здесь unit - зарезервированное слово (единица); начинает заголовок модуля; <имя> - имя модуля (правильный идентификатор); interface - зарезервированное слово (интерфейс); начинает интерфейсную часть модуля; implementation - зарезервированное слово (выполнение); начинает исполняемую часть; initialization -зарезервированное слово (инициация); начинает инициирующую часть модуля; finalization - зарезервированное слово (завершение);

начинает завершающую часть модуля; end - зарезервированное слово - признак конца модуля.

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



ЗАГОЛОВОК МОДУЛЯ И СВЯЗЬ МОДУЛЕЙ ДРУГ С ДРУГОМ



12.2. ЗАГОЛОВОК МОДУЛЯ И СВЯЗЬ МОДУЛЕЙ ДРУГ С ДРУГОМ

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

Unit Global;

то исходный текст соответствующего модуля должен размещаться в дисковом файле global. pas. Имя модуля служит для его связи с другими модулями и основной программой. Эта связь устанавливается специальным предложением

Uses <сп.модулей>

Здесь uses - зарезервированное слово (использует); <сп.модулей> -список модулей, с которыми устанавливается связь; элементами списка являются имена модулей, отделяемые друг от друга запятыми, например:

Uses Windows, SysUtils, MyUnit;

Если объявление uses используется, оно должно открывать раздел описаний основной программы. Модули могут использовать другие модули. Предложение uses в модулях может следовать либо сразу за зарезервированным СЛОВОМ interface, либо Сразу за словом implementation, либо, наконец, и там, и там (т. е. в модуле допускаются два предложения uses).



ИНТЕРФЕЙСНАЯ ЧАСТЬ



12.3. ИНТЕРФЕЙСНАЯ ЧАСТЬ

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

Unit Cmplx;

interface type

Complex = record

re,im: Real end;

Function AddC(x,y: Complex): Complex;

Function MulC(x,y: Complex): Complex;

Если теперь в другом модуле написать предложение Uses Cmplx; то в нем станут доступными тип Сomplex и две процедуры - AddС и МulС из модуля Cmplx.



ИСПОЛНЯЕМАЯ ЧАСТЬ



12.4. ИСПОЛНЯЕМАЯ ЧАСТЬ

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

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

Unit Cmplx;

Interface type

Complex = record

re,im: real

end;

Function AddC(x,y: Complex): Complex;

Function MulC(x,y: Complex): Complex;

Implementation

Function AddC(x,y: Complex): Complex;

begin

end; Function MulC;// Вариант описания подпрограммы без

// повторения списка параметров

begin

end;

end.

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

Хотя допускается краткое объявление заголовка подпрограммы ( как в предшествующем примере—функции Mul(), тем не менее использовать такую форму в серьезной программе не рекомендуется: перечень параметров непосредственно в заголовке подпрограммы облегчает чтения кода и понимания деталей реализации алгоритма.

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

Function AddC(x,z: Complex): Complex; begin

end;

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



ИНИЦИИРУЮЩАЯ И ЗАВЕРШАЮЩАЯ ЧАСТИ



12.5. ИНИЦИИРУЮЩАЯ И ЗАВЕРШАЮЩАЯ ЧАСТИ

Инициирующая и завершающая части чаще всего отсутствуют

Вместе с начинающим их словами initialization и finalization.

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



ДОСТУП К ОБЪЯВЛЕННЫМ В МОДУЛЕ ОБЪЕКТАМ



12.6. ДОСТУП К ОБЪЯВЛЕННЫМ В МОДУЛЕ ОБЪЕКТАМ

Пусть, например, мы создаем модуль, реализующий арифметику комплексных чисел (такая арифметика ни в стандартном Паскале, ни в Object Pascal не предусмотрена, но в Delphi 6 введен пользовательский вариант, который реализует действия над комплексными

Числами - см. п. 10.5 и модуль Source\Rtl\Common\VarCmplx.pas Каталога размещения Delphi). Арифметика комплексных чисел реализуется четырьмя функциями:

Unit Cmplx;

//---------------------------

Interface

//---------------------------

type

Complex = record

re,im: real end; Function AddC (x,y: Complex): Complex;

Function SubC (x,y: Complex): Complex;

Function MuiC (x,y: Complex): Complex;

Function DivC (x,y: Complex): Complex;

const

с : Complex = (re : 0.1; im : -1);

//---------------------------

Implementation

//---------------------------

Function AddC (x,y: Complex): Complex;

// Сложение комплексных чисел

begin

Result.re := x.re + y.re;

Result.im := x.im + y.im

end; //AddC

Function SubC (x,y: Complex): Complex;

// Вычитание комплексных чисел

begin

Result.re := x.re - y.re;

Result.im := x.im - y.im

end; //SubC

Function MulC (x,y: Complex): Complex;

// Умножение комплексных чисел

begin

Result.re := x.re * y.re - x.im * y.im;

Result.im := x.re * y.im + x.im * y.re

end; //MulC

Function DivC (x,y: Complex): Complex;

// Деление комплексных чисел

var

z: Real;

begin

z := sqr(y.re) + sqr(y.im);

// Защищаем программу от краха в случае, когда z=0:

try- Result, re := (x.re * у.re + x.im * y.im) / z;

Result.im := (x.re * y.im - x.im * y.re) / z;

except

Result.re := l.le309;

Result.im := l.le309;

end

end

{Div.C};

end.

Чтобы создать такой модуль, следует вызвать опцию File | New I unit[ В Delphi 1 для этого используется опция File | New | Unit, в версиях 2...5 - опция File |

New и выбор пиктограммы на закладке New окна Репозитория. ]. Текст модуля следует сохранить в файле cmplx.pas: имя файла должно совпадать с именем модуля - только в этом случае Delphi сможет автоматически найти модуль и следить за его обновлением.

После создания модуля его имя нужно упомянуть в предложении uses того модуля, в котором будут использоваться вновь созданные подпрограммы, типы, константы (в нашем модуле - тип complex, подпрограммы Addc, subc. Mule, Dive и константа с). Пусть, например, при каждом щелчке по кнопке bbRun учебной программы создается пара случайных комплексных чисел, над которыми осуществляются все четыре арифметических действия. Тогда обработчик bbRunClick мог бы быть таким:

implementation

uses Cmplx;

{$R *.DFM}

procedure Tform1.bbRunClick(Sender: TObject);

var

x,y,z: Complex;

procedure Output(Operation: Char);

//Осуществляет нужное действие и выводит результат в mmOutput

var

S: String;

begin

case Operation of

'+': z := AddC(x,y) ;

'-': z := SubC(x,y) ;

'*': z := MulC(x,y) ;

'/': z := DivC(x,y) ;

end;

S := '('+For.gif" >




ТИПЫ МОДУЛЕЙ В DELPHI



12.7. ТИПЫ МОДУЛЕЙ В DELPHI

Наиболее распространенным типом модуля в Delphi является форма - модуль со связанным с ним окном. Интерфейсная часть такого модуля обычно содержит объявление нового класса и автоматически обновляется Delphi в ходе конструирования окна. В интерфейсной части модуля-формы содержится также объявление объекта для соответствующего оконного класса. Например, для нашей учебной программы модуль содержит объявление класса TfmExamie и объекта fmExampie. Большинство типовых модулей в репозитории содержат заготовки для создания диалоговых окон.

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

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

Модули динамических библиотек предназначены для создания широко используемых в Windows динамически связываемых библиотек DLL (Dynamic-Link Libraries). DLL служат универсальным средством согласования подпрограмм, написанных на разных языках программирования. В Windows содержится множество DLL, написанных на языке Си или на языке ассемблера, что ничуть не мешает Delphi-программам использовать их. Модули динамических библиотек предназначены для разработки DLL с помощью Object Pascal. Такие DLL затем смогут использовать программы, созданные с помощью других языков программирования.

Пакеты - это особым образом откомпилированные DLL, оптимизированные для совместного использования Delphi-программами, или средой Delphi, или и программами, и средой. В отличие от DLL пакеты могут хранить и передавать программе типы (включая классы) и данные. Они разработаны специально для хранения компонентов, разного рода экспертов, редакторов сложных свойств и т. п. Например, в пакете VCL60 .bpl содержатся основные компоненты Delphi.

Модули потоков предназначены для реализации так называемых потоков команд[ В Delphi существуют также потоки данных - см.п. 11.4. ] - фрагментов программы, которые исполняются параллельно с другими фрагментами, разделяя с ними время процессора и остальные системные ресурсы. Механизм потоков используется в 32-разрядных Windows и не поддерживается в Delphi 1. К сожалению, в текущей реализации Delphi 32 потоки не могут связываться с собственными видимыми компонентами, так как библиотека визуальных компонентов VCL (Visual Component Library) не поддерживает работу с потоками. Вот почему модуль потока не имеет связанного с ним окна.



TScrollBar управление значением величины



18.1.12. TScrollBar - управление значением величины

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

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

TSrollBarKind = (sbHorizontal, sbVertical) ; property Kind: TScrollBarKind;

property LargeChange: TScroll-Barinc;

Определяет ориентацию компонента: sbHorizontal - бегунок перемещается по горизонтали; sbVertical - бегунок перемещается по вертикали “Большой” сдвиг бегунка (при щелчке мышью рядом с концевой кнопкой)
property Max: Integer; Максимальное значение диапазона изменения числовой величины
property Min: Integers; Минимальное значение диапазона изменения числовой величины
property PageSize: Integers; Определяет размер позиции табуляции бегунка
property Position: Integers;property SmallChange: TScroll-Barinc; Текущее значение числовой величины “Малый” сдвиг бегунка (при щелчке мышью по концевой кнопке)

С помощью метода

procedure SetParams(APosition, AMax, AMin: Integer);

можно сразу установить свойства Position, мах и Min.

С компонентом связано два события:

type TScrollEvent = procedure(Sender: TObject;

ScrollCode: TScrollCode; var ScrollPos: Integer) of objects;

property OnScroll: TScrollEvent;

property OnChange: TNotifyEvent;

Первое возникает при любом изменении свойства position, второе -при изменении параметров методом Setparams.

Подобно TButton компонентом полностью управляет Windows поэтому у него нет свойства Color.



TStaticText метка для отображения текста



18.2.12. TStaticText - метка для отображения текста

Этот компонент во всем подобен своему “двоюродному брату” TLabel за исключением двух обстоятельств. Во-первых, он порожден от TwinControl и, таким образом, имеет Windows-окно. Это обстоятельство может быть необходимым условием правильного взаимодействия со связанным свойством FocusControl управляющим элементом, если это внешний для Delphi элемент ActiveX. Во-вторых, в его свойстве

type TStaticBorderStyle = (sbsNone, sbsSingle, sbsSunken) ;

property BorderStyle: TStaticBorderStyle;

добавлено значение sbsSunken, которое создает иллюзию “вдавлен-ности” компонента. Все остальные свойства и методы компонента совпадают со свойствами и методами TLabel.



TTreeView дерево иерархии



18.3.12. TTreeView - дерево иерархии

Компонент TTreeView служит для показа ветвящихся иерархических структур, таких как дерево наследования объектов или файловая структура диска. Он содержит связанные узлы, каждый из которых может содержать пиктограмму, текст и произвольный объект (подобно спискам TStringList - см. п. 14.3.2). Любой узел может иметь собственный список подузлов (Рисунок 18.27), которые можно раскрывать или закрывать щелчком мыши на пиктограмме узла.



РЕАЛИЗАЦИЯ



13.2. РЕАЛИЗАЦИЯ

Для создания DLL в Object Pascal введено зарезервированное слово Library, которым должен начинаться текст библиотеки. За словом Library следует правильный идентификатор, но в отличие от объявления модуля он не обязан совпадать с именем файла: имя DLL определяется именем DLL-файла, а не идентификатором, следующим за Library.

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

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

Library MyLibrary;

Function MyFunc (...):...;

begin

end;

Procedure MyProc;

begin

end;

Exports

MyFunc, MyProc;

begin

end.

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

Помимо имени подпрограммы в заголовок DLL помещается также ее порядковый номер, точнее, присвоенный ей целочисленный индекс. Это позволяет вызывающей программе ссылаться не на имя, а на индекс подпрограммы и тем самым уменьшить затраты времени на установление с ней связи. Индекс присваивается подпрограмме по порядку ее появления в списках Exports: первая подпрограмма в первом списке получает индекс 0, следующая - 1 и т. д. Программист может изменить умалчиваемую индексацию и явно указать индекс подпрограммы, добавив за ее именем в списке Exports слово index и целое число без знака в диапазоне от 0 до 32767:

Expots

MyFunc index 1, MyProc index 2;

Программист может определить внешнее имя экспортируемой подпрограммы отличным от ее настоящего имени. Для этого в списке Exports добавляется слово name и внешнее имя в апострофах:

Exports

MyFunc index I name 'NEWFUNC';

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

Замечу, что в отличие от модулей Delphi не компилирует DLL автоматически в режимах make или build, т. к. справедливо рассматривает ее как другую программу, никак не связанную в момент компиляции с основной программой.



ПРИМЕР



13.3. ПРИМЕР

Рассмотрим пример создания DLL, в котором иллюстрируются различные приемы объявления экспортируемых подпрограмм. Для примера выбран модуль cmpix, описанный в гл. 12. В его состав входят 4 процедуры, реализующие действия с комплексными числами. Вариант соответствующей DLL показан ниже.

Для создания заготовки библиотечного модуля выберите опцию меню File | New | Unit или в окне репозитория щелкните по пиктограмме Da. В ответ Delphi откроет специальное окно проекта с длинным комментарием, в котором указывается на необходимость вставить ссылку на модуль ShareMem, если библиотека экспортирует длинные строки в параметрах обращения к подпрограммам или как результат функций. Эта ссылка должна быть первой как в предложении uses библиотеки, так и в uses файла проекта программы, которая использует эту библиотеку. Если подпрограммы библиотеки экспортируют строки ShortString или PChar, ссылаются на ShareMem не обязательно. Сразу же сохраните проект под именем Сmpix, чтобы Delphi автоматически исправила имя библиотеки в предложении Library.

Library Cmplx;

uses

SysUtils, Classes;

{$R *.RES}

type

TComplex = record Re, Im: Real;

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

begin

Result.Im := x.Im + y.Im;

Result.Re := x.Re + y.Re end;

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

stdcall;

begin

Result.Im := x.Im - y.Im;

Result.Re := x.Re - y.Re

end;

function MulC(x, у: TComplex): TComplex;

stdcall;

begin

Result.Re := x.Re * y.Re + x.Im * y.Im;

Result.Im := x.Re * y.Im - x.Im * y.Re

end;

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

stdcall;

var

z: Real;

begin

z := sqr(y.Re) + sqr(y.Im);

try

Result.Re := (x.Re * y.Re + x.Im * y.Im)/z;

Result.Im := (x.Re * y.Im - x.Im * y.Re)/z

except

Result.Re := le+309;

Result.Im := le+309

end

end;

Exports

AddC index 1 name 'ADDC' resident,

SubC index 2,

MulC index 3,

DivC index 4;

begin

end.

Обратите внимание: все функции нашей DLL используют соглашение stdcall, которое обеспечивает совместимость новых функций с функциями API Windows 32. Мы могли бы не указывать это соглашение; в этом случае компилятор использовал бы более эффективное соглашение register, но обращение к нашей DLL из программ, написанных на других языках программирования, в общем случае стало бы невозможным.

Если вы создали DLL для "внешнего" исользования (внеDelphi), объявляйте подпрограммы с директивой stdcall или safecall!

Для использования подпрограмм из DLL необходимо описать их как внешние, добавив за словом External имя библиотеки в апострофах:

Procedure MyProc; External 'MyDLL';

Как уже говорилось, подпрограмма вызывается по имени или по индексу. В нашем примере из библиотеки MyDLL вызывается подпрограмма с внешним именем 'мургос'. Если нужно сослаться на индекс подпрограммы, за именем библиотеки указывается слово index и индекс:

Procedure MyProc; External 'MyDLL' index 2;

В этом случае имя, под которым подпрограмма будет известна программе, может не совпадать с ее внешним DLL-именем. Впрочем, программист может и явно переопределить имя подпрограммы, даже если он ссылается на ее внешнее имя:

Procedure MyProc; External 'MyDLL' Name 'ExtName';

В этом варианте предполагается, что экспортируется процедура с внешним именем ' ExtName '.

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



ИСПОЛЬЗОВАНИЕ



13.4. ИСПОЛЬЗОВАНИЕ

13.4.1. Статическая загрузка

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

type

TComplex = record Re, Im: Real;

end;

function ADDC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' ;

function SubC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' ;

function MulC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' ;

function DivC(x, y: TComplex): TComplex; stdcall; External 'Cmplx';

procedure TfmExample.bbRunClick(Sender: TObject);

var

x,y,z: TComplex;

..... // Далее смотри текст обработчика bbRunClick в п.12.6 end; end.

Обратите внимание: библиотечная функция cmpixAdd имеет внешнее имя addc. Именно так (заглавными буквами) описана эта функция в приведенном выше примере. Если бы мы использовали function AddC(x, у: TComplex): TComplex; stdcall; External

'Cmplx';

компоновщик не смог бы ее идентифицировать.



ВКЛЮЧЕНИЕ В БИБЛИОТЕКУ ФОРМ



13.5. ВКЛЮЧЕНИЕ В БИБЛИОТЕКУ ФОРМ

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

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

Текст DLL

library DLLWithFor.gif" >




TControlBar инструментальная панель



18.2.13. TControlBar - инструментальная панель

Компонент служит удобным контейнером для размещения инструментальных панелей TTооlBаr (см. п. 18.3.16). Он активно использует технологию Drag&Dock для управления положением панелей. На Рисунок 18.15 показан компонент TControlBar с двумя помещенными на него панелями TTооlваг.

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

Создайте новое приложение с пустой формой и положите на нее компонент ControlBar.

TGroupBox панель группирования



18.1.13. TGroupBox - панель группирования

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



TListView список просмотра



18.3.13. TListView - список просмотра

Компонент TListView предназначен для показа и выбора нескольких элементов. Каждый элемент может содержать пиктограмму и текст и подобно TTreeView иметь список связанных с ним подэлементов. В отличие от TTreeview в TListView допускается не более одного уровня вложенности подэлементов. TListView показывает свои элементы в одной или нескольких колонках, с крупными или мелкими пиктограммами, а также в виде “отчетов”, представляющих элементы в двухмерной таблице: по вертикали изображаются элементы верхнего уровня, по горизонтали - вложенные подэлементчатели, упрощающие множественный выбор элементов.

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

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

На Пустую форму положите компоненты TListView, TImageList, TComboBox И TCheckBox.

Компонент ImageList1 будет служить контейнером для нескольких пиктограмм, отображаемых компонентом Listview. Для наполнения контейнера дважды щелкните по нему мышью или нажмите на нем правую кнопку и выберите продолжение ImageList Editor. В появившемся окне редактора imageList нажмите кнопку Add и выберите файл images | ICONS | CHEMICAL[ См. замечание в начале главы. ]. Повторите п. 3 для выбора нескольких пиктограмм. Обратите внимание, что каждой помещаемой в imageListi пиктограмме редактор присваивает уникальный индекс. Напишите такой обработчик события oncreate для формы:

procedure TFor.gif" >




TApplicationEvents обработчик сообщений Windows



18.2.14. TApplicationEvents - обработчик сообщений Windows

Компонент TApplicationEvents впервые введен в версии Delphi 5. В отличие от остальных компонентов страницы Additional он не имеет видимого эквивалента в работающей программе. Его основное и единственное назначение - служить приемником многочисленных сообщений, которые windows посылает работающей программе.

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

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

На пустую форму поместите TEdit И TApplicationEvents. Напишите такой обработчик события OnMessage компонента TApplicationEvents:

procedure TFor.gif" >




THeaderControl управляющий заголовок



18.3.14. THeaderControl - управляющий заголовок

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

В программе, окно которой показано на Рисунок 18.30, компонент THeaderControl используется для управления положением и линейными размерами трех других компонентов. Для реализации программы выполните следующее:

Положите на пустую форму компоненты THeaderControl, ТЕ-dit, TMemo и TButton. По умолчанию HeaderControll .Align =alTop - убедитесь в этом и установите свойство, если это не так. Положение и размеры других компонентов не имеют значения. Создайте такие обработчики событий OnCreate для формы For.gif" >



TRadioGroup группа зависимых переключателей



18.1.14. TRadioGroup - группа зависимых переключателей

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

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

property Columns: Integers; Определяет количество столбцов переключателей
property Itemlndex: Integer; Содержит индекс выбранного переключателя
property Items: TStrings; Содержит список строк с заголовками элементов. Добавление/удаление элементов достигается добавлением/удалением строк списка items (см. п. 16.3.1)

После размещения компонента на форме он пуст. Чтобы создать в нем хотя бы один переключатель, следует раскрыть редактор списка Items и ввести хотя бы одну строку: строки Items используются как поясняющие надписи справа от переключателей, а их количество определяет количество переключателей в группе. Замечу также, что после создания компонента его свойство Itemlndex по умолчанию имеет значение -1, это означает, что ни один переключатель в группе не выбран. Если в момент появления компонента на экране в каком-то переключателе выбор уже должен быть установлен, необходимо на этапе конструирования с помощью окна Инспектора объектов или программно (например, в обработчике OnActivate формы) установить в свойство ItemIndex номер соответствующего переключателя (нумерация начинается с 0). Это же свойство позволяет программе проанализировать выбор пользователя, например:

case RadioGroupl.Itemlndex of

0: ...; //Выбран 1-й переключатель

1: ...; //Выбран 2-й переключатель

else

..... //Не выбран ни один переключатель

end;



КОНСТАНТЫ ПРОСТЫХ ТИПОВ И ТИПА STRING



15.1. КОНСТАНТЫ ПРОСТЫХ ТИПОВ И ТИПА STRING

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

Примеры объявлений:

type

colors = (white, red, black);

{ ----- Правильные объявления: ----- } const

CurrCol colors = red;

Name String = 'Вирт H.' ;

Year Word = 1989;

X Real = 0.1;

Min Integer =0;

Max Integer = 10;

Days 1..31 = 1;

Answer Char = 'Y';

{----- Неправильные объявления: ----- }

Mass : array [Min..Max] of Real;

{Нельзя использовать типизированные константы в качестве границ диапазона} a,b,c : Byte =0;

{Нельзя использовать список идентификаторов}



КОНСТАНТЫМАССИВЫ



15.2. КОНСТАНТЫ-МАССИВЫ

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

type

colors = (white, red, black) ;

const

ColStr : array [colors] of String [5] =('white', 'red', 'blak');

Vector : array [1..5] of Byte = (0,0,0,0,0);

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

const

Digit : array [0..9] of Char =

('0', '1', '2', ' 3 ', ' 4'•, '5', '6', '7', '8', '9');

DigChr: array [0..9] of Char = '0123456789';

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

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

Procedure TfmExample.bbRunClick(Sender: TObject);

var

i, j, k, 1 : Byte;

S: String;

const

Matr : array [1..3, 1..5] of Byte =

((0, 1, 2, 3, 4), (5, 6, 7, 8, 9), (10,11,12,13,14));

Cube : array [0..1, 0..1, 0..2] of Integer =

(((О ,1 ,2 ),(3 ,4 ,5 )), ((6 ,7 ,8 ),(9 ,10,11)));

Mas4 : array [0..1, 0..1, 0..1, 0..1] of Word =

((((О ,1 ),(2 ,3 )),

((4 ,5 ), (6 ,7 ))), (((8 ,9 ), (10,11)), ((12,13), (14,15))));

begin

S:=' ';

for i := I to 3 do for j := 1 to 5 do

S := S + IntToStr(Matr[i,j]) +' ';

mmOutput.Lines.Add(S);

S: = '';

for i := 0 to 1 do for j := 0 to 1 do

for k := 0 to 2 do

S := S + IntToStr(Matr[i,j,k]) +' ';

mmOutput.Lines.Add(S);

S:=''; for i := 0 to 1 do

for j := 0 to 1 do

for k := 0 to 1 do

for l := 0 to 1 do

S := S + IntToStr(mas4[i,j,k,l]:3);

mmOutput.Lines.Add(S) ;

end;

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



КОНСТАНТЫЗАПИСИ



15.3. КОНСТАНТЫ-ЗАПИСИ

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

<идентификатор> : <тип> = (<сп.знач.полей>)

Здесь <идентификатор> - идентификатор константы; <тип> - тип записи; <сп. знач. полей> - список значений полей.

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

type

Point = record

X, Y : Real end;

Vect = array [0..1] of Point;

Month = (Jan, Feb, Mar, Apr, May, Jun, Jly, Aug, Sep, Oct, Nov, Dec) ;

Date = record

D : 1..31;

M : month;

Y : 1900..1999 end;

const

Origon : Point = (X : 0; Y : -1) ;

Line : Vector =

((X : -3.1; Y : 1.5), (X : 5.9; Y : 3.0));

SomeDay : Date = (D : 16; M : May; Y : 1997);

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

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

type

For.gif" >




КОНСТАНТЫМНОЖЕСТВА



15.4. КОНСТАНТЫ-МНОЖЕСТВА

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

type

Days = set of 1..31;

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

Error = set of 1..24;

const

WorkDays : Days = [1..5, 8..12, 15..19, 22..26, 29, 30];

EvenDigits: Digc = ['0', '2', '4', '6', '8'];

ErrorFlag : Error= [];



КОНСТАНТЫУКАЗАТЕЛИ



15.5. КОНСТАНТЫ-УКАЗАТЕЛИ

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

const pR : ^Real = NIL;



ИНИЦИАЦИЯ ПЕРЕМЕННЫХ



15.6. ИНИЦИАЦИЯ ПЕРЕМЕННЫХ

Во всех 32-разрядных версиях Delphi при объявлении глобальных переменных разрешается одновременно присваивать им значения (инициировать). Речь идет о глобальных переменных, объявляемых в интерфейсной или исполняемой частях модулей (переменные, объявляемые в теле процедуры, называются локальными, их инициировать нельзя).

Инициированная переменная получает присвоенное ей значение один раз - в момент старта программы; в дальнейшем она хранит последнее присвоенное ей значение. Пример инициации переменной:

unit Unit1.

implementation var

MyVar: Integer = 10;

end.

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



TPanel панель



18.1.15. TPanel - панель

Компонент TPanel (панель) представляет собой контейнер общего назначения. В отличие от TGroupBox он не имеет заголовка и поэтому менее удобен для функционального группирования элементов. С другой стороны, его свойство Caption отображается в виде текстовой строки и может использоваться для вывода сообщений. Компоненты этого класса часто помещаются на форму для того, чтобы располагать вставленные в них дочерние компоненты вдоль одной из сторон окна независимо от изменения размеров этого окна (см. учебный пример в гл. 5).

Компонент имеет развитые средства создания различных эффектов трехмерности за счет использующихся в нем двух кромок -внешней и внутренней (см. п. 17.4).

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

type TAlignment = (taLeftJustify, taRightJustify, taCenter) ; property Alignment: TAlignment; Определяет выравнивание текста относительно границ компонента
type TBevelCut = (bvNone, bvLow-ered, bvRaised, bvSpace) ; Определяет вид внутренней кромки: bvNone - кромки нет; bvLowered - вдавленная кромка; bvRaised - приподнятая кромка; bvSpace - то же, что и bvRaised
property BevelInner: TPanelBevel; Определяет вид внешней кромки
property BevelOuter: TPanelBevel; type TBevelWidth = l..MaxInt; Определяет толщину кромок
property BevelWidth: TBevelWidth; TBorderStyle = bsNone..bsSingle; property BorderStyle: TBorderStyle; Определяет стиль рамки: bsNone - нет рамки; bsSingle - компонент по периметру обводится линией толщиной в 1 пиксель
property FullRepaint: Boolean; Разрешает/запрещает перерисовку панели и всех ее дочерних элементов при изменении ее размеров
property Locked: Boolean; Используется при работе с объектами OLE

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



TStatusBar информационная панель



18.3.15. TStatusBar - информационная панель

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



TValueListEditor специализированный редактор строк



18.2.15. TValueListEditor - специализированный редактор строк

Этот компонент введен в версии 6 и предназначен для редактирования списков строк вида имя=значение. Такие списки широко используются в реестре Windows и файлах инициализации. Наконец. начиная с версии 5 Delphi по умолчанию в таком формате хранит файлы описания форм dfm. Если на пустую форму положить компонент TValueListEditor, диалог TOpenDialog и кнопку TBitBtn, то после загрузки в редактор файла Example. dfm (для учебной формы, описанной в гл. 5) получим экран, показанный на Рисунок 18.17. Обработчик нажатия кнопки имеет такой вид:

procedure TFor.gif" >



КЛАСС EXCEPTION ОБРАБОТКА ИСКЛЮЧЕНИЙ



16.1. КЛАСС EXCEPTION - ОБРАБОТКА ИСКЛЮЧЕНИЙ

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

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

При работе в среде Delphi эксперименты с исключениями плохо прослеживаются, т. к. при каждом исключении среда; перехватывает управление программой. В этом случае бывает полезно отменить такое поведение среды. Для этого вызовите опцию Tools. [.- -Debugger Options и на странице Languaqe Exception уберите флажок в переключателе Stop on delphi. Exceptions (для шэсдьиуш-лх версий Delphi выберите опцию меню Tools | Environent: Options и на странице Preference уберите флажок в персключателе Break on exception).



КЛАСС TLIST СПИСКИ



16.2. КЛАСС TLIST - СПИСКИ

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

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

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

property List: pPointerList; Возвращает указатель на массив элементов списка
property Capacity: Integers; Содержит количество элементов массива указателей списка. Всегда больше Count. Если при добавлении очередного элемента Count стало равно Capacity, происходит автоматическое расширение списка на 16 элементов
property Count: Integer; Количество элементов списка. Это свойство изменяется при добавлении или удалении элемента
property Items(Index: Integer): Pointers; Возвращает указатель на элемент списка по его индексу. Самый первый элемент списка имеет индекс 0

Тип pPointerList определен следующим образом:

type

pPointerList = PPointerList;

TPointerList = array [0..MaxListSize] of Pointer;

Константа MaxListSize для Delphi 1 ограничена значением 16379 элементов. Для старших версий Delphi она ограничивается доступной памятью.

Следует учесть, что свойство count определяет количество помещенных в список элементов, в то время как capacity - текущую емкость списка. Если при добавлении очередного элемента обнаруживается, что емкость списка исчерпана, происходит наращивание емкости на фиксированную величину (для count < 5 - на 4 элемента, для 4 < count < 8 - на 8, для Count > 7 - на 16). При этом сначала резервируется память для размещения расширенного массива указателей, затем в нее копируется содержимое старого массива, после чего старый массив указателей уничтожается (занимаемая им память возвращается Windows).

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

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

Методы класса:

function Add(Item:

Pointer): Integer; procedure Clear;

Добавляет элемент item в конец ci;

вращает его индекс Очищает список, удаляя из него вес Не освобождает память, связанную удаленным элементом. Устанавлив: ства Count и Capacity значение 0

procedure Delete(Index:Integer); Удаляет из списка элемент с индекс все элементы, расположенные за удаляемым, смещаются на одну позицию вверх
class procedure Er

ror(const Msg: Stringy; Data: Integer); virtual;

Возбуждает исключение ElistErr метрами Msg и Data
procedure Ex

change (Indexl, Index2:Integer) ;

Меняет местами элементы с индексами index1 иI ndex2
function Expand: TList; function Extract(Item: Pointer): Pointer; Расширяет массив, увеличивая Capacity Удаляет из списка элемент Item
function First: Pointer; Возвращает указатель на самый первый элемент списка
function IndexOf(Item:Pointer): Integer; Отыскивает в списке элемент Item и возвращает его индекс
procedure Insert(Index:

Integer; Item: Pointer) ;

Вставляет элемент Item в позицию Index списка: новый элемент получает индекс Index, все элементы с индексами Index и больше увеличивают свой индекс на 1. При необходимости расширяет список
function Last: Pointer; Возвращает указатель на последний элемент

списка

procedure Move(Curlndex,

Newlndex: Integers;

Перемещает элемент в списке с позиции CurIndex в позицию Newlndex. Все элементы старого списка с индексами от Curlndex-1 до Newlndex уменьшают свой индекс на 1
procedure Pack; Упаковывает список: удаляет пустые элементы в конце массива индексов
function Remove(Item:

Pointer): Integer;

Отыскивает в списке элемент Item и удаляет его
procedure Sort(Compare: rListSortCompare); Сортирует коллекцию с помощью функции Compare

Методы Add и insert получают указатель на вставляемый элемент. Чтобы воспользоваться ими, программист должен сам разместить в куче данные и получить соответствующий указатель. Точно так же методы Delete, Remove и Сlear не уничтожают распределенные в памяти данные, которые программист должен, если это необходимо, уничтожить сам.

Например:

var

List: TList;

Item: Pointer;

Value: AnyType;

begin

List := TList.Create; // Создаем список

Item := New(Value); // Размещаем в куче данные

List.Add(Item); // Добавляем элемент к списку .....

List.Remove(Item); // Удаляем элемент из списка

Dispose(Item); // Удаляем его из кучи

List.Free; // Удаляем ненужный список

end;

Метод sort сортирует список по критерию, устанавливаемому функцией compary. Тип TListSortCompare определен следующим образом:

TListSortCompare = function(Iteml, Item2: Pointer): Integer;

Таким образом, функция compare получает указатели на два элемента списка. Результат сравнения:

любое отрицательное число, если Item1 ^ <Item.2^; 0,если Item1 ^ = Item2^; любое положительное число, если Item1 ^ > Item2^.

Критерий сравнения данных устанавливается программистом и реализуется в функции Compare.

В следующем примере в список List помещается 20 случайных вещественных чисел, равномерно распределенных в диапазоне 0...1.

Список сортируется по возрастанию чисел и отображается в компоненте mmOutput (многострочный редактор из учебной формы fmExample).

type

PDouble = ^Double;

Function Comp(Iteml, Item2:. Pointer): Integer;

// С помощью этой функции реализуется сортировка чисел

begin

if PDouble(Iteml)^ < PDouble(Item2) ^ then

Result := -1 else

if PDouble(Iteml^ > PDouble (Item2) ^ then

Result := 1 else

Result := 0 end;

procedure TfmExample.bbRunClick(Sender: TObject);

// Обработчик нажатий кнопки bbRun выполняет основную работу

var

k: Integer;

List: TList;

pD: PDouble;

begin

List := TList.Create; // Создаем список

for k := 1 to 20 do // Наполняем его

begin

New(pD); // Резервируем память

pD^ := Random; // Помещаем в нее случайное число

List.Add(pD); // Добавляем к списку

end/List. Sort (Comp) ; // Сортируем список по возрастанию mmOutput.Lines.Clear;

{ Очищаем редактор mmOutput. В следующем цикле наполняем mmOutput и уничтожаем элементы List }

for k := 0 to List.Count-1 do

begin

pD := List[k]; // Очередное число из списка

mmOutput. Lines .Add (FloatToStr (pD^ );

{Помещаем в mmOutput}

Dispose(pD) // Уничтожаем число

end;

List.Free; // Уничтожаем список

end;



КЛАССЫ TSTRINGS И TSTRINGLIST НАБОРЫ СТРОК И ОБЪЕКТОВ



16.3. КЛАССЫ TSTRINGS И TSTRINGLIST НАБОРЫ СТРОК И ОБЪЕКТОВ

16.3.1. TStrings

Абстрактный класс TStrings инкапсулирует поля и методы для работы с наборами строк. От него порождены многочисленные специализированные потомки, обслуживающие наборы строк в таких компонентах, как TComboBox, TListBox, TRichEdit и др. Эти классы

(TComboBoxStrings, TListBoxStrings, TRichEditStrings и др.) объявляются в разделах Implementation соответствующих модулей (Stdctris, Сomctris и др.) и поэтому скрыты от браузера Delphi и не включены в Help-службу. Единственным доступным наследником TStrings является TStringList - полнофункциональный класс общего назначения.

Замечательной особенностью TStrings и его потомков является то обстоятельство, что элементами наборов служат пары строка-объект, в которых строка - собственно строка символов, а объект - объект любого класса Delphi. Такая двойственность позволяет сохранять в TStrings объекты с текстовыми примечаниями, сортировать объекты, отыскивать нужный объект по его описанию и т. д. Кроме того, в качестве объекта может использоваться потомок от TStrings, что позволяет создавать многомерные наборы строк.

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

property Capacity: Integer; Текущая емкость набора строк
property CommaText: String; Служит для установки или получения всего набора строк в виде единой строки с кавычками и запятыми (см. ниже пояснения) Текущее количество строк в наборе.
property Count: Integer; Интерпретирует все строки списка в виде одной длинной строки
property DelimitedText: String; Каждая строка окружается символами QuoteChar и отделяется от соседней символом Delimiter
property Delimiter: Char; Символ для выделения строк в свойстве DelimitedText
property Names[Index: Integer] : String; Для строки с индексом Index возвращает часть Name, если это строка вида Name=Value, в противном случае возвращает пустую строку
property Objects[Index: Integer] : TObject; Открывает доступ к объекту, связанному со строкой с индексом Index
property QuoteChar: Char; Символ для разделения строк в свойстве DelimitedText
property Strings[Index: Integer] : String; Открывает доступ к строке с индексом Index
property StringsAdapter: TStringsAdapter; Это свойство используется только при разработке компонентов, отвечающих стандарту Act iv
property Text: String; Интерпретирует набор строк в виде одной длинной строки с разделителями eoln между отдельными строками набо
property Values[const Name: String]: String; По части Name отыскивает в наборе и возвращает часть Value для строк вида

Name=Valu

Набор строк технически реализуется подобно TList - в виде массива указателей. Свойство Capacity показывает текущую длину этого массива, а свойство count - количество элементов, занятых в нем. Если при добавлении очередного элемента capacity окажется меньше count, происходит автоматическое расширение массива. При этом в динамической памяти резервируется место для размещения Capacity + 16 указателей, в новый массив переписывается содержимое старого массива, после чего старый массив уничтожается. Если вам известно количество элементов в создаваемом наборе строк, имеет смысл заранее нужным образом установить свойство capacity, чтобы сократить непроизводительные расходы на многократные расширения массива указателей.

Свойство commaText интерпретирует содержимое набора строк в виде одной длинной строки с элементами вида "первая строка", "вторая строка", "третья строка" и т. д. (каждая строка набора заключается в двойные кавычки и отделяется от соседней строки запятой; если в строке встречается символ “"”, он удваивается). Свойство Text интерпретирует содержимое набора в виде одной длинной строки с элементами, разделенными стандартным признаком eoln (#13#10).

Свойства Names И Values обрабатывают строки вида Name=Value.

Такие строки широко используются в различных файлах инициации, например, в файле win. ini. Методы класса:

function Add(const S: String) : Integer;

function AddObject(const S:String; aObject: TObject):Integer;

Добавляет строку в набор данных и возвращает ее индекс добавляет строку и объект в набор данных
procedure AddStrings( Strings: TStrings); Добавляет к текущему набору новый набор строк
procedure Append(const S:String) ; То же, что Add, но не возвращает индекс вставленной строки
procedure Assign(Source: TPersistent) ; Уничтожает прежний набор строк и загружает из Source новый набор. В случае не удачи возникает исключение EсоnvertError
procedure BeginUpdate; Устанавливает флаг начала обновления.

До вызова EndUpdate блокируется сортировка строк, что ускоряет процесс много кратного изменения данных

procedure Clear; Очищает набор данных и освобождает связанную с ним память
procedure Delete(Index: Integer) ; Уничтожает элемент набора с индексом Index и освобождает связанную с ним память
procedure EndUpdate; Сбрасывает флаг изменения и при необходимости сортирует строки
function Equals(Strings:TStrings): Boolean; Сравнивает построчно текущий набор данных с набором Strings и возвращает True, если наборы идентичны
procedure Exchange(Indexl,

Index3: Integers;

Меняет местами строки с индексами Index1 и Index2. Если объект сортируется, вызывает исключение EstringListError
function GetObject(Index:Integer): TObject; virtual; Возвращает объект, связанный со строкой Index
function GetText: PChar; Загружает строки из единого массива, в котором они отделяются друг от друга признаком EOLN
function IndexOf(const S:

String): Integer;

Для строки S возвращает ее индекс или -1, если такой строки в наборе нет
function IndexOfName(const Name: String): Integer; Возвращает индекс первой строки вида Name=Value, в которой часть Name совпадает с параметром обращения
function IndexOfObject (aObject: TObject): Integer; Для объекта aObj ect возвращает индекс строки или -1, если такого объекта в наборе нет
procedure Insert(Index: In

teger; const S: Strings;

Вставляет строку в набор и присваивает ей индекс Index
procedure InsertObject (Index: Integer; const S: String; aObject: TObject) Вставляет строку и объект в набор и присваивает им индекс Index
procedure LoadFromFile (const FileName: Strings; Загружает набор из файла
procedure LoadFromStream (Stream: TStream) ; Загружает набор из потока
procedure Move(Curlndex, Nwlndex: Integers; Перемещает строку из положения Curlndex в положение Newlndex
procedure SaveToFile(const FileName: Strings; Сохраняет набор в файле
procedure SaveToStream (Stream: TStream) ; Сохраняет набор в потоке
procedure SetText(Text:

PChar);

Выгружает строки в единый массив, в ко

тором они отделяются друг от друга при знаком EOLN

Методы Add, Append, Insert, Clear И Т. П. В классе TStrings - абстрактные. Связано это с тем, что класс инкапсулирует их и таким

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



ГРАФИЧЕСКИЙ ИНСТРУМЕНТАРИЙ



16.4. ГРАФИЧЕСКИЙ ИНСТРУМЕНТАРИЙ

Богатство изобразительных возможностей Windows связано с так называемым дескриптором контекста графического устройства DC (Device Context) и тремя входящими в него инструментами - шрифтом, пером и кистью. В Delphi созданы специализированные классы-надстройки, существенно упрощающие использование графических инструментов Windows: для контекста - класс TCanvas, для шрифта - TFont, для пера - ТРеп и для кисти - TBrush.

Связанные с этими классами объекты автоматически создаются для всех видимых элементов и становятся доступны программе через свойства Canvas, Font, Pen и Brush.



TActionList механизм действий



18.1.16. TActionList - механизм действий

Этот компонент впервые введен в Delphi 4. Он не имеет видимого изображения и служит для поддержки механизма действий (см. п. 17.7).

Основная схема его использования такова. Вначале с помощью его редактора создается действие - объект класса TAction (редактор вызывается двойным щелчком на компоненте либо с помощью опции ActionList Editor его вспомогательного меню, которое раскрывается после щелчка на нем правой кнопкой мыши - Рисунок 18.8).

Этот объект (на рисунке он имеет умалчиваемое имя Action1) имеет ряд свойств и событий, с помощью которых уточняется характер действия. Доступ к этим свойствам и событиям можно получить с помощью окна Инспектора объектов. С действием можно связать группу свойств (Caption, Checked, Enabled, Shortcut И Т. Д.), которыне будут помещаться в одноименные свойства компонентов, реализующих общее действие. Если с компонентом связан контейнер пиктограмм типа TImageList (свойство images - не действия, а самого компонента TActionList), при реализации действия можно использовать одну из хранящихся в нем пиктограмм (ImageIndex). Чтобы действие подкреплялось программным кодом, для него обязательно следует определить обработчик события OnExecute.

В свойства Action тех компонентов, активизация которых должна сопровождаться одним и тем же действием (например, в свойства Action опции меню и кнопки инструментальной панели), помещается имя только что определенного действия (Actioni). В результате выбор опции или нажатие кнопки вызовут один и тот же метод (OnExecute), в меню появится пиктограмма (imageindex), такая же пиктограмма будет у кнопки, у них будет одинаковые названия (caption), оперативные подсказки (Hint) И Т. Д.

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

property ActionCount: Integer; Содержит количество определенных в компоненте действии (только для чтения)
property Actions[Index: Integer]: TContainedAction; Позволяет программе обратиться к нужному действию (объекту класса TContainedAction) по его индексу index
property Images: TCustomImageList; Содержит имя компонента класса TimageList
type TActionListState = (asNormal, asSuspended, asSus-pendedEnabled) ; property State: TActionListState; Состояние действий: asNormal - нормальное; asSuspended - механизм действий отключен, их свойства Enabled не изменены; asSuspendedEnabled - механизм действий отключен, но их свойства Enabled имеют значения True

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

Свойства TAction:

property Caption: String; Содержит строку, которая будет устанавливаться в свойствах caption всех компонентов, связанных данным действием
property Checked: Boolean; Содержит значение, которое будет устанавливаться в свойствах Checked
property DisableIfNoHandler: Boolean; Указывает, будут ли запрещены для выбора связанные компоненты, если для действия не определен обработчик OnExecute
property Enabled: Boolean; Содержит значение, которое будет устанавливаться в свойствах Enabled
property HelpContext: THelpContext; Содержит значение, которое будет устанавливаться в свойствах HelpContext
property Hint: String; Содержит строку, которая будет устанавливаться в свойствах Hint
property Imagelndex: Integer; Содержит индекс изображения в хранилище, указанном в свойстве images компонента. Это изображение будет связано с компонентами данного действия
property Shortcut: TShortCut; Содержит значение, которое будет устанавливаться в свойствах shortcut
property Visible: Boolean; Содержит значение, которое будет устанавливаться в свойствах visible


TToolBar и ToolButton инструментальная



18.3.16. TToolBar и ToolButton - инструментальная панель и кнопки для нее

Компонент TToolBar представляет собой специальный контейнер для создания инструментальных панелей. Главная отличительная черта TToolBar - его способность гибкого управления дочерними элементами, которые он может группировать, выравнивать по размерам, располагать в несколько рядов. Компонент может манипулировать любыми вставленными в него дочерними элементами, но все его возможности в полной мере проявляются только со специально для него разработанным компонентом TToolButton (инструментальная кнопка). Этот компонент похож на кнопку TSpeedButton, но не ищите его в палитре компонентов - его там нет. Поскольку он разработан специально для TToolBar, вставить его в инструментальную панель можно только после щелчка правой кнопкой на компоненте TToolBar и выборе NewButton или NewSeparator (сепараторы предназначены для функционального выделения на инструментальной панели групп элементов и представляют собой разновидности кнопок TTooiButton). Компонент TTooiButton не имеет свойства, предназначенного для хранения картинки, однако TToolBar умеет использовать контейнер TimageList, чтобы извлечь из него нужную картинку и поместить ее на инструментальную кнопку.

Методику использования TToolBar совместно с TToolButton рассмотрим на примере программы, окно которой показано на Рисунок 18.32.



ИЕРАРХИЯ КОМПОНЕНТОВ



17.1. ИЕРАРХИЯ КОМПОНЕНТОВ

Все компоненты Delphi порождены от класса TComponent, в котором инкапсулированы самые общие свойства и методы компонентов. Предком TComponent является класс TPersistent, который произошел непосредственно от базового класса TObject.

Класс TPersistent передает своим потомкам важный виртуальный метод

procedure Assign(Source: TPersistent);

с помощью которого поля и свойства объекта source копируются в объект, вызвавший метод Assign.

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

Класс TComponent служит базой для создания как видимых, так и невидимых компонентов.

Большинство видимых компонентов происходит от класса ТСоntrol. Два наследника этого класса - TWinControl И TGraphicControопределяют две группы компонентов: имеющие оконный ресурс rwincontroi и его потомки) и не имеющие этого ресурса TGraphicControl и его потомкам и).

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

Оконный компонент в момент своего создания обращается к Windows с требованием выделения оконного ресурса и, если требование удовлетворено, получает так называемый дескриптор окна. TWinControl и его потомки хранят дескриптор окна в свойстве Handle.

Программист может использовать этот дескриптор для непосредственного обращения к API-функциям Windows. 1 Потомки TGraphicControl не требуют от Windows дефицитного оконного ресурса, но они и не могут получать и обрабатывать Win-jows-сообщения - управляет такими элементами оконный компонент-владелец (например, форма), который является посредником между Windows и не оконными компонентами.



ИМЕНА И СОБСТВЕННИКИ КОМПОНЕНТОВ



17.2. ИМЕНА И СОБСТВЕННИКИ КОМПОНЕНТОВ

Класс TComponent включает в себя свойства и методы, общие для всех компонентов.

Свойство

property Name: TComponentName;

type TComponentName = String; // Delphi 32

type TComponentName = String[63]; // Delphi 1

определяет имя компонента. Имя компонента строится по тем же правилам, что и имена любых других объектов программирования - констант, переменных, подпрограмм и т. д.: оно представляет собой правильный идентификатор и должно быть уникальным в области своей видимости в программе. Так как компоненты помещаются на форму средой Delphi, каждый компонент автоматически получает создаваемое средой имя, совпадающее с именем своего класса (без начальной буквы Т) и дополненное числовым суффиксом: For.gif" >




РОДИТЕЛЬСКИЕ И ДОЧЕРНИЕ КОМПОНЕНТЫ



17.3. РОДИТЕЛЬСКИЕ И ДОЧЕРНИЕ КОМПОНЕНТЫ

Класс TControl со своими наследниками образуют всю палитру видимых компонентов Delphi. Терминологически они называются элементами управления, так как на их основе прежде всего реализуются управляющие элементы Windows - кнопки, переключатели, списки и т. п. В тексте книги я часто буду употреблять слова компонент и элемент как синонимы.

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

Класс TControl определяет свойство parent, которое содержит ссылку на родительский компонент:

property Parent: TWinControl;

Это свойство не следует путать с собственником owner: owner создал компонент (не обязательно - видимый), a parent управляет видимым компонентом. поскольку конструктор TComponent. Create не изменяет свойства parent (в родительском классе TComponent такого свойства нет), при создании видимых компонентов на этапе прогона программы это свойство необходимо изменять программно. Например, Следующий обработчик События OnCreate формы For.gif" >




ПОЛОЖЕНИЕ РАЗМЕРЫ И ОФОРМЛЕНИЕ КОМПОНЕНТОВ



17.4. ПОЛОЖЕНИЕ, РАЗМЕРЫ И ОФОРМЛЕНИЕ КОМПОНЕНТОВ

Положение и размеры компонента определяются четырьмя его свойствами (в пикселях):

property Height: Integer; // Высота

property Left: Integer;// Положение левой кромки

property Top: Integer;// Положение верхней кромки

property Width: Integer;// Ширина

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

property BoundsRect: TRect;

type

TPoint = record X: Longint;

Y: Longint;

end;

TRect = record case Integer of

0: (Left, Top, Right, Bottom: Integer);

1: (TopLeft, BottomRight: TPoint);

end;

Это свойство удобно использовать при прорисовке компонента методом TCanvas . FrameRect.

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

function ClientToScreen(const Point: TPoint): TPoint;

function ScreenToClient(const Point: TPoint): TPoint;

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

type TAlign = (aINone, alTop, alBottom, alLeft, alRight, alClient) ;

property Align: TAlign;

Если это свойство не равно aiNone, компонент прижимается к верхней (alTop), нижней (alBottom), левой (alLeft) или правой (alRight) границе своего родителя. При этом размеры компонента по соседним с границей измерениям игнорируются, и компонент “растекается” по границе. Например, если Align=alTop, значения свойств компонента Left и width игнорируются и его прямоугольник будет занимать всю верхнюю часть клиентской области родителя высотой Height пикселей; если Align=alLeft, свойства тор и Height игнорируются и прямоугольник занимает левую часть родителя шириной width пикселей и т. д. Если несколько компонентов имеют одинаковое выравнивание, они последовательно прижимаются друг к другу в порядке их перечисления в свойстве controls: первый прижимается к границе родителя, второй - к границе первого и т. д. Вся не заполненная другими компонентами клиентская область родителя заполняется компонентами со свойствами Align=alClient, которые в этом случае накладываются друг на друга. Замечательной особенностью свойства является его постоянство при изменении размеров клиентской части родителя. Если, например, компонент прижат к верхней границе формы, он будет неизменно занимать верхнюю часть клиентской области при любых изменениях размеров окна. Таким способом можно легко реализовать панели с инструментальными кнопками, панели статуса и т. п. Временное отключение и затем включение эффекта от свойства Align обеспечивается методами

procedure DisableAlign;

procedure EnableAlign;

Любой видимый компонент можно спрятать или показать с помощью свойства visible или методами Hide и show:

property Visible: Boolean; // True - показывает

procedure Hide; // Прячет компонент

procedure Show; // Показывает компонент

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

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

procedure BringToFront; // Сделать верхним

procedure SendToBack.gif" >



УКАЗАТЕЛИ МЫШИ



17.5. УКАЗАТЕЛИ МЫШИ

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

property Cursor: TCursor;

type TCursor = -32768..+32767;

В Delphi предопределены стандартные указатели, показанные на рисунке 17.2.



РЕАКЦИЯ НА СОБЫТИЯ ОТ МЫШИ И КЛАВИАТУРЫ



17.6. РЕАКЦИЯ НА СОБЫТИЯ ОТ МЫШИ И КЛАВИАТУРЫ

17.6.1. События от мыши

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

type

TMouseButton = (mbLeft, mbRight, mbMiddle) ;

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

ssRight, ssMiddle, ssDouble);

TMouseEvent = procedure (Sender: TObject;

Button: TMouseButton;

Shift: TShiftState; X, Y: Integer) of object;

TMouseMoveEvent = procedure(Sender: TObject;

Shift: TShiftState; X, Y: Integer) of object;

TNotifyEvent = procedure (Sender: TObject) of object-property OnMouseDown: TMouseEvent;

property OnMouseUp: TMouseEvent;

property OnMouseMove: TMouseMoveEvent;

property OnClick: TNotifyEvent;

property OnDblClick: TNotifyEvent;

Тип TMouseButton определяет одну из трех кнопок мыши: левую (mbLeft), правую (mbRigth) и среднюю (mbMiddle).

Тип TShiftState содержит признаки, уточняющие обстоятельства возникновения события: ssShift - нажата клавиша Shift; ssAit -нажата клавиша Alt; ssctri - нажата клавиша Ctrl; ssLeft - нажата левая кнопка мыши; ssRight - нажата правая кнопка; ssMiddie -нажата средняя кнопка; ssDoubie - нажаты одновременно левая и правая кнопки.

Обработчики OnMouseDown и OnMouseUp определяют реакцию программы на соответственно нажатие и отпускание кнопки мыши, оп-MouseMove - на перемещение указателя мыши над компонентом, оп-click и OnDblClick - соответственно на щелчок и двойной щелчок левой кнопки. Во всех обработчиках параметр sender содержит ссылку на компонент, над которым произошло событие, а х и y определяют координаты точки чувствительности указателя мыши в момент возникновения события в системе координат клиентской области родительского компонента. Замечу, что событие OnClick возникает после OnMouseDown, но перед OnMouseUp, а событие

OnDblClick Возникает после OnMouseUp.