Общий обзор языка
ВведениеДля операционной системы Linux долгое время не было достаточно простой среды быстрой разработки приложений. Многие программисты, которые успешно создают программы для Windows, используют среду Borland Delphi. В нашей стране Delphi пользуется особой популярностью как среди начинающих разработчиков, так и среди профессионалов. Многие из них готовы создавать программы для среды Linux, но не было среды, похожей на Delphi. Наконец, летом 2001 года фирма Borland выпустила среду для быстрой разработки приложений в среде Linux и назвала ее Kylix (Kylix — это античная винная чаша, расписанная с внешней и внутренней стороны). На первый взгляд, эта среда — практически копия Delphi, но есть некоторые отличия. Причем эти отличия являются довольно опасными, т. к. одна и та же команда в Delphi и Kylix может привести к совершенно разным последствиям. Данная книга представляет собой краткий обзор среды Kylix версии Kylix Server Developer. С помощью нее вы узнаете особенности среды Kylix и ее отличия от Delphi. Кроме того, заключительная часть книги расскажет вам о методах переноса приложений из Delphi в Kylix и создании межплатформенных приложений.
Для кого предназначена эта книга
Книга предназначена для всех желающих изучить среду Kylix и научиться создавать работоспособные программы под Linux. Стиль изложения материала — от простого к сложному, приведены многочисленные примеры. Конечно, желательно, чтобы читатель был знаком (хотя бы поверхностно) с операционной системой Linux и программированием. Данная книга будет читаться еще легче, если вы знакомы с программированием в Delphi.
В данном объеме невозможно охватить все аспекты программирования в Kylix, поэтому в конце книги приводится список литературы и ссылки на сайты в Интернете, из которых читатель сможет почерпнуть отсутствующую в книге информацию.
Структура и особенности книги
Книга состоит из семи частей.
Первая часть книги рассказывает о языке программирования Object Pascal, который лежит в основе Kylix. В данной части представлен общий обзор языка, синтаксис, типы данных и простые конструкции языка.
Во второй части рассматриваются основы программирования в Kylix. Прочитав эту часть, вы узнаете назначение основных окон среды, а также состав палитры компонентов Kylix. Кроме того, в этой части рассматривается библиотека классов Kylix.
Третья часть посвящена дополнительным возможностям среды. Здесь мы рассматриваем работу с классами и исключительными ситуациями, интерфейсами, сокетами. Одна из глав части посвящена созданию справочной системы в Kylix. В этой же части рассматривается работа с графикой в Kylix: вы научитесь рисовать любые фигуры и работать с графическими объектами. Последняя глава этой части расскажет о процессах и потоках. После ее прочтения вы сами сможете создавать многопоточные приложения.
Четвертая часть книги содержит главы, посвященные созданию приложений баз данных в Kylix. Вы узнаете основные принципы построения баз данных. Затем мы рассмотрим компоненты для работы с базами данных. Одна из глав части посвящена изучению основ языка SQL. В заключительной главе данной части мы рассмотрим принципы создания простого отчета.
Пятая часть предназначена для тех читателей, которые хотят создавать собственные компоненты и пакеты компонентов для среды Kylix.
Шестая часть книги расскажет о проблемах создания межплатформенных приложений. Вы узнаете об отличиях Kylix и Delphi, а также Linux и Windows.
Седьмая часть включает в себя приложения со списками программ для создания справочной системы, с особенностями файловой структуры Linux, a также со списком рекомендуемой литературы и ссылками на сайты в Интернете.
Используемые обозначения
В книге были использованы следующие обозначения:
Абстрактные методы
Абстрактные методыАбстрактными методами называются такие методы, которые описаны внутри определения класса или компонента, но не содержат никаких действий и никогда не вызываются. Абстрактными могут быть виртуальные или динамические методы. Абстрактные методы используются только в компонентах или классах-предках. Описание абстрактного метода выглядит следующим образом:
procedure MyProcedure; virtual; abstract;
Примечание
Никогда не вызывайте на выполнение абстрактные методы, т. к. они не содержат никаких команд, которые могли бы выполниться. Вызов абстрактного метода приведет к генерации исключительной ситуации EAbstractError.
О создании свойств, методов и событий новых компонентов расскажет следующая глава этой книги.
Назад Вперед
Алфавит и словарь языка
Алфавит и словарь языкаВ алфавит языка Object Pascal входят следующие символы:
• (* и *) — ремарка, пояснение. Является альтернативой символам фигурных скобок { и };
• ( . и . ) — применяется для индексов массива, работы со строками и в других случаях. Данные символы можно использовать вместо квадратных скобок [ и ];
• .. — применяется для определения диапазона значений;
• / / — ремарка, пояснение. Символы, находящиеся справа от данной комбинации символов, игнорируются компилятором и считаются пояснением;
• : = — символ присваивания;
• <= — меньше или равно;
• >= - больше или равно;
• <> — не равно;
Примечание
Символы ! , ", % , ?, \, _, ~ не являются специальными символами языка Object Pascal.
Все слова условно делятся на три большие группы:
and, array, as, asm, begin, case, class, const, constructor, destructor, dispinterface, div, do, downto, else, end, except, exports, file, finalization, finally, for, function, goto, if, implementation, in, inherited, initialization, inline, interface, is, label, library, mod, nil, not, object, of, or, out, packed, procedure, program, property, raise, record, repeat, resourcestring, set, shl, shr, string, then, threadvar, to, try, type, unit, until, uses, var, while, with, xor.
В дополнение к представленным выше зарезервированным словам в языке Object Pascal присутствуют еще слова private, protected, public, published и automated, которые являются зарезервированными в пределах области объявления типов. Во всех других случаях они рассматриваются как директивы.
Директивы — слова, которые имеют специальное значение в языке Object Pascal, но, в отличие от зарезервированных слов, программист может использовать данные слова в качестве идентификаторов. Компилятор языка всегда отличит такой идентификатор от директивы. Ниже представлен список директив Object Pascal:
absolute, abstract, assembler, automated, cdecl, contains, default, dispid, dynamic, export, external, far, forward, implements, index, message, name, near, nodefault, overload, override, package, pascal, private, protected, public, published, read, readonly, register, reintroduce, requires, resident, safecall, stdcall, stored, virtual, write, writeonly.
Идентификаторами называются слова,которые применяются для обозначения констант, переменных, полей,'"типов, свойств, процедур, функций, программ, модулей, библиотечек и пакетов. К таким словам относятся как предопределенные (например, Pi, Sin), так и создаваемые программистом.
Идентификаторы должны создаваться по следующим правилам:
Архитектура баз данных
Архитектура баз данныхПриложения баз данных строятся из элементов пользовательского интерфейса, компонентов, которые предоставляют наборы данных, и компонентов, предназначенных для соединения с базой данных. В зависимости от того, как вы организуете эти части приложения, получатся приложения той или иной архитектуры.
На рис, 15.2 представлена схема организации приложения базы данных.
Арифметические выражения
Арифметические выраженияАрифметические операции выполняются над целыми и действительными числами. Результатом выполнения арифметического выражения является также целое или действительное число.
В языке Object Pascal определены арифметические операции над двумя операндами, которые приведены в табл. 3.1.
Библиотека классов Kylix
Библиотека классов KylixВ данной главе мы рассмотрим библиотеку классов CLX, которая поставляется со средой Kylix. Изучим типы событий и научимся писать их обработчики. Узнаем, как происходит наследование данных и кода компонентов Kylix. Кроме того, рассмотрим иерархию классов CLX.
CLX Kylix
Kylix является средой для быстрой разработки программ под Linux. Для облегчения работы программиста и ускорения создания приложений в стандартную поставку Kylix входят некоторые готовые классы, которые называются компонентами. Эти компоненты программист может использовать в своих приложениях. Они обеспечивают практически все возможные элементы пользовательского интерфейса.
Библиотека компонентов Kylix называется CLX (произносится как "клике"). Эта аббревиатура расшифровывается так: Библиотека компонентов для кросс-платформенной (межплатформенной) разработки (Component Library for Cross-platform development).
Данная библиотека содержит более ста компонентов, готовых к использованию. Их возможности могут быть расширены самим программистом путем создания новых компонентов на основе стандартных.
Библиотека CLX позволяет достаточно быстро разрабатывать эффективные программы для Интернета, настольные приложения, а также приложения баз данных (как локальных, так и сетевых).
CLX является развитием визуальной библиотеки компонентов Delphi (Visual Component Library, VCL) и позволяет довольно легко переносить приложения, написанные на Delphi, в среду Linux. О разработке межплатформенных приложений мы расскажем в заключительной, шестой части книги.
Вперед
CLX как версия VCL
CLX как версия VCLKylix использует библиотеку компонентов Borland для создания кроссплат-форменных приложений (Borland Component Library for Cross Platform, CLX) вместо библиотеки визуальных компонентов Delphi (Visual Component Library, VCL). В VCL многие оконные компоненты позволяли достаточно просто работать с окнами Windows. В среде Linux CLX обеспечивает доступ к Qt widgets (образовано от двух слов: window — "окно" и gadget — "приспособление") при помощи специальной библиотеки Qt.
CLX очень похоже на VCL. Множество компонентов CLX имеют такие же имена, как и в VCL. Многие свойства также имеют одинаковые названия.
Компоненты CLX можно сгруппировать в части, представленные в табл. 21.1.
Диалоговое окно добавления новых полей
Рисунок 18.4. Диалоговое окно добавления новых полей Добавим определения полей, представленные в табл. 18.1.Диалоговое окно сохранения файла таблицы
Рисунок 18.8. Диалоговое окно сохранения файла таблицыТеперь определим поля явно на основе FieldDefs. Дважды щелкнем на компоненте Clients, в появившемся диалоговом окне щелчком правой кнопкой мыши откроем контекстное меню и выберем пункт добавления всех полей Add all fields (Рисунок 18.9).
Динамическая загрузка пакетов
Динамическая загрузка пакетовИногда требуется загружать необходимый пакет во время работы приложения. Для этой цели служит функция LoadPackage. Данная функция находится в модуле Kylix SysUtils. Описание этой функции имеет следующий вид:
function LoadPackage(const Name: string): HMODULE;
В качестве передаваемого функции параметра служит имя файла пакета типа string. Вызов данной функции очень прост:
LoadPackage('Имя файла пакета');
Для динамической выгрузки пакета применяется процедура UnloadPackage. Эта процедура также содержится в модуле SysUtils. Ее описание имеет вид:
procedure UnioadPackage(Module: HMODULE);
При вызове данной процедуры будьте осторожны, чтобы не уничтожить экземпляры классов, определенных в пакете.
Среда Kylix поставляется с уже установленными пакетами компонентов, которые поддерживают основные компоненты, необходимые для создания стандартных приложений Linux. Наибольшее число стандартных компонентов Kylix содержится в уже знакомом нам пакете bplclx. Но данный пакет не содержит многие компоненты, например компоненты для работы с базами данных. Эти компоненты находятся в других пакетах Kylix (например, компоненты, предназначенные для работы с базами данных, находятся в пакете bpldataclx). Однако, несмотря на это, для работы с базами данных вам понадобятся оба пакета: bplclx и bpldataclx. В табл. 20.2 перечислены пакеты времени выполнения, поставляемые с Kylix, а также модули (units), входящие в данные пакеты.
Динамические методы
Динамические методыДинамические методы похожи на виртуальные, они также могут быть перегружены. Основная разница между виртуальными и динамическими методами — в способе их вызова. Если для виртуальных методов строится таблица виртуальных методов, то каждому динамическому методу присваивается уникальное число-идентификатор, после чего строится таблица динамических методов (Dynamic Method Table), в которую заносится данное число, а также адрес метода. Еще одно отличие динамических методов от виртуальных заключается в том, что таблицы динамических методов содержат методы только одного компонента или класса (не включая его предков). Поэтому существенно экономится память, но замедляется время работы, т. к. для поиска адреса метода обычно приходится просматривать несколько таблиц динамических методов.
Описание динамического метода может выглядеть так:
type
TComponent = class procedure MyProcedure; dynamic; end;
Методы-сообщения
Методы-сообщения не вызываются из программы непосредственно, как другие методы. Этот тип методов предназначен для того, чтобы выполнить какие-либо действия в ответ на сообщение операционной системы. В качестве примера рассмотрим описание метода-сообщения:
type TComponent = class
procedure MyProcedure(Var A: TMessage); message wm_MessageWindows; end;
После служебного слова message ставится значение (в нашем случае wm_MessageWindows), которое определяет сообщение операционной системы, в ответ на которое будет вызван метод MyProcedure.
Виртуальные и динамические методы могут быть замещенными (overriden) или абстрактными (abstract).
Назад Вперед
Директивы компилятора
Директивы компилятораДирективы компилятора — это указания компилятору на выполнение каких-либо действий. Для записи директив компилятора используют символы:
{$ директива} либо( * директива *)
Все директивы компилятора делятся на:
Локальные директивы действуют от места их появления до появления отменяющей директивы.
Имеется три вида директив компилятора:
Назад
Для чего используются пакеты
Для чего используются пакетыКак мы уже говорили выше, пакеты разработки предназначены для упрощения задачи распределения и установки компонентов, созданных разработчиком. Программирование с помощью пакетов разработки, по определению, имеет некоторое преимущество по сравнению с обычным программированием. Главное преимущество — сокращение размера кода. Например, все ваши приложения, включая среду программирования Kylix, могут одновременно использовать стандартные компоненты Kylix, расположенные в одном и том же пакете. Так как приложения не содержат отдельные копии библиотек компонентов, их размер намного меньше. Более того, время компиляции пакетов намного меньше, т. к. для конкретного приложения компилируется тот код, который ему необходим.
Для того чтобы приложение использовало пакеты, необходимо установить флажок Build with runtime package в диалоговом окне Project Options на странице Packages. Для открытия этого диалогового окна используйте пункт главного меню Kylix Project/Options. При такой компиляции приложения оно значительно сократится в размерах (примерно в 8—10 раз), но вам придется при распространении приложения передавать и все применяемые им пакеты.
Рассмотрим, когда нужно использовать пакеты, а когда — стандартные библиотеки разделяемых объектов Linux:
Другие методы работы с графикой в Куliх
Другие методы работы с графикой в КуliхВообще, вам не требуется наличие специальных компонентов для работы с графическими возможностями Kylix. Вы можете создавать, рисовать, сохранять и уничтожать графические объекты без отображения графики на экране. В качестве графического объекта могут выступать bmp-файлы, рисунки, пиктограммы и другие объекты, включая сжатые jpeg-файлы. В большинстве случаев приложение редко рисует напрямую на форме. Обычно сначала создается графический образ, а затем он отображается с помощью компонента CLX Image.
Как только вы разместили рисунок в компонент Image, вы можете достаточно легко его сохранять, загружать и копировать в буфер обмена.
Примечание
Если вы рисуете не на экране, а, например, на канве объекта TBitmap, изображение не будет отображаться на экране до тех пор, пока не будет произведено копирование рисунка из канвы объекта TBitmap в канву визуального объекта. Более того, необходимо сделать перерисовку визуального объекта после копирования, например с помощью вызова метода Refresh для данного визуального объекта. Если вы рисуете напрямую в канве визуального объекта, таких проблем не возникает.
Иногда картинка превышает размер формы. Для просмотра таких больших изображений можно разместить на форме компонент TScrollBox и помещать изображение внутрь этого компонента.
Работа с компонентом Image
Компонент Image представляет собой контейнер, который может содержать и отображать графический объект.
Вы можете расположить данный компонент в любом месте формы, после чего с помощью инспектора объектов в свойстве Picture указать графический объект, который будет содержаться в компоненте Image. Кроме того, данное свойство можно изменять и в процессе выполнения приложения, изменяя свойство Picture.
Если вы хотите, чтобы приложение сразу после запуска создавало чистую заготовку для изображения, вам необходимо выполнить следующие шаги:
1. Создать заготовку обработчика события OnCreate для формы, содержащей Компонент Image.
2. Создать объект Bitmap и присвоить его свойству Picture.Graphic компонента Image.
В нижеприведенном примере (листинг 13.17) главная форма приложения Form1 содержит компонент типа TImage, который имеет имя (свойство Name) Image. Код размещен в обработчике события OnCreate формы Form1.
Файловая система Linux
Файловая система LinuxПонятие каталога в Linux и Windows несколько отличается. В Linux любой файл или устройство может быть "смонтировано" в произвольном месте файловой системы.
Примечание
При указании пути к файлу в Linux используется прямой слэш в отличие от Windows, который использует обратный слэш. Первый начальный слэш обозначает корневой каталог.
В табл. П1 указаны основные каталоги Linux и их содержание.
Фигуры получаемые после вызова метода Chord
Рисунок 8.14. Фигуры, получаемые после вызова метода ChordНастоящий метод можно применять и к объекту Clipboard. Вызов метода Clear для буфера обмена удалит все содержимое буфера.
Button1.Click;
Примечание
Обратите внимание на то, что при удалении элемента списка происходит перестройка данного списка. То есть, если вы удалили третий элемент, то после его удаления на место третьего элемента будет поставлен четвертый. Таким образом, пустых мест в списках не бывает.
Примечание
Не рекомендуется вызывать непосредственно метод Destroy для уничтожения объекта Для этих целей лучше использовать метод Free, который проверяет, не была ли уже раньше освобождена занимаемая объектом память, после чего вызывает метод Destroy. Более того, метод Free генерирует меньший код для уничтожения форм используйте метод Release.
Функции языка SQL
Функции языка SQLВ языке SQL, кроме операторов, имеется несколько функций, основные из которых будут рассмотрены далее.
Статистические функции — функции, предназначенные для статистической обработки данных. Наиболее часто используемые статистические функции перечислены в табл. 17.4.
Функции
ФункцииФункции — это подпрограммы, которые могут возвращать под своим именем результирующее значение. Типичным примером функции может быть функция Sin (х). Запись:
A:=Sin(x);
позволяет вызвать функцию вычисления синуса числа х и вернуть результат под именем функции, а затем присвоить его переменной А.
Описание функции состоит из двух частей: заголовка и блока. Заголовок функции имеет следующий вид:
Function имя функции (параметры): тип результата;
Имя функции однозначно идентифицирует данную функцию и используется для ее вызова из основной программы.
Параметры — это необязательная часть функции, содержащая список переменных, которые передаются в функцию из основной программы.
Тип результата — показывает, какой тип будет иметь результат выполнения функции. Тип результата может быть любым, за исключением файлового.
Блок функции — это программный блок, состоящий, как минимум, из одного оператора присваивания:
Имя функции := результат выполнения функции;
или
Result := результат выполнения функции;
Данная операция присваивания (как первая, так и вторая) присваивает результирующее значение, которое вернет функция при возврате в основную программу. Например:
function WF: Integer;
begin
WF := 17; end;
и
function WF: Integer; begin
Result := 17; end;
Вызов обеих функций приведет к одному и тому же результату. Данная функция всегда будет возвращать значение 17.
Вызов функции осуществляется по ее имени и списку аргументов, заключенных в круглые скобки после имени функции. Все аргументы должны быть совместимы по типу с параметрами, указанными в заголовке функции.
В качестве примера рассмотрим описание функции нахождения максимального значения среди элементов одномерного массива (листинг 4.1). В качестве параметров в функцию будем передавать имя массива и количество его элементов.
Генерация исключений
Генерация исключенийИногда программисту необходимо, чтобы программа в нужный момент времени генерировала исключительную ситуацию нового типа, которого нет в стандартных типах исключений Kylix. В этом случае следует создать новый тип исключения.
Для создания собственных типов исключений нужно знать, как определить тип объекта исключения и как вызвать исключение.
Так как исключение является объектом Kylix, то определение нового типа исключения так же просто, как определение объекта нового типа. Теоретически возможно вызвать любой объект как объект исключения, но стандартные обработчики исключений работают только с теми объектами, кото-
рые являются потомками Exception или, другими словами, с объектами, предками которых являются Exception.
В качестве примера создания собственного типа исключения рассмотрим следующее определение:
type
EMyException = class(Exception);
Теперь, если вы вызовете исключение EMyException, но не напишите собственный обработчик для него, произойдет вызов стандартного обработчика для Exception. Так как стандартный обработчик для Exception показывает имя вызванного исключений, вы можете увидеть имя вашего нового исключения,
Чтобы вызвать созданное исключение, используйте команду raise.
Для примера рассмотрим типичную задачу проверки введенного пользователем пароля:
type
EPasswordInvalid = class(Exception);
После определения нового типа исключения EPasswordInwalid вы можете вызвать это исключение в любом месте программы:
if Password <> CorrectPassword then
raise EPasswordInvalid.Create('Введен неправильный пароль');
Вызов созданного исключения производится по его имени. При этом вызывается метод конструктора Create. Уничтожать самостоятельно вызванное исключение не нужно, т. к. об этом позаботится среда Kylix.
Назад
Главное окно Kylix
Рисунок 6.1. Главное окно KylixМеню главного окна Kylix содержит стандартные для любой программы пункты. Меню — это самая верхняя строка главного окна Kylix (File, Edit, Search и т. д.). При помощи меню можно работать с файлами, проектами, формами, настраивать установки Kylix и выполнять многие другие действия. Меню главного окна позволяет устанавливать новые компоненты, а также вызывать другие инструменты разработки.
Некоторые пункты меню Kylix можно выполнить при помощи "горячих клавиш", например команду Open Project (Открыть проект) можно выполнить с помощью комбинации клавиш
Панели инструментов состоят из шести частей, расположенных под меню главного окна (панель Desktop находится справа от меню), и содержат кнопки для вызова некоторых команд меню главного окна. Панели подразделяются по функциональному назначению:
Графический интерфейс пользователя
Графический интерфейс пользователя.И регенерация исключений
и регенерация исключенийИногда бывает необходимо после обработки исключительной ситуации вызвать стандартный обработчик ошибки. Например, в случае возникновения некоторой ошибки вы хотите, чтобы приложение сообщало пользователю какую-либо информацию, а затем передавало управление стандартному обработчику ошибок. Как вы уже знаете, после обработки исключения вашим кодом исключение уничтожается. Для того чтобы самостоятельно вызвать снова это исключение, можно воспользоваться регенерацией исключений. Для регенерации исключения служит команда raise, рассмотренная в листинге 9.5.
Иерархия классов CLX
Иерархия классов CLXКак уже говорилось ранее, библиотека классов CLX содержит наиболее применяемые компоненты, из которых строится ваше приложение. Так как в языке Object Pascal объекты создаются путем наследования, библиотека классов CLX построена по иерархическому принципу. Рассмотрим иерархию компонентов CLX (Рисунок 7.1).
Приведенный Рисунок 7.1 требует некоторых пояснений. Отметим, что данный рисунок показывает полную иерархию классов Kylix. Компоненты CLX являются лишь составной частью этой иерархии и начинаются с класса TComponent, который является базовым для всех компонентов CLX.
Далее рассмотрим полную иерархию классов Kylix.
Как мы уже знаем, все классы, и компоненты в том числе, являются прямыми или косвенными потомками класса TObject. Класс TObject инкапсулирует небольшой набор обычных для всех классов методов:
Информация о типе во времени выполнения
Информация о типе во времени выполненияИнформация о типе во время выполнения (Runtime Type Information, RTTI) — это способность среды Kylix предоставлять приложению информацию об объектах во время выполнения приложения. Так как все объекты Kylix являются потомками класса TObject, то все они содержат указатель на информацию о типе, а также методы для работы с этой информацией. В приведенной ниже табл. 5.1 рассмотрены некоторые из этих методов.
Инициализация потоков
Инициализация потоковЕсли вы хотите написать код инициализации для вашего нового объекта потока, вам необходимо добавить новый конструктор в описание вашего нового класса потока, после чего вы можете добавлять код инициализации вместо кода реализации класса. Здесь вы можете также указать, какой приоритет вы устанавливаете для данного потока, а также, как должен вести себя данный поток по завершении своей работы.
Приоритеты потоков
Приоритеты потоков указывают операционной системе, сколько процессорного времени выделяется для данного потока. Для критических задач можно установить наивысший приоритет, для менее значимых — более низкий приоритет.
Для установки значения приоритета у потоков имеется свойство Priority. Данное свойство может принимать произвольное целое значение. Используется как бы шкала значений приоритетов от самого низкого до наивысшего. В Linux-приложениях свойство Priority всегда должно принимать целое числовое значение. Наибольшее числовое значение указывает на самый высокий приоритет выполнения данного потока. Диапазон значений, которые может принимать свойство Priority, зависит от значения свойства Policy. Это свойство доступно только для Linux-приложений и может принимать значения, перечисленные в табл. 14.1.
Инспектор объектов
Рисунок 6.5. Инспектор объектовСписок объектов предназначен для быстрой навигации среди объектов и представляет собой выпадающий список, содержащий все компоненты текущей формы. Активный компонент отображается в верхней строке выпа-
дающего списка. На Рисунок 6.5 активным компонентом является сама форма Form1.
Вкладка свойств (Properties) служит для установки значений свойств активного компонента во время разработки приложения. Установка этих значений во время разработки приложения задает начальные свойства компонента во время выполнения приложения.
Все свойства для активного компонента перечислены в левой части вкладки Properties, значения свойств расположены в правой части. Свойства могут быть отмечены значком "+", находящимся слева от названия свойства. При щелчке левой кнопкой мыши на этом значке откроются подсвойства данного свойства. Значок "+" при этом сменится на "—".
Для возвращения свойства в исходное состояние (со знаком "+") достаточно щелкнуть на значке "—". Если значение свойства может быть установлено через диалоговое окно, то рядом со значением появляется кнопка "", при нажатии на которую это диалоговое окно и вызывается. Оно также может вызываться при двойном щелчке кнопки мыши на значении свойства.
Если значение свойства является перечисляемым, то при выборе свойства появляется кнопка со стрелкой вниз, при нажатии на которую в выпадающем списке будут перечислены все значения, которые может принимать данное свойство. Выбор производится простым щелчком мыши по нужному значению.
Kylix позволяет по-разному группировать свойства. Например, вы можете сгруппировать свойства в инспекторе объектов по категориям, для чего нужно щелкнуть правой кнопкой мыши на свойствах и выбрать в выпадающем меню строку Arrange/by category (Группировать/по категории). При этом вкладка свойств (Properties) примет вид, представленный на Рисунок 6.6.
Вы можете просмотреть свойства той или иной категории, щелкнув на значке "+" слева от названия категории.
Имеется возможность скрывать и отображать отдельные группы свойств. Это делается следующим образом: щелкните правой кнопкой мыши на свойстве или группе свойств, выберите из выпадающего меню пункт View (Вид). Те группы свойств, которые отмечены флажком, являются видимыми. По умолчанию группа свойств наследования Legacy не отображается.
Обратите внимание, что свойства для разных объектов могут довольно сильно отличаться. В Kylix имеется возможность множественного выбора объектов на форме (для этого необходимо, удерживая нажатой клавишу
Вкладка событий (Events) (Рисунок 6.7) содержит список событий (системных и пользовательских), которые могут произойти с объектом, выбранным в окне выбора объекта. Список событий отличается для разных объектов. Названия событий перечислены на правой части вкладки событий.
Название каждого события начинается с приставки On.
Интегрированная среда разработки Kylix
Интегрированная среда разработки KylixИз данной главы вы:
Средство для быстрой разработки приложений (Rapid Application Development, RAD) Borland Kylix было создано в 2001 году. Корпорация Borland предлагает два основных варианта Kylix:
Интерфейс IUnknown
Интерфейс IUnknownПо аналогии с наследованием классов, предком которых является базовый класс TObject, все интерфейсы являются прямыми или косвенными наследниками интерфейса IUnknown. Этот базовый интерфейс описан в модуле System следующим образом (листинг 10.3).
Интерфейсы
ИнтерфейсыВ этой главе мы рассмотрим, что такое интерфейс и где он применяется. Кроме того, вы узнаете, что такое графический интерфейс пользователя, и познакомитесь с методами создания SDI- и MDI- приложений.
Понятие интерфейса
Ключевое слово Kylix interface позволяет вам создавать и использовать интерфейсы в ваших приложениях. Интерфейсы расширяют модель наследования в CLX, позволяя одному классу принадлежать нескольким интерфейсам, а также нескольким классам — наследникам различных базовых классов — использовать один интерфейс. Интерфейсы полезны в тех случаях, когда наборы операций, таких как потоки, используются большим количеством объектов.
Таким образом, интерфейсы — это средства для обеспечения взаимодействия между разными объектами.
Интерфейсы похожи на классы, которые содержат в себе только абстрактные методы и четкие определения их функциональности. Определение метода интерфейса включает в себя параметры и типы параметров, возвращаемый тип, а также ожидаемое поведение. Методы интерфейса семантически или логически связаны с отражением цели интерфейса, Существует соглашение об интерфейсах, гласящее, что каждый интерфейс должен быть назван в соответствии с задачей, которую он предназначен выполнять. Например, интерфейс IMalloc — предназначен для распределения, освобождения и управления памятью. Аналогично, интерфейс IPersist может использоваться как базовый интерфейс для потомков, каждый из которых определяет специфичные прототипы методов для загрузки и сохранения состояния объектов в память, поток или в файл. В листинге 10.1 приведен простой пример объявления интерфейса.
Использование главного CLXпотока
Использование главного CLX-потокаКогда вы применяете в своем приложении объекты из библиотеки визуальных компонентов, то вам нужно иметь в виду, что свойства и методы объектов из CLX не гарантируют потоковую безопасность.
В случае, когда все объекты обращаются к своим свойствам и выполняют свои методы в одном потоке, вам не нужно беспокоиться о том, что объекты будут создавать друг другу помехи.
Для использования главного CLX-потока создайте отдельную процедуру, которая выполняет необходимые действия. А затем вызовите эту процедуру из вашего потокового модуля (внутри метода Execute), применив синхронизацию. Например, как представлено в листинге 14.7.
Использование кисти
Использование кистиСвойство Brush канвы позволяет вам указывать, каким образом будет Производиться заполнение областей и геометрических фигур.
Кисть имеет три свойства:
Рассмотрим эти свойства более подробно.
Цвет кисти
Цвет кисти определяет, какой цвет будет использоваться для заполнения внутренних областей геометрических фигур и областей канвы. Для смены цвета кисти достаточно присвоить необходимое значение свойству Color кисти.
Цвет кисти используется как фоновый цвет текста и линий. В листинге 13.6 мы устанавливаем синий цвет кисти.
Использование ключевого слова implements
Использование ключевого слова implementsМногие классы CLX Kylix имеют в качестве некоторых своих свойств объекты. Кроме того, вы можете применять в качестве свойств класса интерфейсы. В том случае, когда свойство имеет тип интерфейса, вы можете использовать ключевое слово implements для определения методов, которые данный интерфейс передает объекту. По умолчанию ключевое слово implements передает все методы интерфейса. Тем не менее, вы можете самостоятельно определить список тех методов интерфейса, которые передаются объекту.
В листинге 10.5 представлен пример использования ключевого слова implements при создании объекта адаптера цвета, предназначенного для преобразования восьмибитного значения цвета RGB.
Использование компилятора командной строки
Использование компилятора командной строкиЕсли вы компилируете пакет из командной строки (без загруженной графической оболочки Linux), вы можете воспользоваться ключами, приведенными в табл. 20.5.
Использование методов объекта Canvas
Использование методов объекта CanvasВ этой части главы мы рассмотрим методы объекта Canvas, которые позволяют рисовать простые графические объекты.
Рисование линий и ломаных
Объект канвы позволяет чертить прямые линии и ломаные линии.
Прямая линия — это точки отрезка прямой, проходящей через две заданные точки.
Ломаная линия — это несколько прямых линий, которые соединены между собой конечными точками.
Для рисования прямой линии на канве вы можете использовать метод LineTo. Данный метод чертит линию из текущей позиции пера в точку, указанную вами, и делает конечную точку линии текущей позицией пера.
Приведенный ниже пример (листинг 13.9) чертит диагональные линии формы каждый раз, когда форма перерисовывается (обновляется). Для этого мы записываем код в обработчик события формы OnPaint.
Использование оператора as
Использование оператора asОбъекты, поддерживающие интерфейсы, могут использовать оператор as для динамического присоединения интерфейса. Например,
procedurePaintObjects(P: TInterfacedObject) var
X: IPaint; begin
X := P as IPaint; {операторы} end;
В данном примере переменная Р имеет тип TInterfacedObject. Данная переменная может быть назначена переменной X, как ссылка на интерфейс IPaint. Для данного назначения компилятор генерирует код для вызова метода QueryIntetface, относящегося к интерфейсу IUnknown переменной P. Такое назначение возможно, даже если Р не поддерживает данный интерфейс. То есть компилятор не выдаст ошибку при таком назначении.
Во время выполнения вышеприведенного примера либо успешно происходит присваивание
Х:= Р as IPaint;
либо генерируется исключительная ситуация.
При использовании оператора as вы должны выполнять следующие требования:
Использование пакетов в приложениях
Использование пакетов в приложенияхДля того чтобы приложение, которое использует пакеты, благополучно запустилось, должны присутствовать в наличии все необходимые приложению файлы. Файлы so должны быть прописаны в путях приложения.
Примечание
При разработке коммерческих приложений обратите внимание на то, чтобы пользователи получили правильную версию файлов пакетов (so).
Для использования пакетов времени выполнения в вашем приложении нужно проделать следующие шаги:
1. Загрузите или создайте новый проект в среде Kylix.
2. В главном меню Kylix выберите Project/Options.
3. В открывшемся диалоговом окне выберите вкладку Packages (Рисунок 20.1).
4. Установите флажок Build with runtime package. Затем в открывшееся поле введите одно или несколько названий пакетов, которые вы хотите использовать в своем приложении. Вы можете воспользоваться также кнопкой Add для поиска необходимого пакета (Рисунок 20.2).
Использование пера
Использование пераСвойство Реn позволяет устанавливать атрибуты пера, которым производится рисование линий и точек, а также других геометрических фигур.
Перо имеет четыре собственных свойства, которые вы можете изменять:
Рассмотрим последовательно использование этих четырех свойств.
Цвет пера
Вы можете устанавливать цвет пера по своему усмотрению с помощью свойства Color во время исполнения приложения. Для этого нужно лишь присвоить соответствующее значение цвета свойству Color пера Реn.
В листинге 13.3 мы устанавливаем красный цвет пера (значение clRed) по нажатии кнопки Button1.
Использование специальных директив
Использование специальных директивИспользование директивы компилятора $IFDEF является достаточно разумным путем для разделения кода Windows и Linux в вашем межплатформенном приложении. Тем не менее, использование директивы $IFDEF делает код приложения более трудным для понимания, поэтому старайтесь применять эту директиву как можно реже.
Пользуясь директивой $IFDEF, следуйте нижеприведенным указаниям:
Класс TlnterfacedObject
Класс TlnterfacedObjectВ CLX Kylix определен класс TInterfacedObject, который служит базовым классом для объектов интерфейса. Данный класс определен в модуле Kylix System (листинг 10.4).
Классы и исключения
Классы и исключенияДанная глава расскажет вам, как использовать классы в среде Kylix. Кроме того, вы узнаете, что такое исключительная ситуация и как можно самостоятельно обрабатывать исключительные ситуации. Вы научитесь создавать обработчики исключений, а также генерировать собственные исключения.
Работа с классами в Kylix
Напомним основные положения о классах, которые были достаточно подробно рассмотрены в пятой главе книги.
Класс — это абстрактное определение, инкапсулирующее понятия: свойства, методы, события и члены класса (например, локальные переменные, объявленные внутри класса).
Когда вы создаете экземпляр класса — он называется объектом. Термин "объект" часто в документации по Kylix используется более свободно, и, где различие между объектом и классом, не важно. Этот термин может обозначать класс, от которого данный объект произошел.
Часто программисту приходится создавать собственные классы для решения каких-либо задач, не предусмотренных стандартными классами CLX Kylix. Класс, который вы создаете, может иметь в качестве предка основной класс TObject или его потомок. Объявление нового класса содержит три допустимые секции, обеспечивающие доступ к полям и методам класса:
Тyре
TClassName = Class(TObject)
public
{public fields}
{public methods} protected
{protected fields}
{protected methods} private
{private fields}
{private methods} end;
Kylix позволяет вам объявлять самостоятельно нужные классы для использования их в своих приложениях. Некоторые версии Kylix включают в себя специальные возможности, которые называются завершение класса. Данные возможности позволяют упростить работу программиста по созданию нового класса. Упрощение происходит благодаря автоматическому генерированию скелета кода для членов класса, который вы определяете.
Ниже перечислены шаги, позволяющие вам объявить новый класс.
TMyClass = class; {Новый класс является потомком класса TObject} public
...
private
...
published{Класс является потомком TPersistent или его потомков}
. . .
Примечание
Вы должны включить в описание класса секцию published только в том случае, если ваш класс является потомком класса TPersistent или его потомков.
Если вы хотите создать свой класс как потомка определенного класса, то вам необходимо указать это в объявлении класса:
TMyClass = class(TParentClass); {Новый класс является потомком класса TParentClass}
Например,
type TMyButton = class(TButton)
property Size: Integer;
procedure DoSomething;
end;
В этом примере мы определяем класс TMyButton, который является потомком класса TButton и будет иметь все свойства, события и методы своего родителя, а также дополнительное свойство Size целого типа и процедуру DoSomething.
Если ваша версия Kylix включает завершение класса, выполните следующие действия: поместите курсор внутри определения методов класса в секции интерфейса (interface) и нажмите комбинацию клавиш
В приведенном ниже примере, если у вас есть завершение класса, Kylix добавит слова read и write, включая все поддерживаемые поля и методы:
type TMyButton = class (TButton)
property Size: Integer read FSize write SetSize;
procedure DoSomething;
private
FSize: Integer;
procedure SetSize(const Value: Integer);
Он также добавит следующий код в секцию реализации модуля:
{ TMyButton }
procedure TMyButton.DoSomething;
begin
end;
procedure TMyButton.SetSize(const Value: Integer);
begin
FSize := Value;
end;
Теперь заполните методы. Для примера, если вы хотите, чтобы кнопка издавала звуковой сигнал каждый раз при вызове метода DoSomething, добавьте команду Bеер между словами begin и end данного метода в разделе реализации:
{ TMyButton }
procedure TMyButton.DoSomething;
begin
Beep;
end;
procedure TMyButton.SetSize(const Value: Integer);
begin
FSize := Value;
DoSomething;
end;
Примечание
Наша кнопка будет также издавать звуковой сигнал в случае, если вы вызовете метод SetSize для изменения ее размера.
Вперед
Классы
КлассыКлассы — это специальные типы данных языка Object Pascal, которые используются для описания объектов.
В состав класса входят поля, свойства и методы. Подробное их описание смотрите далее в этой главе.
Типичное определение нового класса выглядит следующим образом:
type Имя класса = class (Класс-предок)
{Список состава класса} private
{частные описания} protected {защищенные описания} public
{общедоступные описания} published
{опубликованные описания} end; где Имя класса — любое корректное имя (выбирается произвольно), Класс-предок — название класса, наследником которого является создаваемый класс, а Cписок состава класса содержит свойства и методы нового класса.
Для каждого элемента класса можно установить разную видимость. Для этого предназначены четыре ключевых слова: private, protected, public и published.
Видимость элемента класса определяет, где в программе и как будет виден данный элемент класса. Минимальная видимость элемента класса задается ключевым словом private, ключевое слово protected определяет средний уровень видимости. Наконец, public и published определяют наивысшую степень доступности.
Если перед описанием элемента класса не ставится ключевое слово, определяющее его степень видимости, то считается, что видимость элемента такая же, как и у предыдущего элемента класса.
Рассмотрим все четыре ключевых слова более подробно.
В Kylix имеется понятие абстрактного класса.
Абстрактный класс описывает несуществующий объект. Он нужен для того, чтобы описать некоторые фундаментальные свойства и методы объектов, которые будут созданы из абстрактного класса.
Все объекты в Kylix созданы из абстрактного класса TObject. Класс TObject — предок многих простых классов. Этот класс объединяет в себе основные функции, которые свойственны всем объектам Kylix. TObject обеспечивает:
Класс называется прямым потомком класса TObject, если он произведен непосредственно от класса TObject.
Класс называется косвенным потомком от класса TObject, если он произведен от класса, являющегося прямым или косвенным потомком класса TObject (то есть произведен от промежуточного класса).
Примечание
В другой литературе можно встретить названия дочерний класс и класс-потомок. Дочерний класс — это прямой потомок, а класс-потомок — это косвенный потомок в терминологии данной книги.
Если при создании нового класса не указывается родительский класс, то считается, что родитель — класс TObject.
Назад Вперед
Команды компоненты и другие элементы перенос которых невозможен
Команды, компоненты и другие элементы, перенос которых невозможенНекоторые специфичные для Windows возможности не могут быть перенесены напрямую в среду Kylix. Такие элементы, как COM, ActiveX, OLE, BDE и ADO недоступны в среде Kylix. В табл. 21.2 перечислены элементы, отличающиеся в средах Linux и Windows, а также эквивалентные элементы Kylix, если таковые имеются.
это текст, который игнорируется компилятором
КомментарииКомментарий — это текст, который игнорируется компилятором и нужен для пояснения работы отдельных частей программы. Комментарии широко используются программистами для быстрого понимания написанного. Комментарий может располагаться в любом месте программы (если он не вставлен внутри слова или оператора Object Pascal).
Имеется несколько способов записи комментария:
{ многострочныйкомментарий }
(* еще один
многострочный комментарий *)
/ / текст, расположенный справа от двойного слэша, также является/ / комментарием, только однострочнымКроме прямого предназначения, комментарии можно использовать для того, чтобы на время запретить выполнение некоторых операторов. Это очень полезно при отладке программ:
if tim>50 thenbegin timer1. Enabled: =false ;
/ / form2.showmodal; end;
Назад Вперед
Компиляция пакета
Компиляция пакетаКак откомпилировать пакет, мы с вами уже знаем, осталось только рассмотреть некоторые особенности компиляции.
Для начала рассмотрим директивы компилятора, которые могут включаться в файл пакета и файлы модулей пакета (табл. 20.4).
Компонент Clients в окне модуля данных
Рисунок 18.3. Компонент Clients в окне модуля данныхСоздадим поля первым способом. Для этого дважды щелкнем на свойстве FieldDefs компоненту Clients. При этом откроется диалоговое окно добавления новых полей (Рисунок 18.4).
Компоненты для работы с базами данных
Компоненты для работы с базами данныхВ этой главе мы рассмотрим основные компоненты, предназначенные для работы с базами данных. Компоненты расположены на вкладках Data Access, dbExpress и Data Controls.
Вкладка Date Access
На этой вкладке расположено всего три компонента, которые мы и рассмотрим.
Компонент TDataSource - обеспечивает интерфейс между набором данных и компонентом, отображающим данные. В табл. 16.1 приведены его основные свойства и их описания.
Консольные приложения
Консольные приложенияКонсольные приложения — это 32-разрядные приложения, которые могут работать без загруженного графического интерфейса Linux.
Для создания нового консольного приложения выберите пункт главного меню Kylix File/New и в появившемся диалоговом окне выберите пиктограмму Console Application (Рисунок 10.5).
Координация потоков
Координация потоковПри работе с потоками, на этапе первоначального знакомства с ними, неизбежны ошибки. Особенно неприятны ошибки, связанные с конфликтами потоков, обращающихся к разделяемым ресурсам, а также глобальным переменным. Также иногда бывает необходимо, чтобы потоки работали слаженно Например, после выполнения какого-либо события в одном потоке вам необходимо, чтобы возникало какое-либо постоянное событие в другом потоке. Все это можно объединить общим названием координации потоков. Рассмотрим, как можно эффективно управлять потоками для достижения каких-либо задач.
Для начала определим, какие способы хранения локальных переменных потока нам предоставляет Kylix. Таких способов три.
Рассмотрим два других способа хранения локальных переменных потока. Второй способ проще и эффективнее чем третий (листинг 14.8).
Координаты точек задаваемых при вызове метода Arc
Рисунок 8.13. Координаты точек, задаваемых при вызове метода Arcдуги, которая находится на пересечении прямой, проходящей через центр окружности или эллипса и точки (X3, Y3). Точка (X4, Y4) определяет конечную точку дуги, которая находится на пересечении прямой, проходящей через центр окружности или дуги и точки (Х4, Y4). Дуга рисуется против часовой стрелки, от начальной до конечной точки (Рисунок 8.13).
Для Рисунок 8.13 можно привести такой пример вызова метода Arc:
Image1,Canvas.Arc (0,0, 200,100, 200,10, 0,0);
Image1.Picture.Assign (Clipboard);
и, наоборот, из компонента в буфер обмена
Clipboard.Assign (Image1.Picture);
Form1.ChangeScale (2,1);
При выполнении данной строки размеры формы Form1 увеличатся в два раза.
Для уменьшения размеров, например в три раза, нужно задать значение M, равное eдинице, а значение D — равное трем:
Form1.ChangeScale (1,3);
ListBox1.Clear;
Memo1. Clear;
Кроссплатформенные Интернетприложения
Кроссплатформенные Интернет-приложенияИнтернет-приложения — это приложения типа клиент-сервер, которые используют стандартные Интернет-протоколы для обеспечения связи между клиентом и сервером. Так как ваши приложения используют стандартные Интернет-протоколы, вы можете легко сделать ваше приложение межплатформенным. Например, программа — сервер Интернет-приложения соединяется с клиентом при помощи специального программного обеспечения, называемого Web-сервером. Приложение для сервера пишется обычно под конкретную операционную систему, но может быть и межплатформенным. Клиентские приложения обычно кросс-платформенные.
Среда Kylix позволяет вам создать приложение Web-сервера для работы под Linux. Это такие приложения, как CGI- или Apache-серверы. В Windows вы можете создать другие типы Web-серверов, например Microsoft Server DLLs (ISAPI), Netscape Server DLLs (NSAPI) и приложения Windows CGI. Приложения CGI и некоторые приложения, использующие WebBroker, могут запускаться как в Windows, так и в Linux.
Перенос Интернет-приложений в среду Linux
Если у вас есть готовое Интернет-приложение, которое необходимо перенести в Linux, и оно применяет WebBroker и написано с использованием интерфейса WebBroker без специфичных для Windows вызовов API, достаточно будет простой перекомпиляции его в Linux, естественно, с учетом вышеописанной процедуры переноса простого Windows-приложения в Linux.
Если ваше приложение использует ISAPI, NSAPI, Windows CGI или другие Web API, осуществить перенос будет довольно сложно. Вам придется просматривать приложение и преобразовывать все вызовы API в вызовы Apache или CGI. Кроме того, вам понадобится сделать все изменения, необходимые для переноса обычного Windows-приложения в Linux.
Итак, мы рассмотрели основные методы переноса приложений из среды Windows в Linux. С учетом вышеизложенного материала вы можете создавать межплатформенные приложения.
Линии тренда
Линии тренда
Тренды всегда заканчиваются, и его можно использовать, чтобы подтвердить разворот. Линии тренда - также очень мощный подтверждающий фактор разворотов тренда.
Объявление интерфейса
Листинг 10.1.Объявление интерфейсаtype IEdit = interface
procedure Copy; stdcall; procedure Cut; stdcall; procedure Paste; stdcall; function Undo: Boolean; stdcall; end;
Примечание
Тем читателям, которые имеют слабое представление о создании компонентов и новых классов, советуем прочитать пятую часть книги, посвященную созданию собственных компонентов и модификации уже существующих.
Нельзя создать экземпляр интерфейса при помощи интерфейса. Для получения экземпляра интерфейса вам нужно объявить его в классе, содержащем данный интерфейс. Таким образом, нужно определить класс, который содержит необходимый интерфейс в списке своих родителей (листинг 10.2).
Объявление класса содержащего интерфейс
Листинг 10.2.Объявление класса, содержащего интерфейсTEditor = class(TInterfacedObject, IEdit)
procedure Copy; stdcall;
procedure Cut; stdcall; procedure Paste; stdcall;
function Undo: Boolean; stdcall; end;
Как уже было отмечено выше, использование интерфейсов позволяет нескольким классам общаться с помощью общего интерфейса. При этом не обязательно наличие одного базового класса-предка. Следует помнить, что интерфейс — это тип с управляемым временем жизни, т. е. он автоматически при инициализации принимает значение nil, обладает счетчиком ссылок и автоматически уничтожается при выходе за пределы своей области видимости.
Вперед
Описание базового интерфейса IUnknown
Листинг 10.3.Описание базового интерфейса IUnknowntype
IUnknown = interface
[ '{ 00000000-0000-0000-C000-000000000046} ' ]
function QueryInterface(const IID: TGUID; out Obj): Integer; stdcall;
function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; end;
Синтаксис описания интерфейса похож на описание класса. Главное отличие заключается в том, что интерфейс может быть связан с глобальным уникальным идентификатором (Global Unique Identifier, GUID).
GUID — это 128-разрядное целое число, которое используется для уникальной идентификации интерфейсов. Так как в 128-ми разрядах можно закодировать большое количество чисел, GUID гарантирует глобальную уникальность идентификатора интерфейса. То есть, практически невозможно, чтобы на двух компьютерах GUID совпал. Алгоритм генерации GUID основан на аппаратной части компьютера (частота процессора, номер сетевой карты и т. д.). В результате работы алгоритма, который может быть реализован с помощью функции API CoCreateGUID( ), получается запись типа TGUID. Эту запись можно определить в виде строки следующего формата:
'{хххххххх-хххх-хххх-хххх-хххххххххххх}'
Для создания нового GUID в среде Kylix достаточно нажать комбинацию клавиш
+
+
при работе редактора кода.
Итак, интерфейс IUnknown поддерживает три метода, которые наследуются всеми интерфейсами:
Определение класса TInterfacedObject
Листинг 10.4. Определение класса TInterfacedObjecttype
TInterfacedObject = class (TObject, IInterface) protected
FRefCount: Integer;
function QueryInterface(const IID: TGUID; out Obj) : HResult; stdcall;
function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; public
procedure AfterConstruction; override; procedure BeforeDestruction; override; class function NewInstance: TObject; override; property RefCount: Integer read FRefCount; end;
Как вы видите, данный класс в качестве родителей имеет класс TObject и интерфейс IInterface. Класс TInterfacedObject позволяет достаточно легко создавать классы, поддерживающие интерфейсы. Например,
type
TMyObjInterfaced = class(TInterfacedObject, IPaint)
end;
На вышеприведенном примере мы определяем новый класс TMyObjInterfaced, который является прямым потомком класса TInterfacedObject и поддерживает некий интерфейс IPaint.
Назад Вперед
Использование ключевого слова implements
Листинг 10.5. Использование ключевого слова implementsunit cadapt; type
IRGB8bit = interface
['{1d76360a-f4f5-lldl-87d4-00c04fbl7199}']
function Red: Byte;
function Green: Byte;
function Blue: Byte; end;
IColorRef = interface
['{ld76360b-f4f5-11dl-87d4-00c04fbl7199}']
function Color: Integer; end;
TRGB8ColorRefAdapter = class(TInterfacedQbject, IRGB8bit, IColorRef) private
FRGB8bit: IRGB8bit;
FPalRelative: Boolean; public
constructor Create(rgb: IRGB8bit);
property RGB8Intf: IRGB8bit read FRGB8bit implements IRGB8bit;
property PalRelative: Boolean read FPalRelative write FPalRelative; function Color: Integer; end; implementation
constructor TRGB8ColorRefAdapter.Create(rgb: IRGB8bit);
begin
FRGB8bit := rgb; end;
function TRGB8ColorRefAdapter.Color: Integer; begin
if FPalRelative then
Result := PaletteRGB(RGB8Intf.Red, RGB8Intf.Green, RGB8Intf.Blue) else Result := RGB(RGB8Intf,Red, RGB8Intf.Green, RGB8Intf.Blue);
end; end. Назад Вперед
Код автоматически создаваемой для MDIприложения
Листинг 10.6.Код,автоматически создаваемой для MDI-приложенияunit clxmain;
interface
uses SysUtils, Classes, QForms, OImgList , QStdActns, QActnList , QDialogs, QMenus, QTypes, QComCtrls, QControls, QExtCtrls;
type
TMainForm - class(TForm) MainMenu1: TMainMenu; File1: TMenuItem; FileNewItem: TMenuItem; FileOpenItem; TMenuItem; FileCloseItem: TMenuItem; Window1: TMenuItem; Help1: TMenuItem; N1: TMenuItem; FileExitItem: TMenuItem; WindowCascadeItem: TMenuItem; WindowTileItem: TMenuItem; HelpAboutItem: TMenuItem; OpenDialog: TOpenDialog; FileSaveItem: TMenuItem; FileSaveAsItem: TMenuItem; Edit1: TMenuItem; CutItem: TMenuItem; CopyItem: TMenuItem; PasteItem: TMenuItem;
WindowMinimizeItem: TMenuItem; StatusBar: TStatusBar; ActionList1: TActionList; EditCut1: TEditCut; EditCopy1: TEditCopy; EditPaste1: TEditPaste; FileNew1: TAction; FileSave1: TAction; FileExit1: TAction; FileOpen1: TAction; FileSaveAs1: TAction; WindowCascade1: TWindowCascade; WindowMinimizeAll1: TWindowMiniraizeAll; HelpAbout1: TAction; FileClose1: TWindowClose; WindowTileItem2: TMenuItem; ToolBar2: TToolBar; ToolButton1: TToolButton; ToolButton2: TToolButton; ToolButton3: TToolButton; ToolButton4: TToolButton; ToolButton5: TToolButton; ToolButton6: TToolButton; ToolButton9: TToolButton; ToolButton7: TToolButton; ToolButton8: TToolButtun; ToolButton10: TToolButton; ToolButton11: TToolButton; WindowClose1: TWindowClose; WindowTile1: TWindowTile; ToolButton12: TToolButton; ImageList1: TImageList;
procedure FileNew1Execute(Sender: TObject);
procedure FileOpen1Execute(Sender: TObject);
procedure HelpAbout1Execute(Sender: TObject);
procedure FileExit1Execute(Sender: TObject);
private
{ Private declarations}
procedure CreateMDIChild(const Name: string);
public
{ Public declarations } end;
var
MainForm: TMainForm; implementation
{$R *.xfm}
uses clxchildwin, clxabout;
procedure TMainForm.CreateMDIChild(const Name: string);
var
Child: TMDIChild; begin { создание нового дочернего MDI-окна },
Child := TMDIChild.Create(Application);
Child.Caption := Name;
if FileExists(Name) then Child.Memo1.Lines.LoadFromFile(Name);
end;
procedure TMainForm.FileNew1Execute(Sender: TObject);
begin
CreateMDIChild('NONAME' + IntToStr(MDIChildCount + 1));
end;
procedure TMainForm.FileOpen1Execute(Sender: TObject);
begin
if OpenDialog.Execute then
CreateMDIChild(OpenDialog.FileName);
end;
procedure TMainForm.HelpAbout1Execute(Sender: TObject);
begin
AboutBox.ShowModal; end;
procedure TMainForm.FileExit1Execute (Sender: TObject);
begin
Close; end; end.
Назад Вперед
Заготовка для консольного приложения
Листинг 10.7. Заготовка для консольного приложенияprogram Project1;
{$APPTYPE CONSOLE} // Директива компилятора, означающая, что приложение // будет консольным
begin end.
Формы в консольных приложениях отсутствуют.
Консольные приложения пишутся на языке Object Pascal. Создание таких приложений практически не отличается от создания программ на языке Pascal под DOS.
Назад
Список сетевых услуг содержащийся в файле services
Листинг 11.1.Список сетевых услуг,содержащийся в файле services# /etc/services:
# $Id: services,v 1.4 2000/05/15 15:54:48 chmouel Exp $
#
# Сетевые услуги Интернет
#
# номера портов как для TCP, так и для UDP; большинство портов используют
# оба эти протокола.
# Обновлено RFC 1700, ``Ассоциированные номера" (Октябрь 1994).
# Не все порты включены в список, только наиболее используемые.
tcpmux 1/tcp
echo 7/tcp
echo 7/udp
discard 9/tcp sink null
discard 9/udp sink null
systat 11/tcp users
daytime 13/tcp
daytime 13/udp
netstat 15/tcp
qotd 17/tcp quote
msp 18/tcp # протокол отправки сообщений
msp 18/udp # протокол отправки сообщений
chargen 19/tcp ttytst source
chargen 19/udp ttytst source
ftp-data 20/tcp
ftp 21/tcp
fsp 21/udp fspd
ssh 22/tcp # SSH удаленный протокол авторизации
ssh 22/udp # SSH удаленный протокол авторизации
telnet 23/tcp
# 24 - для частного использования smtp 25/tcp mail
# 26 - не назначен
time 37/tcp timserver
time 37/udp timserver
rlp 39/udp resource # расположение ресурсов
nameserver 42/tcp name # IEN 116
whois 43/tcp nicname
re-mail-ck 50/tcp # Удаленный протокол проверки почты
re-mail-ck 50/udp # Удаленный протокол проверки почты
domain 53/tcp nameserver # имя сервера домена
domain 53/udp nameserver
mtp 57/tcp
bootps 67/tcp # ВООТР-сервер
bootps 67/udp
bootpc 68/tcp # ВООТР-клиент
bootpc 68/udp
tftp 69/udp
gopher 70/tcp # Internet Gopher
gopher 70/udp
rje 77/tcp netrjs
finger 79/tcp
www 80/tcp http # WorldWideWeb HTTP
www 80/udp # HyperText Transfer Protocol
link 87/tcp ttylink
kerberos 88/tcp kerberos5 krb5 # Kerberos v5
kerberos 88/udp kerberos5 krb5 # Kerberos v5
supdup 95/tcp
# 100 - reserved
hostnames 101/tcp hostname
iso-tsap 102/tcp tsap # часть ISODE.
csnet-ns 105/tcp cso-ns
csnet-ns 105/udp cso-ns
# poppassd (Eudora) использует порты, которые уже были ассоциированы
# с другими услугами. Ниже приведен список poppassd.
# Это позволяет программам запрашивать данные услуги.
rtelnet 107/tcp # удаленный Telnet
rtelnet 107/udp
pop2 109/tcp pop-2 postoffice # POP версии 2
pop2 109/udp pop-2
рор3 110/tcp pop-3 # POP версии 3
рор3 110/udp pop-3
sunrpc 111/tcp portmapper # RPC 4.0 portmapper TCP
sunrpc 111/udp portmapper # RPC 4.0 portmapper UDP
auth 113/tcp authentication tap ident
sftp 115/tcp
uucp-path 117/tcp
nntp 119/tcp readnews untp # USENET News Transfer Protocol
ntp 123/tcp
ntp 123/udp # Network Time Protocol
netbios-ns 137/tcp # имя сервиса NETBIOS
netbios-ns 137/udp
netbios-dgm 138/tcp # NETBIOS Datagram-услуга
netbios-dgm 138/udp
netbios-ssn 139/tcp
netbios-ssn 139/udp
imap2 143/tcp imap # Interim Mail Access Proto v2
imap2 143/udp imap
snmp 161/udp # Simple Net Mgmt Proto
snmp-trap 162/udp snmptrap
cmip-man 163/tcp
cmip-man 163/udp
cmip-agent 164/tcp
amp-agent 164/udp
xdmcp 177/tcp # X Display Mgr. Control Proto
xdmcp 177/udp
nextstep 178/tcp NeXTStep NextStep # Окно NeXTStep
nextstep 178/udp NeXTStep NextStep # сервер
bgp 179/tcp # Border Gateway Proto.
bgp 179/udp
prospero 191/tcp # Cliff Neuman's Prospero
prospero 191/udp
irс 194/tcp # Internet Relay Chat
irc 194/udp
smux 199/tcp # SNMP Unix Multiplexer
smux 199/udp
at-rtmp 201/tcp # маршрутизация AppleTalk
at-rtmp 201/udp
at-nbp 202/tcp # привязка имен AppleTalk
at-nbp 202/udp
at-echo 204/tcp # эхо AppleTalk
at-echo 204/udp
at-zis 206/tcp # информация о часовом поясе AppleTalk
at-zis 206/udp
qmtp 209/tcp # The Quick Mail Transfer Protocol
qmtp 209/udp # The Quick Mail Transfer Protocol
z3950 210/tcp wais # база данных NISO Z39.50
z3950 210/udp wais
ipx 213/tcp # IPX
ipx 213/udp
imap3 220/tcp # Interactive Mail Access
imap3 220/udp # Protocol v3
rpc2portmap 369/tcp
rpc2portmap 369/udp # Coda portmapper
codaauth2 370/tcp
codaauth2 370/udp # сервер авторизации Coda
ulistserv 372/tcp # UNIX Listserv
ulistserv 372/udp
ldap 389/tcp # Lightweight Directory Access Protocol
ldap 389/udp # Lightweight Directory Access Protocol
https 443/tcp # MCom
https 443/udp # MCom
snpp 444/tcp # Simple Network Paging Protocol
snpp 444/udp # Simple Network Paging Protocol
saft 487/tcp ft Simple Asynchronous File Transfer
saft 487/udp # Simple Asynchronous File Transfer
npmp-local 610/tcp dqs313_qmaster # npmp-local / DQS
npmp-local 610/udp dqs313_qmaster # npmp-local / DQS
npmp-gui 611/tcp dqs313_execd # npmp-gui / DQS
npmp-gui 611/udp dqs313_execd ft npmp-gui / DQS
hmmp-ind 612/tcp dqs313_intercell# HMMP Indication / DQS
hmmp-ind 612/udp dqs313_intercell# HMMP Indication / DQS
#
# Особые сервисы UNIX
#
exec 512/tcp
biff 512/udp comsat
login 513/tcp
who 513/udp whod
shell 514/tcp and # без использования пароля
syslog 514/udp
printer 515/tcp spooler # линейный пул принтера
talk 517/tcp
ntalk 518/udp
route 520/udp router routed # RIP
timed 525/udp timeserver
tempo 526/tcp newdate
courier 530/tcp rpc
conference 531/tcp chat
netnews 532/tcp readnews
netwall 533/udp # для непредвиденных передач
uucp 540/tcp uucpd # uucp daemon
afpovertcp 548/tcp # AFP над TCP
afpovertcp 548/udp # AFP над TCP
remotefs 556/tcp rfs_server rfs # удаленная файловая система Brunhoff
klogin 543/tcp # Kerberized `rlogin' (v5)
kshell 544/tcp krcmd # Kerberized `rsh' (v5)
kerberos-adm 749/tcp. # Kerberos `kadmin' (v5)
#
webster 765/tcp # сетевой словарь
webster 765/udp
#
#
ingreslock 1524/tcp
ingreslock 1524/udp
prospero-np 1525/tcp # Prospero non-privileged
prospero-np 1525/udp
datametrics 1645/tcp old-radius # datametrics / старый радиус вхождения
datametrics 1645/udp old-radius # datametrics / старый радиус вхождения
sa-msg-port 1646/tcp old-radacct # sa-msg-port / старый radacct вхождения
sa-msg-port 1646/udp old-radacct # sa-msg-port / старый radacct вхождения
radius 1812/tcp # радиус
radius 1812/udp # радиус
radacct 1813/tcp # радиус учета
radacct 1813/udp # радиус учета
cvspserver 2401/tcp # CVS client/server operations
cvspserver 2401/udp # CVS client/server operations
venus 2430/tcp # codacon port
venus 2430/udp # Venus callback/wbc interface
venus-se 2431/tcp # tcp side effects
venus-se 2431/udp # udp sftp side effect
codasrv 2432/fccp # не используется
codasrv 2432/udp # порт сервера
codasrv-se 2433/tcp # tcp side effects
codasrv-se 2433/udp # udp sftp side effect
mysql 3306/tcp # MySQL
mysql 3306/udp # MySQL
rfe 5002/tcp # Radio Free Ethernet
rfe 5002/udp # Используется только UDP
cfengine 5308/tcp # CFengine
cfengine 5308/udp # CFengine
bbs 7000/tcp # BBS
#
#
kerberos4 750/udp kerberos-iv kdc # Kerberos (сервер) udp
kerberos4 750/tcp kerberos-iv kdc # Kerberos (сервер) tcp
kerberos_master 751/udp # Kerberos авторизация
kerberos_master 751/tcp # Kerberos авторизация
passwd_server 752/udp # Kerberos сервер passwd
krb_prop 754/tcp # Kerberos
krbupdate 760/tcp kreg # регистрация Kerberos
kpasswd 761/tcp kpwd # Kerberos "passwd"
kpop 1109/tcp # Kerberos
knetd 2053/tcp # Kerberos
zephyr-srv 2102/udp # сервер Zephyr
zephyr-clt 2103/udp # Zephyr serv-hm -соединение
zephyr-hm 2104/udp # Zephyr менеджер хоста
eklogin 2105/tcp # Kerberos зашифрованный rlogin
#
# Неофициальные, но необходимые (для NetBSD) услуги
#
supfilesrv 871/tcp # сервер SUP
supfiledbg 1127/tcp # отладчик SUP
#
# Услуги протокола Datagram Delivery
#
rtmp 1/ddp
nbp 2/ddp # Протокол связывания имен
echo 4/ddp # Эхо-протокол AppleTalk
zip 6/ddp # Протокол часового пояса
#
# Услуги, добавленные для Debian GNU/Linux
#
poppassd 106/tcp # Eudora
poppassd 106/udp # Eudora
mailq 174/udp
mailq 174/tcp
ssmtp 465/tcp # SMTP над SSL
gdomap 538/tcp # распределенные объекты GNUstep
gdomap 538/udp # распределенные объекты GNUstep
snews 563/tcp # NNTP над SSL
ssl-ldap 636/tcp # LDAP над SSL
omirr 808/tcp omirrd # Онлайн-зеркало
omirr 808/udp omirrd # Онлайн-зеркало
rsync 873/tcp # rsync
rsync 873/udp # rsync
swat 901/tcp # inetd
simap 993/tcp # IMAP над SSL
sрор3 995/tcp # POP-3 над SSL
socks 1080/tcp # socks-прокси сервер
socks 1080/udp # socks-прокси сервер
rmtcfg 1236/tcp # Удаленный сервер конфигурирования
xtel 1313/tcp # minitel
support 1529/tcp # GNATS
cfinger 2003/tcp # GNU Finger
ninstall 2150/tcp # услуга ninstall
ninstall 2150/udp # услуга ninstall
afbackup 2988/tcp # система Afbackup
afbackup 2988/udp # система Afbackup
icp 3130/tcp # Internet Cache Protocol (Squid)
icp 3130/udp # Internet Cache Protocol (Squid)
postgres 5432/tcp # POSTGRES
postgres 5432/udp # POSTGRES
fax 4557/tcp # FAX (старый)
hylafax 4559/tcp # HylaFAX (новый)
noclog 5354/tcp # noclogd с TCP (nocol)
noclog 5354/udp # noclogd с UDP (nocol)
hostmon 5355/tcp # hostmon использующий TCP (nocol)
hostmon 5355/udp # hostmon использующий TCP (nocol)
ircd 6667/tcp # Internet Relay Chat
ircd 6667/udp # Internet Relay Chat
webcache 8080/tcp # WWW услуга кэширования
webcache 8080/udp # WWW услуга кэширования
tproxy 8081/tcp # Transparent Proxy
tproxy 8081/udp # Transparent Proxy
mandelspawn 9359/udp mandelbrot # сеть mandelbrot
amanda 10080/udp # Услуга сохранения amanda
kamanda 10081/tcp # Услуга сохранения amanda (Kerberos)
kamanda 10081/udp # Услуга сохранения amanda (Kerberos)
amandaidx 10082/tcp # Услуга сохранения amanda
amidxtape 10083/tcp # Услуга сохранения amanda
isdnlog 20011/tcp # система входа isdn
isdnlog 20011/udp # система входа isdn
vboxd 20012/tcp
vboxd 20012/udp
jserver 22273/tcp
binkp 24554/tcp # Binkley
binkp 24554/udp # Binkley
asp 27374/tcp # Протокол поиска адреса
asp 27374/udp # Протокол поиска адреса
tfido 60177/tcp # Ifmail
tfido 60177/udp # Ifmail
fido 60179/tcp # Ifmail
fido 60179/udp # Ifmail
#
# Локальные услуги
#
linuxconf 98/tcp
Все соединения, использующие сокеты, делятся на три типа:
Соединение-клиент подключает сокет-клиент локального компьютера к сокету-серверу на удаленном компьютере. Соединение создает сокет-клиент. Сначала сокет-клиент должен определить сокет-сервер, с которым необходимо соединиться. После чего происходит поиск этого сокета и, если сокет найден, сокет-клиент посылает серверу запрос на соединение. Сокет-сервер может не установить соединение сразу же после получения запроса. Сервер запоминает запрос и отвечает на него, как только появляется возможность. Как только сокет-сервер устанавливает соединение, он отсылает сокету-клиенту свое полное описание, после чего клиент завершает соединение.
Соединение-сервер прослушивает запросы сокетов на установление соединения. В случае, если сокет-клиент запрашивает от сокета-сервера соединение, сокет-сервер отсылает клиенту свое полное описание.
Соединение-слушатель - это пассивное соединение сервера, которое принципиально отличается от двух других типов соединений и является односторонним. В этом случае соединение с сокетами -клиентами не устанавливается, а происходит прослушивание и запись запросов на соединение, отправляемых сокетами-клиентами.
Каждый сокет может рассматриваться как конечная точка сетевого соединения. Все сокеты имеют собственные адреса, которые определяют:
Компонент TCPClient позволяет превратить ваше приложение в TCP/IP-клиент. Сокет-клиент позволяет вам указать сокет-сервер, с которым будет производиться соединение с помощью свойства RemoteHost. Данное свойство может содержать как сетевое имя компьютера, так и его IP-адрес. В дополнение к данному свойству компонент TCPClient имеет свойство RemotePort, которое определяет номер порта сервера, к которому будет производиться подключение. Вы можете указать номер порта либо имя услуги.
После установки этих двух свойств вы можете активизировать ваше соединение с помощью вызова метода open компонента TCPClient. Данный метод вызывается во время выполнения приложения. Если вы хотите, чтобы соединение устанавливалось автоматически после запуска приложения, установите свойство Active компонента TCPClient в true во время разработки приложения.
Как только соединение установлено, ваше приложение может отправлять или принимать данные. Передача данных может осуществляться двумя способами: блоками и асинхронно.
Асинхронная передача данных — передача данных, не разбитых на отдельные блоки, Для такой передачи данных установите свойства BlockMode сокета-клиента и сокета- сервера в bmNonBlocking.
Передана данных блоками осуществляется быстрее, чем асинхронная. Данный способ передачи данных применяется в тех случаях, когда необходимо продолжать выполнение приложения во время передачи данных. Таким обра-зом, приложение создает дополнительный поток для чтения или передачи данных (о процессах и потоках см. главу 14). Для установки блочного режима передачи данных установите свойства BlockMode клиента и сервера bmBlocking.
Для завершения соединения достаточно произвести вызов метода Close для компонента TCPClient. Кроме того, соединение может быть завершено и со стороны сервера. Если это происходит, то генерируется событие OnDisconnect.
Компонент TCPServer позволяет превратить приложение в ТСР/IР-сервер. Перед тем как сокет-сервер сможет прослушивать запросы клиентов, вы должны указать номер порта, который будет прослушивать сервер. Это можно сделать с помощью свойства LocalPort. Для начала прослушивания запросов клиентов нужно вызвать метод open компонента TCPServer. Для автоматического включения прослушивания во время запуска приложения установите свойство Active компонента TCPServer в true. Если вы хотите, чтобы сокет-сервер автоматически устанавливал соединение с клиентом при получении от него запроса, установите свойство AutoAccept компонента TCPServer в True. Для завершения текущего соединения можно вызвать метод Close или установить свойство Active компонента TCPServer в false.
Если отключение произведено клиентом, то на сервере произойдет событие OnDisconnect.
Для передачи данных используйте функцию SendBuf. Данная функция описана следующим образом:
function SendBuf(var buff; bufsize: integer; flags: integer = 0): integer;
dynamic;
При вызове этой функции приложение отсылает буфер данных через сокет. Переменная buf — это переменная, содержащая отсылаемые данные, а bufsize - размер буфера данных.
Для приема данных используется функция ReceiveBuf:
function ReceiveBuf(var buf; bufsize: integer; flags: integer =0): integer; dynamic;
Код обработки события OnPaint
Листинг 13.1.Код обработки события OnPaintprocedure TForm1.FormPaint(Sender: TObject);
begin
messagedlg('Произошло обновление формы' ,mtInformation, [mbOK], 0);
end; Теперь напишем код обработки события OnClick.
Построение ломанной линии
Листинг 13.10.Построение ломанной линииwith Canvas do begin
MoveTo(0, 0);
LineTo(12, 14);
LineTo(50, 30);
LineTo(130, 120);
LineTo(2l0,132);
end; Примечание
Если вы рисуете ломаные линии, то используйте метод Polyline, т. к. он выполняется значительно быстрее, чем вызов нескольких методов LineTo.
Рисование геометрических фигур
Для рисования эллипсов, окружностей или прямоугольников вы можете использовать методы Ellipse или Rectangle соответственно.
Приведем пример (листинг 13.11), в котором рисуется прямоугольник, занимающий левую верхнюю четвертую часть формы, а затем в этот прямоугольник вписывается эллипс (Рисунок 13.5).
Прямоугольник со вписанным эллипсом
Листинг 13.11.Прямоугольник со вписанным эллипсомprocedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.Rectangle(0, 0, ClientWidth div 2, ClientHeight div 2);
Canvas.Ellipse(0, 0, ClientWidth div 2, ClientHeight div 2);
end; Для того чтобы нарисовать на канве прямоугольник со скругленными углами, вы можете воспользоваться методом RoundRect.
Первые четыре параметра определяют координаты главной диагонали прямоугольника, остальные два показывают, как скругляются его углы.
Прямоугольник со скругленными углами procedure TForm1 FormPaint{Sender TObject);
begin
Листинг 13.12.Прямоугольник со скругленными углами
procedure TForm1.FormPaint{Sender: TObject);begin
Canvas.RoundRect(0, 0, ClientWidth div 2, ClientHeight div 2, 10, 10);
end;
Объявление типа и переменных
Листинг 13.13.Объявление типа и переменныхtype
TDrawingTool = (dtLine, dtRectangle, dtEllipse, dtRoundRect);
TForm1 = class(TForm)
. . . { объявление методов }
public
Drawing: Boolean;
Origin, MovePt: TPoint;
DrawingTool: TDrawingTool; { переменная, которая будет содержать текущий
инструмент }
end;
Расположим на панели инструментов четыре кнопки SpeedButton, каждая из которых будет означать линию, прямоугольник, эллипс или прямоугольник со скругленными углами. Теперь нужно для каждой кнопки написать обработчик события OnClick, в котором необходимо присвоить соответствующее значение переменной DrawingTool (листинг 13.14).
Обработчики нажатия кнопок
Листинг 13.14. Обработчики нажатия кнопокprocedure TForm1.LineButtonClick{Sender: TObject);
{ Кнопка линии } begin
DrawingTool := dtLine; end;
procedure TForm1.RectangleButtonClick(Sender: TObject);
{ Кнопка
прямоугольника } begin
DrawingTool := dtRectangle; end; procedure TForm1.EllipseButtonClick (Sender: TObject);
{ Кнопка эллипса } begin
DrawingTool := dtEllipse; end;
procedure TForm1.RoundedRectButtonClick(Sender: TObject}; { Кнопка
прямоугольника со скругленными углами } begin
DrawingTool := dtKoundRect; end; Теперь нам осталось написать лишь обработчики событий движения мыши (OnMouseMove) и отпускания левой кнопки мыши (OnMouseUр). Эти обработчики представлены в листингах 13.15 и 13.16.
Обработчик события OnMouseup
Листинг 13.15.Обработчик события OnMouseupprocedure TForm1. FormMouseUp (Sender: TObject; Button TMouseButton; Shift: TShiftState; X ,Y: Integer);
begin
case DrawingTool of dtLine: begin
Canvas.MoveTo(Origin.X, Origin. Y);
Canvas.LineTo(X, Y) end;
dtRectangle: Canvas.Rectangle{Origin.X, Origin.Y, X, Y);
dtEllipse: Canvas.Ellipse(Origin.X, Origin.Y, X, Y);
dtRoundRect: Canvas.RoundRect(Origin.X, Origin.Y, X, Y, (Origin.X - X} div 2, (Origin.Y - Y) div 2);
end;
Drawing := False; end;
Обработчик события OnMouseMove
Листинг 13.16.Обработчик события OnMouseMoveprocedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if Drawing then
begin
Canvas.Pen.Mode := pmNotXor; case DrawingTool of dtLine: begin
Canvas.MoveTo(Origin.X, Origin.Y);
Canvas.LineTo(MovePt.X, MovePt.Y);
Canvas.MoveTo(Origin.X, Origin.Y);
Canvas.LineTo(X, Y);
end; dtRectangle: begin
Canvas.Rectangle(Origin.X, Origin.Y, MovePt.X, MovePt.Y);
Canvas.Rectangle(Origin.X, Origin.Y, X, Y);
end;
dtEllipse: begin
Canvas.Ellipse(Origin.X, Origin.Y, X, Y);
Canvas.Ellipse(Origin.X, Origin.Y, X, Y);
end;
dtRoundRect: begin
Canvas.RoundRect(Origin.X, Origin.Y, X, Y, (Origin.X - X) div 2, (Origin.Y - Y) div 2);
Canvas.RoundRect(Origin.X, Origin.Y, X, Y,
(Origin.X - X) div 2, (Origin.Y - Y) div 2);
end; end;
MovePt := Point(X, Y);
end; Canvas.Pen.Mode := pmCopy; end; Назад Вперед
Создание объекта Bitmap
Листинг 13.17.Создание объекта Bitmapprocedure TForm1.FormCreate(Sender: TObject);
var Bitmap: TBitmap; {временная переменная для хранения графического образа}
begin
Bitmap := TBitmap.Create;{ создаем графический объект }
Bitmap.Width := 200; { устанавливаем начальную ширину }
Bitmap.Height := 200; { и начальную высоту объекта Bitmap }
Image.Picture.Graphic := Bitmap; { присваиваем созданный графический
объект компоненту Image } Bitmap.Free; { Нам больше не нужен графический объект, поэтому
уничтожаем его } end; Если вы записали вышеприведенный код в обработчике события OnCreate формы Form1 и запустили приложение, то вы сможете увидеть в клиентской части формы белый квадрат, представляющий собой как бы заготовку для изображения. Если вы уменьшите окно таким образом, чтобы изображение не помещалось в нем, автоматически появятся полосы прокрутки.
В данной заготовке можно осуществлять любые графические операции. Для этого следует воспользоваться канвой компонента Image.
Для работы с линиями объекта Bitmap имеется свойство ScanLine, которое позволяет получать информацию о цветах пикселов одной линии в виде массива RGB.
Пример, приведенный в листинге 13.18, показывает, как можно использовать свойство ScanLine для одновременного получения пикселов одной линии.
Прямая работа с Bitmap
Листинг 13.18.Прямая работа с Bitmapprocedure TForm1.Button1Click(Sender: TObject);
// Данный пример показывает, как можно рисовать напрямую в Bitmap
var
х,y : integer; Bitmap : TBitmap; P : PByteArray; begin
Bitmap := TBitmap.create; try
if OpenDialog1.Execute then begin
Bitmap.LoadFromFile(OpenDialog1.FileName);
for y := 0 to Bitmap.height -1 do begin
P : = Bitmap. ScanLine [y];
for x := 0 to Bitmap.width -1 do
Р[х] := y; end; end;
canvas.draw(0,0,Bitmap);
finally Bitmap.free; end; end; Назад Вперед
Код обработки события OnClick
Листинг 13.2.Код обработки события OnClickprocedure TForm1.Button1Click(Sender: TObject);
begin
Form1.Refresh; // Вызываем метод обновления формы end; Запустим приложение на выполнение. Сразу после запуска произойдет событие первоначальной прорисовки формы. В результате появится окно сообщения об обновлении формы (рис 13.2).
Попробуйте изменить размеры формы в сторону увеличения или нажмите на кнопку Button1. В результате вы увидите то же самое информационное окно.
Таким образом, во время перерисовки компонента вы можете выполнить необходимые действия.
Сохранение графики в файл
Листинг 13.20.Сохранение графики в файлvar Form1: TForm1 ;
CurrentFile:String; implementation
{$R *.XFM}
procedure TForm1.Save1Click(Sender: TObject);
begin
if CurrentFile <>
'' then
Image1.Picture.SaveToFile(CurrentFile) { файл уже существует } else SaveAslClick(Sender);
{ иначе нужно ввести имя файла } end;
procedure TForm1.SaveAslClick(Sender: TObject);
begin
if SaveDialog1.Execute then { Получить имя файла } begin
CurrentFile := SaveDialog1.FileName; { сохранить файл с именем,
заданным пользователем }
Save1Click(Sender);
{ вызов метода сохранения файла } end;
end; Назад Вперед
Копирование графики в буфер обмена
Листинг 13.21.Копирование графики в буфер обменаprocedure TForm1.Copy1Click{Sender: TObject);
begin
Clipboard.Assign(Image.Picture) end. Вырезание графики в буфер обмена
Вырезание графики в буфер обмена похоже на копирование. Отличие заключается в том, что после копирования картинка, содержащаяся в источнике, уничтожается.
Для реализации данной операции нужно выполнить два последовательных шага:
1. Скопировать данные в буфер обмена.
2. Уничтожить оригинальные данные.
В листинге 13.22 показано, как можно осуществить операцию вырезания картинки в буфер обмена. Сначала изображение копируется в буфер обмена, затем место, откуда взято изображение, закрашивается белым цветом с помощью установки режима копирования cmWhiteness.
Вырезание графики в буфер обмена
Листинг 13.22. Вырезание графики в буфер обменаprocedure TForm1.Cut1Click(Sender: TObject);
var
ARect: TRect; begin
Copy1Click{Sender);
{ копирование картинки в буфер обмена }
with Image.Canvas do begin
CopyMode := cmWhiteness;{установить режим копирования в белый цвет} ARect := Rect(0, 0, Image.Width, Image.Height);
{получение квадрата копирования}
CopyRect(ARect, Image.Canvas, AReCt);
{ наложение белого прямоугольника } CopyMode := cmSrcCopy; { восстановление нормального режимакопирования } end; end; Вставка графики из буфера обмена
Если в буфере обмена содержится какая-либо графическая информация, вы можете вставить ее в любой графический компонент Kylix, включая канву формы.
Для вставки графики из буфера обмена нужно выполнить следующие шаги:
1. Вызвать метод Provides объекта Clipboard для того, чтобы убедиться, что буфер обмена содержит графическую информацию. Метод Provides представляет собой функцию, которая возвращает булевы значения. Если возвращаемое значение True, то буфер обмена содержит данные именно такого типа, которые указаны в параметре метода Provides.
2. Указать объект, в который будет произведено копирование с помощью метода Assign.
Нижеприведенный код (листинг 13.23) показывает, как можно копировать картинку из буфера обмена в компонент Image с помощью пункта меню Edit/Paste.
Копирование графики
Листинг 13.23.Копирование графики из буфера обмена procedure TForm1.PasteButtonClick(Sender: TObject);var
Bitmap: TBitmap; begin
if Clipboard.Provides(SDelphiBitmap) then { в буфере обмена
изображение? ) begin
Image1.Picture.Bitmap.Assign(Clipboard);
end; end; Изображение, находящееся в буфере обмена, может быть скопировано из любого приложения.
Назад Вперед
Установка позиции пера в координатах указаннных пользователем
Листинг 13.26. Установка позиции пера в координатах, указаннных пользователемprocedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Canvas.MoveTo (X, Y);
{ установка позиции пера } end; Обработка событии OnMouseUp
Событие OnMouseUp происходит всякий раз, когда пользователь отпускает на-жатую кнопку мыши. Комбинация данного события с событием OnMouseDown позволит вам, например, рисовать линии. Когда пользователь нажал кнопку мыши, установить начальную точку линии, а когда отпустил — конечную.
Для обработки события OnMouseUp нужно, как и для обработки OnMouseDown, создать программу-обработчик.
Приведем пример (листинг 13.27), который рисует линию из точки, в которой произошло нажатие кнопки мыши, в точку, в которой пользователь отпустил кнопку мыши (Рисунок 13.8).
Пример рисования линии
Листинг 13.27. Пример рисования линииprocedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Canvas.MoveTo(X, Y) ; { установка позиции пера } end;
procedure TForm1. FormMouseUp (Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Canvas.LineTo(X, Y);
{ рисуем линию из координат PenPos в (X, Y) } end; Пользователь не будет видеть линию, пока не отпустит кнопку мыши.
Пример обработки
Листинг 13.28.Пример обработки события OnMouseMove procedure TForm1.FormMouseMove(Sender: ТОbject;Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
begin
Canvas.LineTo(X, Y);
{ рисует линию в текущую позицию } end;
Листинг игровой программы "Крестикинолики"
Листинг 13.29.Листинг игровой программы "Крестики-нолики"unit Unit1;
interface
uses
SysUtils, Types, Classes, Variants, QGraphics, QControlS, QForms, QDialogs,
QStdCtrls;
type
TForm1 = class (TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
f:boolean; // Флаг, указывающий, что ставится: крестик
// или нолик
implementation {$R *.xfm}
procedure TForm1.Button1Click(Sender; TObject); var
i:integer; begin
// Рисуем прямоугольную область, закрашенную белым цветом Canvas.FillRect(rect(10,10,210,210)); i:=10; //Рисуем горизонтальные линии клеточек сетки 10x10 while i<=210 do begin
Canvas.MoveTo(10, i);
Canvas.LineTo(210,1);
i:=i+20; end; i:=10;
// Рисуем вертикальные линии клеточек сетки 10x10 while i<=210 do begin
Canvas.MoveTo(i,10); Canvas.LineTo(i, 210) ;
i :=i+20; end; end;
procedure TForm1.Button2Click{Sender: TObject); begin
Form1.Close; // Закрытие приложения end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Var
x1,y1:integer; begin
// Проверяем, в какой области формы щелкнул мышкой пользователь // Если в области сетки, то
if (х>10) and (x<210) and (у>10) and (y<210) then begin
// Вычисляем координаты левого верхнего угла клеточки, // внутри которой щелкнул пользователь x1:=trunc((х-10)/20)*20+10; y1:=trunc( (у-10) /20) *20+10; // Проверяем, что ставить: крестик или нолик f:=not(f); if f=true then begin // Если нолик, то
canvas.Pen.Color:=clRed; canvas.Pen.Width:=2; canvas.Ellipse(x1,y1,x1+20,y1+20); end else begin // Иначе - крестик
canvas.Pen.Color:=clBlue; canvas.Pen.Width:=2; canvas.MoveTo(x1,y1); canvas. LineTo (x1+20,y1+20); canvas.MoveTo(x1+20,y1); canvas.LineTo(x1, y1+20) ; end; end;
end; end.
Теперь запустим программу. Нажмите кнопку Начать игру, и программа нарисует белый прямоугольник и сетку 10x10 (Рисунок 13.11).
Загрузка графики из файла
Листинг 13.29.Загрузка графики из файлаprocedure TForm1.Open1Click (Sender: TObject);
var
CurrentFile: String; begin
if CpenDialogl.Execute then
begin
CurrentFile := OpenDialog1.FileName; Image1.Picture.LoadFromFile (CurrentFile);
end; end; Для успешной работы данного примера вам необходимо разместить на форме Form1 компонент OpenDialog1, который вы найдете на вкладке Dialogs палитры компонентов Kylix, а также меню Menu1 с пунктом Open, и записать в обработчике события OnClick для данного пункта меню этот код.
Сохранение графического образа в файл
Для сохранения графического образа в файл вызовите метод SaveToFile. Данный метод требует, чтобы вы передали в качестве параметра имя файла, в который будет произведено сохранение графического образа.
Нижеприведенный пример (листинг 13.20) содержит две процедуры для двух пунктов меню Save и SaveAs. Если вызывается пункт меню Save, то производится проверка, был ли уже создан файл для данного графического образа, если он был создан, то образ сохраняется. Если такой файл не был создан, вызывается метод SaveAs, который открывает окно SaveDialog1 и запрашивает имя файла для данного графического образа, после чего управление передается методу Save.
Таким образом, для успешной работы данного примера вам необходимо расположить на форме Form1 меню с двумя пунктами Save и SaveAs и компонент SaveDialog с вкладки Dialogs палитры компонентов Kylix. Кроме того, разместите на форме компонент Image1 для хранения графического образа, после чего запишите в обработчик событий нажатия пунктов меню код, приведенный в листинге 13.20.
Установка значения цвета пера
Листинг 13.3. Установка значения цвета пераprocedure TForm1.Button1Click(Sender: TObject);
begin
Canvas.Pen.Color := PenColor.ForegroundColor; end;
Ширина пера
Ширина пера определяет толщину линий, которыми будут начерчены геометрические фигуры.
Примечание
Если вы создаете кросс-платформенное приложение, которое может функционировать как под Linux, так и под Windows 9x, и ширина пера более одного пиксела, то имейте в виду, что Windows будет всегда рисовать сплошные линии, независимо от значения свойства Style пера.
Для смены ширины пера достаточно присвоить необходимое числовое значение свойству Width пера (листинг 13.4).
Установка ширины пера
Листинг 13.4.Установка ширины пераprocedure TForm1.Button1Click(Sender: TObject);
begin
Canvas.Pen.Width := 5; end;
Стиль пера
Свойство Style позволяет вам устанавливать различные стили начертания линий. Это могут быть сплошные линии, пунктирные, точечные и др.
В листинге 13.5 стиль пера меняет последовательно все возможные значения.
Смена стилей пера
Листинг 13.5. Смена стилей пераprocedure TForm1.Button1Click(Sender: TObject);
begin
with Canvas.Pen do begin Style = psSolid
Style = psDash Style = psDot Style = psDashDot Style = psDashDotDot Style = psClear; end; end; Режим пера
Свойство пера Mode позволяет вам устанавливать различные режимы комбинирования цвета пера с цветом, расположенным на канве. Например, режим постоянного цвета пера, режим инверсии цвета пера или фона канвы пр.
Установка и определение позиции пера
Текущая позиция рисования, с которой начинается рисование линий, называется позицией пера. Как вы уже знаете, объект канвы хранит текущую позицию пера в свойстве PenPos. Позиция пера нужна только для рисования линий. Для рисования геометрических фигур и вывода текста на канву вы указываете необходимые координаты при вызове соответствующих методов. Для установки нужной позиции пера вызывайте метод MoveTo:
Image1.Canvas.MoveTo(0, 0);
Данный код установит перо в левый верхний угол канвы.
Примечание
Черчение линий с помощью метода LineTo также устанавливает текущую позицию, пера, равную конечной точке линии.
Назад Вперед
Установка цвета кисти
Листинг 13.6.Установка цвета кистиprocedure TForm1.Button1Click(Sender: TOtrject);
begin
Canvas.Brush.Color := clBlue; end; Стиль кисти
Стиль кисти определяет, каким образом будет заполняться область на канве или геометрическая фигура. Это позволяет программисту комбинировать цвет кисти с уже имеющимися цветами канвы.
Для смены стиля кисти достаточно напрямую установить свойство Style в одно из следующих значений:
bsSolid, bsClear, bsHonzontal, bsVertical, bsFDiagonal, bsBDiagonal, bsCross, bsDiagCross, bsDense1, bsDense2, bsDense3, bsDense4, bsDense5, bsDense6 или bsDense7.
Пример, приведенный в листинге 13.7, показывает, как можно установить стиль кисти. Здесь происходит последовательная установка нескольких значений стиля кисти.
Установка стииля кисти
Листинг 13.7. Установка стииля кистиprocedure TForm1.Button1Click(Sender: TObject);
begin
with Canvas.Brush do begin
Style = bsSolid Style = bsClear Style = bsHorizontal Style = bsVertical Style = bsFDiagonal Style = bsBDiagonal Style = bsCross Style = bsDiagCross; end; end; Установка значения свойства Bitmap
Свойство Bitmap кисти позволяет указать графический образ, который будет использоваться для заполнения областей и геометрических фигур, расположенных на канве.
Нижеприведенный пример (листинг 13.8) показывает, как можно загрузить графический образ из файла и присвоить его свойству Bitmap кисти канвы формы Form1.
Загрузка графического образа из файла
Листинг 13.8.Загрузка графического образа из файлаvar
Bitmap: TBitmap; begin
Bitmap := TBitmap.Create; try
Bitmap.LoadFromFile('MyBitmap.bmp');
Form1.Canvas.Brush.Bitmap := Bitmap; Form1.Canvas.FillRect(Rect(0,0,100,100));
finally
Form1.Canvas.Brush.Bitmap := nil;
Bitmap.Free; end; end;
Примечание
Кисть не является владельцем графического образа, который присвоен свойству Bitmap кисти. Вы должны самостоятельно уничтожать объект графического образа после использования.
Назад Вперед
Пример рисования прямых линий procedure TForm1 FormPaint(Sender TObject);
begin
Листинг 13.9. Пример рисования прямых линий
procedure TForm1.FormPaint(Sender: TObject);begin
with Canvas do begin
MoveTo(0, 0);
LineTo(ClientWidth, ClientHeight);
MoveTo(0, ClientHeight);
LineTo(ClientWidth, 0), end; end; Результат выполнения примера изображен на Рисунок 13.3.
Объект TThred
Листинг 14.1. Объект TThredTThread = class private
FHandle: THandle; FThreadID: THandle;
FTerminated: Boolean; FSuspended: Boolean; FFreeOnTerminate: Boolean; FFinished: Boolean; FReturnValue: Integer;
FOnTerminate: TNotifyEvent;
FMethod: TThreadMethod;
FSynchronizeException: TObject; procedure CallOnTerminate; function GetPriority: TThreadPriority; procedure SetPriority (Value: TThreadPriority);
procedure SetSuspended (Value: Boolean);
protected procedure DoTerminate; virtual;
procedure Execute; virtual; abstract;
procedure Synchronize(Method: TThreadMethod);
property ReturnValue: Integer read FReturnValue write FReturnValue; property Terminated: Boolean read FTerminated; public
constructor Greate(GreateSuspended: Boolean);
destructor Destroy; override; procedure Resume; procedure Suspend; procedure Terminate;
function WaitFor: LongWord;
property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
property Handle: THandle read FHandle;
property Priority: TThreadPriority read GetPriority write SetPriority;
property Suspended: Boolean read FSuspended write SetSuspended; property ThreadID: THandle read FThreadID;
property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate; end; Из вышеприведенного листинга можно определить, что объект TThread является прямым потомком объекта TObject, следовательно, он не является визуальным компонентом. Его метод Execute — абстрактный. Поэтому сам объект TThread тоже является абстрактным, и вы не сможете создать экземпляр этого класса. Таким образом, вам придется создавать классы — потомки данного класса для работы с потоками.
Для создания потомка класса TThread выберите в главном меню Kylix команду File/New, затем в появившемся окне (Рисунок 14.1) выберите пиктограмму Thread Object.
Заготовка для ноиого объукта потока
Листинг 14.2. Заготовка для ноиого объукта потокаunit Unit1; interface
uses Classes;
type
TMyThread = class(TThread) private
{ Private declarations }
protected
procedure Execute; override;
end;
implementation
{ Важно: Методы и свойства объектов CLX могут быть использованы только
с помощью вызова метода синхронизации, например
Synchronize(UpdateCaption);
и UpdateCaption должно выглядеть следующем образом:
procedure TMyThzead.UpdateCaption;
begin
Form1.Caption := 'Обновлено внутри потока'; end; }
{ TMyThread }
procedure TMyThread.Execute; begin
{ Разместите код потока здесь } end;
end. В автоматически сгенерированном файле, модуля вы можете:
Проверка прекращения работы потока
Листинг 14.3.Проверка прекращения работы потокаprocedure TMyThread.Execute; begin
while not Terminated do
{выполнять какие-либо задачи}; end;
Пример создания многопоточного приложения в Kylix
Теперь настало время создания простого многопоточного приложения.
Мы создадим приложение, которое состоит из трех потоков (главного CLX-потока и двух потоков — потомков класса TThread). Для начала запустим Kylix и выберем в его главном меню пункт File/New Application, после чего разместим на главной форме приложения Form1 поле для редактирования Edit1, индикатор хода выполнения работы ProgressBar1 и системный таймер Timer1. В результате должна получиться форма, похожая на представленную на Рисунок 14.2.
Теперь добавим новый объект потока через пункт главного меню Kylix File/New/Thread Object. Введем имя для нового потомка класса TThread, например TMyThread1. Kylix автоматически добавит модуль Unit2 в наше приложение. В описание объекта TMyThread1 добавим раздел public, в котором опишем глобальную переменную count.
Модуль первого потока
Листинг 14.4.Модуль первого потокаunit Unit2; interface
uses Classes;
type TMyThread1 = class(TThread)
private
{ Private declarations } protected procedure Execute; override;
public
count : integer; // Добавили переменную Count end;
implementation { TMyThread1 }
procedure TMyThread1.Execute; begin
while true do
begin
count:=random (maxint);
end; end;
end. Теперь создадим второй объект потока, который должен заполнять индикатор хода работы ProgressBar1.
По аналогии с первым объектом потока при помощи главного меню Kylix создадим объект потока с именем TMyThread2. Во вновь добавленный модуль Unit3 включим глобальную переменную prcount, после чего в процедуре Execute объекта TMyThread2 запишем код, представленный в листинге 14.5, также зациклив его.
Модуль второго потока
Листинг 14.5.Модуль второго потокаunit Unit3;
interface
uses Classes;
type
TMyThread2 = class(TThread) private
{ Private declarations }
protected
procedure Execute; override;
public
prcotmt:integer; // Добавили переменную prcount end;
implementation { TMyThread2 }
procedure TMyThread2.Execute; begin
while true do begin
prcount;=prcount+1; if prcount>
100 then prcount:=0; end; end;
end.
Теперь сохраним наш проект и модули под теми именами, которые нам предложит Kylix (Project1, Unit1, Unit2, Unit3).
Добавим в модуле Unit1 в описание класса формы в разделе private объекты потоков Thread1 — потомок класса TMyThread1 и Thread2 — потомок класса TMyThread2.
Далее дважды щелкнем на любом свободном пространстве формы Form1. При этом откроется "заготовка" для метода создания формы FormCreate. В обработчике FormCreate напишем код, представленный в листинге 14.6.
Здесь мы создаем объект потока с использованием конструктора Сreate и устанавливаем приоритеты потоков (tpLowest и tpNormal).
Запишем в блоке uses модуля Unit1 используемые модули Unit2 и Unit3.
Нам осталось отразить результаты вычислений, производимых потоками на форме. Для этого создадим обработчик события OnTimer, дважды щелкнув на объекте Timer1. Запишем в обработчик события OnTimer код, представленный в листинге 14.6.
Главный модуль многопоточного приложения
Листинг 14.6. Главный модуль многопоточного приложенияunit Unit1; interface
uses
SysUtils, Types, Classes, Variants, QGraphics, QControls, QForms, QDialogs, QTypes, QExtCtrls,
QComCtrls, QStdCtrls, unit2, unit3;
type
TForm1 = class (TForm)
Edit1: TEdit;
ProgressBar1: TProgressBar;
Timer1: TTimer;
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
thread1:tmythread1;
thread2:tmythread2;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation {$R *.xfm}
procedure TForm1.FormCreate(Sender: TObjеct);
begin thread1:=tmythread1.create(false);
thread2:=tmythread2.create(false);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
edit1.Text:=inttostr(thread1.count);
progressbar1.Position:=thread2.prcount; end;
end.
Наше первое приложение, которое использует потоки, готово. Теперь, если мы запустим приложение с помощью главного меню Kylix: Run/Run, то сможем увидеть, как два созданных нами потока успешно работают (Рисунок 14.3).
Использование синхронизации
Листинг 14.7. Использование синхронизацииprocedure TMyThread.PushTheButton; begin
Button1.Click; end;
procedure TMyThread.Execute; begin
. . . Synchronize(PushTheButton);
. . . end; Метод синхронизации защитит ваше приложение от ситуации "гонки".
Ситуация "гонки" возникает, когда два потока или более пытаются получить доступ к общему ресурсу и изменить его состояние.
Примечание
Метод синхронизации не может использоваться в консольных приложениях Для защиты одновременного доступа к CLX-объектам в консольных приложениях вы должны использовать другие методы, такие как критические секции
В некоторых случаях вы можете обходиться без метода синхронизации, например, если:
Примечание
Когда вы используете компоненты доступа к данным, вы должны применять синхронизацию в том случае, если устанавливаете связь между компонентами доступа к данным (например, свойство DataSet в объекте DataSource). Но вы можете не прибегать к синхронизации при обращении к данным таблицы базы данных
Объявление локальных переменных в потоке класса TThread
Листинг 14.8.Объявление локальных переменных в потоке класса TThreadtype
TMyThread1 = class(TThread)
private
i, j,k,l: integer; // локальные переменные потока типа integer a,b,c: char; // локальные переменные потока типа char
. . . end; Эффективность объявления локальных переменных в потомке класса TThread очевидна, т. к. доступ к любому полю объекта осуществляется очень быстро (примерно в 10—11 раз быстрее, чем при использовании описания threadvar).
Третий способ хранения локальных переменных (с помощью threadvar) служит для создания в потоках локальных копий глобальных переменных.
Глобальные переменные могут использоваться всеми потоками приложения, при этом может возникнуть ситуация, когда при изменении глобальной переменной одним потоком происходит изменение этой же глобальной переменной другим потоком. В результате значение, установленное первым потоком, бесследно исчезает, приводя к нежелательным последствиям (в данном примере произойдет обработка ошибочного значения глобальной переменной первым потоком). Для исключения такой ситуации Kylix предлагает средство хранения локальных данных потоков (thread-local storage). С помощью данного средства можно создавать локальные копии глобальных переменных для любого потока. При этом требуется всего лишь заменить одно слово var при объявлении глобальных переменных на слово threadvar:
threadvar
х : integer;
Итак, прочитав эту главу, вы узнали некоторые приемы работы с потоками и научились создавать многопоточные приложения. Это вам особенно пригодится при переносе приложений из среды Windows в Linux.
Назад
Модуль Ffactlin
Листинг 15.1.Модуль Ffactlinunit Ffactlin;
interface
uses
SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs,QExtCtrls, QDBCtrls, QStdCtrls, DB, DBClient, QGrids, QDBGrids, QButtons;
type
TForm1 = class (TForm)
Panel1: TPanel;
DBImage1: TDBImage;
DBText1: TDBText;
ClientDataSet1: TClientDataSet;
DataSource1: TDataSource;
Panel2: TPanel;
Label1: TLabel;
DBText2: TDBText;
Panel3: TPanel;
Panel4: TPanel;
DBGrid1: TDBGrid;
BitBtn1: TBitBtn;
DBMemo1: TDBMemo;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.xfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
// Указываем файл таблицы базы данных ClientDataSet1.LoadFromFile('biolife.cds');
end;
end.
Внешний вид формы представлен на Рисунок 15.4.
Содержание типичного файла базы данных
Листинг 18.1. Содержание типичного файла базы данныхMETADATA>
В первой строке содержится заголовок:
Вторая строка содержит корневой тэг документа:
Всю остальную часть файла можно разделить на две части:
Внутри тэга METADATA расположены описания полей таблицы (тэг FIELDS и вложенные в него тэги) и другая служебная информация (порядок сортировки по умолчанию, начальное значение автоматически увеличивающегося счетчика).
Теперь давайте запустим наше приложение, вставим в таблицу новую запись, закроем приложение и посмотрим, как изменился xml-файл.
Мы видим, что изменился тэг PARAMS:
Кроме того, тэг ROWDATA тоже изменился:
Если вы внимательно посмотрите на изменения, то увидите, что внутри таблицы ведется журнал операций. Это дает возможность сделать отмену произведенных действий.
Если вам не нужно, чтобы этот журнал велся, в режиме выполнения программы установите свойство LogChanges в false.
Рассмотрим установку отношений таблиц "главный-подчиненный" (master-detail).
Новым способом организации отношения master-detail в Kylix стало использование вложенных наборов данных. Предположим, что нам нужно получить информацию о покупках, сделанных клиентом.
Сначала очистим набор данных Сlients. Для этого щелкнем правой кнопкой мыши на компоненте Сlients и в выпадающем меню выберем пункт очистки данных Clear Data.
Введем дополнительное описание полей Оrders типа ftDataSet. Данный тип поля предназначен для хранения внутри себя наборов данных. Список полей вложенного набора данных устанавливается в свойстве ChildDefs. Определим в ChildDefs следующие поля (табл. 18.2).
Содержимое файла базы данных
Листинг 18.2. Содержимое файла базы данных-
-
-
-
-
Нетрудно убедиться в том, что поле Оrders содержит в себе описание подчиненной таблицы. При этом в сетке данных DBGrid1, расположенной на главной форме, появился новый столбец Оrders. При запуске приложения и попытке редактирования этого поля автоматически открывается форма для редактирования вложенного набора данных.
Другим способом организации взаимодействия с вложенным набором данных является размещение в модуле данных дополнительного клиентского набора данных ClientDataSet. Поместим в модуль данных еще один компонент типа TClientDataSet, установив его имя orders. Свойству DataSetField компонента Orders из раскрывающегося списка присвоим значение ClientsOrders. Теперь, пользуясь компонентом Оrders, можно просматривать и редактировать вложенный набор данных.
Достоинства вышеописанного метода в том, что вся база будет храниться в одном xml-файле, недостаток — в том, что нельзя разорвать связь главный-подчиненный и, как следствие, одновременно посмотреть все записи о заказах вне зависимости от выбранного клиента.
Модуль заготовки нового класса
Листинг 19.1.Модуль заготовки нового классаunit QMyButton; interface
uses
SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs, QStdCtrls;
type
TMyButton = class(TButton) private
{ Private declarations } protected
{ Protected declarations } public
{ Public declarations } published
{ Published declarations } end; procedure Register;
implementation
procedure Register; begin
RegisterComponents('Samples', [TMyButton]);
end;
end.
Итак, заготовка для нового компонента готова. Она не содержит никаких новых свойств, методов и событий для нового компонента. Нужно отметить, что данный компонент уже имеет все свойства, события и методы, которые определены для класса TButton.
Рассмотрим теперь основные типы методов компонента.
Все методы могут быть одного из нескольких типов: статические (static), виртуальные (virtual), динамические (dynamic) или методы-сообщения (message). По умолчанию методу присваивается статический тип.
Назад Вперед
показывает как создать
Листинг 19.10 показывает, как создать новый редактор свойств THintProperty. В качестве класса-предка для данного редактора свойств выберем редактор TStringproperty.Создание нового редактора свойств
Листинг 19.10.Создание нового редактора свойствTHintProperty = class(TStringProperty) public
function GetAttributes: TPropertyAttributes; override;
function GetValue : String; override;
procedure Edit; override; end;
function THintProperty.GetAttributes: TPropertyAttributes; begin
Result := inherited GetAttributes + [paDialog, paReadOnly]; end;
function THintProperty.GetValue : string;
var i : Byte;
begin
result:=inherited GetValue;
for i:=l to Byte(result[0]) do
if result[i]<#32 then result[ i ]:='>
'; end;
procedure THintProperty.Edit ; var
HintEditDlg : TStrEditDlg; s : string; begin
HintEditDlg:=TStrEditDlg.Create(Application);
with HintEditDlg do try
Memo.MaxLength := 254; s:=GetStrValue+#0; Memo.Lines.SetText(@s[1]);
UpdateStatus(nil);
ActiveControl := Memo; If ShowModal = mrOk then begin s: =StrPas (Memo. Lines. GetText) ; if s[0]>
#2 then Dec(Byte(s[0]),2);
SetStrValue(s);
end; finally Free; end; end;Рассмотрим методы нового класса:
).
Для регистрации нового редактора нужно в интерфейсной части модуля поместить Объявление Процедуры Register. После чего В части Implementation модуля написать саму процедуру регистрации (листинг 19.11).
Процедура регистрации нового редактора свойствprocedure Register; begin
Листинг 19.11. Процедура регистрации нового редактора свойствprocedure Register; beginRegisterPropertyEditor (TypeInfо(String), TControl, 'Hint',
THintProperty);
end;
Данная процедура позволяет привязать один и тот же редактор к свойствам, в зависимости от их названия или типа. Это определяется параметрами, которые передаются процедуре RegisterPropertyEditor. Первый параметр определяет тип свойства (в нашем примере это String). Второй параметр определяет класс компонента. Третий параметр позволяет указать имя свойства, четвертый — имя редактора свойства.
Для того чтобы установить новый редактор свойств в Kylix, необходимо выполнить следующие шаги:
1. Выбрать пункт меню Component/Install Components.
2. Нажать кнопку Add.
3. Указать имя подключаемого модуля.
После того как произойдет компиляция библиотеки, можно создать новую форму и разместить на ней какой-либо компонент, после чего установите у этого компонента свойство ShowHint в true и нажмите кнопку <...>
в свойстве Hint. Вы увидите на экране новый многострочный редактор для свойства Hint.
Команды Default и NoDefault
Итак, мы уже умеем создавать свойства произвольного типа для собственного компонента. Осталось заметить, что многим свойствам можно присвоить конкретное значение, которое будет установлено по умолчанию. Для этого достаточно присвоить это значение полю компонента, например:
FMyProperty := 10;
В результате этого при каждом добавлении компонента на форму двойство MyProperty будет принимать значение 10.
Команды Default и NoDefault применяются для ускорения процесса загрузки формы при работе приложения. Например,
property MyCount: Integer read FMyCount write FmyCount Default 0;
Данный код не присваивает значение 0 свойству MyCount. При выполнении вышеприведенного кода команда default 0 означает следующее: если при сохранении формы, содержащей компонент, значение свойства MyCount не — будет равно нулю, то новое значение сохранится в файле формы, иначе значение данного свойства не будет сохранено.
Примечание
Рекомендуется использовать команду Default во всех случаях, когда это возможно, если вы хотите создать быстро работающее приложение.
Команда NoDefault предназначена для нейтрализации команды Default. Команда применяется для отмены команды Default компонентов-предков. Пример использования команды NoDefault:
TSecondComponent = class (TMyButton)
published
property MyCount NoDefault 0;
Метод диспетчеризации события TControl = class (TComponent) private
Листинг 19.12. Метод диспетчеризации события TControl = class (TComponent) privateFOnClick: TNotifyEvent; protected
procedure Click; dynamic;
property OnClick: TNotifyEvent read FOnClick write FOnClick; end;
implementation
procedure TControl.Click; begin
if Assigned (FOnClick) then FOnClick (Self);
end; Обратите внимание: свойство OnClick имеет тип TNotifyEvent, который представляет собой процедуру с одним параметром Sender типа TObject:
TNotifyEvent = procedure (Sender: TObject) of object;
Иначе говоря, когда происходит вызов метода Click, осуществляется проверка, ссылается ли FOnClick на какой-либо метод, и если ссылается, то происходит вызов этого метода.
Суть разобранного выше события в том, чтобы иметь представление, что создание событий подразумевает написание кода, определяющего само событие, а также свойства и метода диспетчеризации. Обработчик события пишется пользователем.
При возникновении какого-либо события операционная система передает приложению не только информацию о наступлении данного события, но и некоторую дополнительную информацию. В нашем примере при обработке события нажатия левой кнопки мыши в приложение поступает информация о координатах внутри клиентской части компонента, в которых произошло нажатие левой кнопки мыши. Например, код, приведенный в листинге 19.13, выводит при наступлении события нажатия левой кнопки мыши на форме координаты указателя мыши.
Пример обработки события нажатия кнопки мыши
Листинг 19.13.Пример обработки события нажатия кнопки мышиprocedure TForm1. FormMouseDown (Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Canvas.TextOut(X, Y, '('+IntToStr(X) +', '+IntToStr(Y) + ')');
end; Данный код мы вписали в обработчик события OnMouseDown формы Form1. Если теперь запустить программу на исполнение и пощелкать мышкой в разных частях формы, в тех местах формы, где происходит щелчок мыши, будут выведены координаты этих точек.
Пример создания нового события unit halfmin; interface
Листинг 19.14.Пример создания нового события unit halfmin; interfaceuses
SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs;
type
TTimeEvent - procedure (Sender: TObject; TheTime: TDateTime) of object;
THalfMinute = class (TComponent)
private
FTimer: TTimer;
FOnHalfMinute: TTimeEvent;
FOldSecond, FSecond: Word; procedure FTimerTimer (Sender: TObject);
protected
procedure DoHalfMinute (TheTime: TDateTime);
dynamic; public
constructor Create (AOwner: TComponent);
override;
destructor Destroy; override; published
property OnHalfMinute: TTimeEvent read FOnHalfMinute write FOnHalf- Minute;
end;
implementation constructor THalfMinute.Create (AOwner: TComponent);
begin inherited Create (AOwner);
if not (csDesigning in ComponentState) then begin FTimer:=TTimer.Create(self);
FTimer.Enabled:= True; FTimer..Interval:= 500; FTimer.OnTimer:=FTimerTimer; end; end;
destructor THalfMinute.Destroy; begin
FTimer.Free;
inherited Destroy; end;
procedure THalfMinute.FTimerTimer (Sender: TObject);
var
DT: TDateTime; Temp: Word; begin
DT:=Now;
FOldSecond:=FSecond;
DecodeTime (DT,Temp,Temp,FSecond,Temp);
if FSecond <>
TOldSecond then
if ((FSecond=30) or (FSecond=0)) then
DoHalfMinute (DT);
end;
procedure THalfMinute.DoHalfMinute(TheTime: TDateTime);
begin
if Assigned (FOnHalfMinute) then FOnHalfMinute (Self, TheTime);
end;
end. Для проверки работоспособности вышеприведенного кода вы можете добавить еще одну процедуру для регистрации нового компонента с именем ThalfMinute, предварительно расположив в interface часть программы строку:
procedure Register;
Ниже представлен код для регистрации компонента:
procedure Register; begin
RegisterComponents('Samples', [THalfMinute]}; end;
Для просмотра работоспособности нового компонента, после его регистрации создадим новую форму и разместим на ней новый компонент. Добавим на форму компонент Tedit, а затем — обработчик события OnHalfMinute для формы (листинг 19.15).
Обработчик нового события procedure TForm1 HalfMinutelHalfMinute(Sender TObject;
Листинг 19.15.Обработчик нового события procedure TForm1.HalfMinutelHalfMinute(Sender: TObject;TheTime: TDateTime);
begin
Edit1.Text:=('Время '+TimeToStr(TheTime));
Edit1.Refresh; end;
В результате работы данной программы в компоненте Edit1 каждые 30 секунд будет выводиться текущее время.
Назад Вперед
Пример создания свойств нового компонента
Листинг 19.2. Пример создания свойств нового компонентаMyButton = class(TButton) private
{ Private declarations }
FMyCount: Integer;
FStirngOfText: String; protected
{ Protected declarations } public
{ Public declarations } published
{ Published declarations }
property MyCount: Integer read FMyCouht write FMyCount;
property StringOfText: String read FStringOfText write FStringOfText; end;
В этом листинге мы задаем два новых поля для компонента TMyButton и определяем два новых свойства компонента, одно типа Integer, другое — String. Для простоты значения данных свойств считываются и записываются в одноименные поля. Задание этих свойств будет гарантировать доступ к ним в окне инспектора объектов (благодаря описанию свойств в разделе published) и не потребует написания дополнительных методов для доступа к свойствам.
Примечание
По взаимной договоренности принято названия полей начинать с буквы f (field — "поле"), а названия компонентов и любых объектов — с буквы t (type — "тип").
Создание перечисляемых свойств компонента
К свойствам перечисляемого типа относятся такие свойства компонента, которые при их редактировании в окне инспектора объектов вызывают раскрывающийся список, содержащий возможные значения данного свойства.К числу таких свойств относятся Align, BorderStyle, Color и др. Для того чтобы самостоятельно добавить в новый компонент перечисляемое свойство, необходимо сначала определить новый перечисляемый тип, например:
TMyEnumType = (eFirst, eSecond, eThird);
После этого нужно определить поле компонента, которое будет хранить значение данного перечисляемого типа, затем определить свойство. Пример добавления перечисляемого типа в новый компонент TMyButton приведен в листинге 19.3.
Создание свойств перечиляемого типа
Листинг 19.3.Создание свойств перечиляемого типаunit QMyButton; interface
uses
SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs, QStdCtrls;
type
TMyEnumType = (eFirst, eSecond, eThird);
type
TMyButton = class(TButton) private
{ Private declarations }
FMyEnum: TMyEnumType; protected
{ Protected declarations } public
{ Public declarations } published
{ Published declarations }
property MyEnumProp: TMyEnumType read FMyEnum write FMyEnum; end;
procedure Register; implementation
procedure Register; begin
RegisterComponents{'Samples', [TMyButton]);
end;
end.
Таким образом, в окне инспектора объектов при изменении свойства MyEnumProp будет выдан раскрывающийся список, содержащий три пункта:
eFirst, eSecond и eThird (рис 19.3).
Создание свойствамножества unit QMyButton;
Листинг 19.4. Создание свойства-множества unit QMyButton;interface
uses
SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs, QStdCtrls;
type
TMyEnumType = (eFirst, eSecond, eThird);
TMySetTypeFirst = {poFirst, poSecond, poThird);
TMySetType = set of TMySetTypeFirst;
type
TMyButton = class(TButton) private
{ Private declarations }
FMyEnum: TMyEnumType;
FMyOptions: TMySetType; protected
{ Protected declarations } public
{ Public declarations } published
{ Published declarations }
property MyEnumProp: TMyEnumType read ЕМуЕnum write FMyEnum;
property MyOptions: TMySetType read FMyOptions write FMyOptions; end;
procedure Register; implementation
procedure Register; begin
RegisterComponents('Samples', [TMyButton]);
end;
end.
Для удобства мы не стали исключать определение перечисляемого свойства в компоненте TMyButton.
В результате в окне инспектора объектов свойство-множество будет отображаться как показано на Рисунок 19 4
Создание потомка TPersistenttype
Листинг 19.5. Создание потомка TPersistenttypeTMyObject = class (TPersistent) private
{ Private declarations }
FProperty1:Real;
FProperty2:Char; protected
{ Protected declarations } public
{ Public declarations }
procedure Assign (Source: TPersistent);
published
{ Published declarations }
property Property1: Real read FProperty1 write FProperty1;
property Property2: Char read FProperty2 write FProperty2; end;В качестве предка нового класса может выступать не только класс TPersistent, но и любой его потомок. В вышеприведенном листинге мы создаем новый класс TMyObject, в котором присутствуют два простых свойства — Property1 и Property2. Кроме того, в новый объект включена процедура Assign. Данная процедура необходима для обеспечения правильного доступа к свойству нашего будущего компонента TMyButton. Ниже приведен листинг 19.6, в котором мы добавляем в компонент TMyButton новое свойство-объект.
Добавление свойстваобъекта в компонент TMyButtontype
Листинг 19.6. Добавление свойства-объекта в компонент TMyButtontypeTMyButton = class(TButton) private
{ Private declarations }
FMyObject:TMyObject;
procedure SetMyObject (Value: TMyObject);
protected
{ Protected declarations } public
{ Public declarations }
constructor Create (AOwner: TComponent);
override;
destructor Destroy; override; published
{ Published declarations }
property MyObject: TMyObject read FMyObject write SetMyObject; end;Как вы можете видеть, мы добавляем в код нового компонента конструктор и деструктор объекта.
Теперь осталось дописать конструктор и деструктор для компонента TMyButton, в которых необходимо, соответственно, создать и уничтожить, кроме компонента TmyButton, объект TMyObject. Также нужно написать код метода SetMyObject, который будет помещать новое значение в свойства объекта TMyObject. Ну и, конечно, написать код метода Assign для объекта TMyObject. Полная версия кода представлена в листинге 19.7. Здесь, помимо ранее описанного, приводится код ко всем этим методам.
Полный листинг для нового компонента
Листинг 19.7. Полный листинг для нового компонентаunit QMyButton;
interface
uses
SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs, QStdCtrls;
type
TMyObject = class (TPersistent) private
{ Private declarations }
FProperty1:Real;
FProperty2:Char; protected
{ Protected declarations }
public
{ Public declarations }
procedure Assign (Source: TPersistent);
published
{ Published declarations }
property Property1: Real read FProperty1 writhe FProperty1;
property Property2: Char read FProperty2 write FProperty2; end;
type
TMyButton = class(TButton) private
{ Private declarations }
FMyObject:TMyObject;
procedure SetMyObject (Value: TMyObject);
protected
{ Protected declarations } public
{ Public declarations }
constructor Create (AOwner: TComponent);
override; destructor Destroy; override; published
{ Published declarations }
property MyObject: TMyObject read FMyObject write SetMyObject; end; procedure Register;
implementation
procedure Register; begin
RegisterComponents('Samples', [TMyButton]);
end;
procedure TMyButton.SetMyObject(Value: TMyObject);
begin
if Assigned(Value) then FMyObject.Assign(Value);
end;
constructor TMyButton.Create(AOwner: TComponent);
begin
inherited Create (AOwner);
FMyObject:=TMyObject.Create; end;
destructor TMyButton.Destroy; begin
FMyObject.Free;
inherited Destroy; end;
procedure TMyObject.Assign(Source: TPersistent);
begin if Source is TMyObject then begin
FProperty1:=TMyObject(Source).Property1; FProperty2: = TMyObject (Source) .Property2; inherited Assign (Source);
end; end;
end.
Пример компонента TWeek
Листинг 19.8.Пример компонента TWeekunit Week; interface
uses
SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs;
type
TWeek = class(TComponent) private { Private declarations }
function GetMonthName (const AIndex: Integer): String;
function GetMonthNurnber (const AMonthName: String) : Integer; protected
{ Protected declarations } public
{ Public declarations }
property MonthName[const AIndex: Integer]: String read GetMonthName; default;
property MonthNumber[const AMonthName: String]: Integer read GetMonthNumber; published
{ Published declarations } end; procedure Register;
implementation
const
MonthNames: array[l..12] of String[8],*('Январь','Февраль','Март', 'Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь', 'Декабрь');
function TWeek.GetMonthName(const AIndex: Integer): String; begin
if (AIndex<=0) or (AIndex>
12) then raise Exception.Create('Номер месяца должен быть числом от 1 до 12')
else Result;=MonthNames [Alndex3]; end;
function TWeek.GetMonthNumber(const AMonthName: String): Integer; var
i:integer; begin
Result:=0;
for i:=l to 12 do begin
if Uppercase(AMonthName)=UpperCase(MonthNames[ i ] ) then Result:=i;
end; end;
procedure Register;
begin RegisterComponents('Samples', [ TWeek ] );
end;
end.
Рассмотрим вышеприведенный код более подробно. Как вы можете видеть, свойства типа массив объявляются вместе с индексами. Для свойства MonthName мы определили индекс AIndex, а для свойства MonthNumber — индекс AMonthName. Для доступа к свойствам такого типа необходимо использовать методы. Внутренние поля здесь не используются. Если свойство типа массив многомерно, то свойство-массив объявляется сразу с несколькими индексами. При вызове методов доступа к ним нужно передавать параметры в том же порядке, в каком вы их указали в свойстве.
Функция GetMonthName возвращает строку, содержащую имя месяца, соответствующего целому числу от 1 до 12, переданному в качестве параметра данной функции. В случае передачи функции числа, не принадлежащего данному диапазону, будет сгенерировано исключение командой raise (об исключениях читайте главу 9 книги).
Наконец, функция GetMonthNumber возвращает число от 1 до 12, которое соответствует названию месяца, переданного в качестве параметра в данную функцию. В случае если ни один месяц не соответствует названию, определенному массивом MonthNames, результатом выполнения данной функции будет ноль.
Таким образом, если поместить на форму экземпляр компонента TWeek с именем Week1, при выполнении строки
ShowMessage (Weekl.MonthName[5]);
будет выдано окно с сообщением Май (Рисунок 19.6).
Определение базового
Листинг 19.9. Определение базового класса TPropertyEditorTPropertyEditor = class(TBasePropertyEditor, IProperty) privateFDesigner: IDesigner;
FPropList: PInstPropList;
FPropCount: Integer;
function GetPnvateDirectory: string; protected
procedure SetPropEntry(Index: Integer; AInstance: TPersistent;
APropInfo: PPropInfo);
override; protected function GetFloatValue: Extended;
function GetFloatValueAt (Index: Integer): Extended;
function GetInt64Value: Int64;
function GetInt64ValueAt(Index: Integer): Int64;
function GetMethodValue: TMethod;
function GetMethodValueAt(Index: Integer): TMethod; function GetOrdValue: Longint;
function GetOrdValueAt(Index: Integer): Longint;
function GetStrValue: string;
function GetStrValueAt(Index: Integer): string;
function GetVarValue: Variant;
function GetVarValueAt(Index: Integer): Variant;
function GetIntfValue: IInterface;
function GetIntfValueAt(Index: Integer): IInterface;
procedure Modified;
procedure SetFloatValue(Value: Extended);
procedure SetMethodValue(const Value: TMethod);
procedure SetInt64Value(Value: Int64);
procedure SetOrdValue(Value: Longint);
procedure SetStrValue(const Value: string);
procedure SetVarValue(const Value: Variant);
procedure SetIntfValue(const Value: IInterface);
protected { IProperty } function GetEditValue(out Value: string): Boolean;
function GetComponentValue: TComponent; virtual;
function HasInstance(Instance: TPersistent): Boolean; public
constructor Create(const ADesigner: IDesigner; APropCount: Integer)
override; destructor Destroy; override;
procedure Activate; virtual;
function AllEqual: Boolean; virtual; function AutoFill: Boolean; virtual;
procedure Edit; virtual;
function GetAttributes: TPrppertyAttributes; virtual;
function GetComponent (Index: Integer) : TPersistent;
function GetEditLimit: Integer; virtual; function GetName: string; virtual;
procedure GetProperties(Proc: TGetPropProc);
virtual;
function GetPropInfo: PPropInfo; virtual;
function GetPropType: PTypeInfo;
function GetValue: string; virtual;
function GetVisualValue: string;
procedure GetValues(Proc: TGetStrProc);
virtual;
procedure Initialize; override;
procedure Revert;
procedure SetValue(const Value: string);
virtual;
functipn ValueAvailable: Boolean;
property Designer: IDesigner read FDesigner;
property PrivateDirectory: string read, GetPrivateDirectory;
property PropCount: Integer read FPropCount;
property Value: string read GetValue write SetValue; end;
Методы данного класса, приведенные ниже, можно переопределять для изменения поведения редактора свойств.
Рассмотрим в качестве примера переработанное свойство Hint, которое применяется для показа всплывающей подсказки при задержании указателя мыши над компонентом. В стандартном случае такая подсказка имеет всего одну строку. Попробуем сделать свойство Hint многострочным.
Использование вариантной записи
Листинг 2.1. Использование вариантной записиvar Person = recordR>
FirstName, LastName: string[40];
BirthDate: TDate; case Citizen: Boolean of
True: (Birthplace: string [40]);
False: (Country: string [20];
EntryDate, ExitDate: TDate);
end; Переменная Citizen в представленном выше листинге должна быть истинна, если человек является гражданином России, и ложна — в противном случае.
Файлы
Файл — это именованная порядковая последовательность элементов одного типа, которая находится на внешнем запоминающем устройстве (дискете, жестком диске и др.).
По определению, можно сказать, что файл похож на одномерный динамический массив. Отличие все же есть. Файл размещается не в оперативной памяти компьютера, а на диске и не требует предварительного задания своего размера.
Для работы с файлами программисты используют файловые переменные или логические файлы.
Файловая переменная — это переменная, которая связывается с конкретным файлом на диске. Все операции с этой переменной приводят к изменению физически размещенного на диске файла.
Файлы бывают разного типа, в зависимости от входящих в него элементов. Так, различают текстовые, типизированные и нетипизированные файлы.
Текстовые файлы состоят из строк текста переменной длины. Такие файлы объявляются с помощью слова Text File. Приведем пример объявления файловой переменной текстового файла:
var f: TextFile;
Типизированные файлы состоят из данных определенного (указанного) типа. Такие файлы объявляются с помощью конструкции file of typeData. Например:
var f1: file of real; f2: file of boolean
Нетипизированные файлы могут содержать элементы, тип которых не указан. Такие файлы объявляются просто словом file. Например:
var f: file;
Кроме доступа к файлу с помощью файловых переменных, многие компоненты Kylix предоставляют свои собственные методы работы с файлами, такие как LoadFromFile или SaveToFile. О них мы расскажем далее, когда будем описывать свойства и методы основных компонентов Kylix.
Назад Вперед
Пример использований указателей
Листинг 2.2. Пример использований указателейvar
X, Y: Integer; / / объявление целых переменных X и Y Р: ^Integer; / / Р - указатель целого типа begin
X := 17; / / присваиваем значение переменной X Р := @Х ; / / присваиваем адрес переменной X указателю Р Y := Р^; / / разыменовываем указатель Р и присваиваем результат / / переменной Y end; Итак, для назначения указателю адреса объекта (в нашем случае — переменной х) мы воспользовались операцией @. Символ @, поставленный перед объектом, определяет адрес этого объекта в оперативной памяти.
Символ ^ имеет два назначения. Во-первых, если он стоит перед идентификатором типа, он обозначает тип данного указателя. Если же он стоит после переменной типа указателя, как в последней строке нашего примера, то он разыменовывает указатель. Операция разыменовывания указателя применяется для получения доступа к значению адресуемых данных.
После выполнения программы, представленной на листинге 2.2, обе переменные х и Y будут иметь одинаковое значение — 17.
Процедурные типы данных
Процедурные типы данных применяются для того, чтобы можно было процедуры и функции понимать как обычные значения, которые можно присваивать переменным, или выполнять с ними различные действия.
Описание данных процедурного типа похоже на описание процедуры или функции. На листинге 2.3 представлено описание процедурных указателей.
Описание процедурных указателей
Листинг 2.3. Описание процедурных указателейtype
TIntegerFunction = function: Integer; TProcedure = procedure; TStrProc = procedure(const S: string);
TMathFunc = function (X: Double): Double; var
F: TIntegerFunction; / / F - это функция без параметров, которая
/ / возвращает целое число
Proc: TProcedure; / / Proc - это процедура без параметров SP: TStrProc; / / SP - это процедура, у которой есть один
/ / строковый параметр М: TMathFunc; / / М - это функция с действительным параметром
/ / данная функция возвращает действительное значение Для описания данных процедурного типа используется конструкция of object. Например:
type
TMethod = procedure of object;
TNotifyEvent = procedure(Sender: TObject) of object;
Данные процедурного типа применяются, например, для назначения обработчиков события.
Вариантные типы данных
Иногда возникает необходимость работы с типами данных, которые не могут быть определены во время разработки приложения или тип которых изменяется. Для этого в язык Object Pascal были введены так называемые вариантные типы данных. Переменные вариантного типа могут содержать данные разных типов, кроме структурных типов данных, указателей и типа Int64. Для объявления переменной вариантного типа используется слово variant. Все типы являются совместимыми с типом variant, и компилятор делает необходимые преобразования типов автоматически.
Пример, приведенный на листинге 2.4, показывает применение вариантного типа данных.
Использование данных вариантного типа
Листинг 2.4. Использование данных вариантного типаvar
V1, V2, V3, V4, V5: Variant; I: Integer;
D: Double; S: string; begin V1 := 1; / / целое значение
V2 := 1234.5678; / / действительное значение
V3 := 'Это строка!'; / / строковое значение
V4 := '1000'; / / строковое значение
V5 := V1 + V2 + V4; / / действительное значение, равное 2235.5678 I := V1; / / I=1 (целое значение) D := V2; / / D = 1234.5678 (действительное значение)
S := V3; / / S = 'Это строка!' (строковое значение)
I := V4; / / I = 1000 (целое значение)
S := V5; / / S = '2235.5678' (строковое значение) end; Переменная вариантного типа может принимать два дополнительных значения:
Использование директивы $IFDEF
Листинг 21.1.Использование директивы $IFDEF// Если среда - Windows
[$IFDEF MSWINDOWS]
IniFile.LoadfromFile('с:\x.txt');
[$ENDIF]
// Если среда - Kylix
[$IFDEF LINUX]
IniFile.LoadfromFile('/home/name/x.txt') ;
[$ENDIF]
6. Найдите ссылки на пути ко всем файлам проекта:
• укажите правильные пути ко всем файлам Linux;
• смените ссылки на имена дисковых накопителей (например, С:\);
• в местах, где вы указали множество путей, смените разделитель путей с точки с запятой ";" на двоеточие ":";
• так как имена файлов являются в Linux чувствительными к регистру, убедитесь, что в приложении все имена файлов записаны правильно.
Примечание
Пути в Linux используют прямой слэш Т как разделитель (например, /usr/lib). Читатели, которые не знакомы с организацией файловой системы Linux, могут обратиться за краткой информацией в Приложение 3 данной книги.
7. Откомпилируйте проект в Linux. Просмотрите список ошибок, которые укажут, что еще необходимо сделать для того, чтобы ваше приложение работало в среде Linux.
Назад Вперед
Код для среды Windows
Листинг 21.2.Код для среды Windowswhile p^ <>
#0 do
begin
if р^ in LeadBytes then
inc (p) ;
inc(p);
end;
Этот код можно преобразовать в платформонезависимый, как показано в листинге 21.3.
Платформонезависимый код
Листинг 21.3. Платформонезависимый кодwhile р^ <>
#0 do
begin
if р^ in LeadBytes then
p := StrNextChar(p)
else
inc(p);
end;
Если использование функций библиотек не приводит к работающему решению, можно попробовать изолировать специфичный код в блоки $IFDEF. Однако постарайтесь ограничить число таких блоков.
Назад Вперед
Неправильная работа директивы $IFDEF
Листинг 21.4.Неправильная работа директивы $IFDEF{$IFDEF WIN32}
{32-битный код Windows размещаем здесь}
{$ELSE}
{16-битный код Windows находится здесь} //!! По ошибке Linux может
// попробовать выполнить этот код '!!
{$ENDIF}
Назад Вперед
Обработчик события
Листинг 21.5.Обработчик события AfterPost procedure TForm1.ClientDataSetlAfterPost(DataSet: TDataSet);begin
with DataSet as TClientDataSet do
ApplyUpdates(1);
end;
Назад Вперед
Примеры использования арифметических операций
Листинг 3.1. Примеры использования арифметических операцийvar
а, b, с, d: Integer; // Объявляем четыре целочисленных переменных
begin
a:=7; b:=5; c:=-10; // Присваиваем трем из них начальные значения
d:=a+b; // Результатом будет число 12
d:=-d; // Результатом будет число -12
d:=d+c; // Результатом будет число -22
d:=d div с; // Результатом будет число 2
d:=a mod b; // Результатом будет число 2 end;
Кроме вышеперечисленных операций, над целочисленными данными можно производить поразрядные операции, представленные в табл. 3.3. Особенностью этих арифметических операций является то, что они выполняются побитно над операндами, переведенными в двоичную форму, Результат выдается в десятичной системе счисления.
Примеры использования побитовых операций
Листинг 3.2. Примеры использования побитовых операцийvar
a,b,с: Integer; // Объявляем три целочисленные переменные begin
а =175; b:=77; // Двум из них присваиваем начальные значения
с =not a; // Результатом будет число -176
с =а or b; // Результатом будет число 239
с =а and b; // Результатом будет число 13
с =а хоr b; // Результатом будет число 226
с =а shl 1; // Результатом будет число 350
с =b shr 1; // Результатом будет число 38 end;Число 175 в двоичной системе выглядит так: 10101111. А число 77 так: 1001101. Операции производятся поразрядно справа налево, затем результат переводится в десятичную систему счисления.
Сдвиг на один разряд влево равносилен умножению числа на 2. Сдвиг на один разряд вправо равносилен делению числа нацело на 2 с отбрасыванием дробной части.
Кроме всего рассмотренного выше, язык Object Pascal имеет достаточно большое количество функций для работы с числовыми данными. Эти функции можно также использовать в арифметических выражениях. Среди прочих наиболее часто используются следующие функции:
Приведем пример вычисления выражения, в котором присутствуют арифметические функции:
a:=sqr( (152+b) /2*cos (3.14+b) +sqrt (23)) ;
Логические выражения
Логические выражения это выражения, в которых содержатся:
Пример работы с оператором with
Листинг 3.3 Пример работы с оператором withtype TDate = record // Объявляем новый тип - запись с тремя полями
Day: Integer; // Поле День Month: Integer; // Поле Месяц
Year: Integer; // Поле Год end;
var OrderDate: TDate; // Объявляем запись OrderDate begin with OrderDate do // Далее оперируем с записью OrderDate
if Month =12 then begin Month := 1;
Year := Year + 1;
end
else
Month := Month + 1; end;
Таким образом, при обращении к полям записи нам не нужно указывать имя самой записи.
Кроме обращения к полям записи, при помощи оператора доступа можно повысить удобство работы с объектами Kylix, которые мы рассмотрим во второй части книги.
Назад Вперед
Пример использования оператора case
Листинг 3.4. Пример использования оператора casecase I of // В зависимости от значения переменной I
1..5: С := 'До пяти'; // Если оно от 1 до 5, то переменная С='До пяти' 6..9: С := 'Выше пяти'; // Если оно от б до 9, то переменная С='Выше
// пяти' 0, 10..99: С := 'Вне области допустимых значений'; // Если оно равно 0
// или от 10 до 99, то С='Вне области допустимых значений' else
С := ''; // Иначе, если ни одно из условий не выполняется,
//С равно пустой строке end;
Таким образом, мы с помощью одного оператора case охватили множество значений. Более того, код программы читается довольно легко. Посмотрим, что было бы, если бы для той же самой задачи мы использовали оператор условия (листинг 3.5).
Пример использования оператора условия
Листинг 3.5. Пример использования оператора условияif I in [1..5] then С := 'До пяти' else if I in [6..10] then С := 'Выше пяти'
else if (I = 0) or (I in [10..99]) then С := 'Вне области допустимых значений' else
С := ";
На листинге 3.5 получилась довольно тяжело читаемая конструкция.
Операторы цикла
Иногда необходимо, чтобы какая-либо часть программы выполнялась несколько раз. Для этого во всех языках программирования, в том числе и в языке Object Pascal, используются циклы.
Цикл — это последовательность операторов, команд, которая выполняется более одного раза, т. е. повторяется. Такие операторы и команды называют телом цикла.
В языке Object Pascal имеются три вида операторов цикла:
В тело цикла допускается помещать оператор безусловного перехода goto. Кроме того, для досрочного прерывания выполнения цикла можно использовать специальную процедуру break. Вызов этой процедуры приводит к прекращению выполнения операторов тела цикла и переходу к выполнению операторов, расположенных сразу за циклом. Вы можете досрочно завершить выполнение данного повторения цикла при помощи вызова процедуры continue. Ее вызов приводит к передаче управления сразу в конец цикла, т. е. досрочному завершению данного повторения.
Операторы циклов допускают множественные вложения друг в друга. При вложении сначала выполняются внутренние операторы цикла, а затем — внешние. Далее мы приведем примеры вложений операторов цикла друг в друга.
Цикл с параметром
Цикл с параметром применяется в том случае, когда заранее известно, сколько раз он должен выполниться. Данный цикл выглядит следующим образом:
For параметр:=нач.значение to кон.значение do оператор;
или
For параметр:=нач.значение downto кон.значение do оператор;
Параметр цикла — это переменная порядкового типа, которая объявлена в разделе объявления переменных.
Начальное значение — это значение, которое принимает параметр цикла. Естественно, что данное значение должно быть того же типа, что и переменная параметра цикла.
Конечное значение — это значение, которое может принимать параметр цикла.
Оператор — это одиночный или составной оператор, который и представляет собой тело цикла.
Внимание
Тело цикла не должно изменять параметр цикла, т. к. это может привести к непредсказуемым последствиям. В частности, к бесконечному циклу (зацикливанию программы).
И первый и второй варианты написания цикла изменяют параметр цикла на единицу. В первом случае (for ... to) происходит увеличение параметра на единицу при каждом проходе цикла, во втором случае (for ... downto) — уменьшение параметра цикла на единицу.
Итак, цикл с параметром выполняется несколько раз, постепенно увеличивая или уменьшая значение параметра: до тех пор, пока это значение не достигнет конечного значения.
Примечание
Цикл не выполняется ни разу, если для первого варианта цикла начальное значение параметра больше конечного, а для второго варианта — конечное значение больше начального.
Приведем несколько примеров циклов с параметрами (листинг 3.6).
Примеры циклов с параметрами
Листинг 3.6. Примеры циклов с параметрамиfor i:=l to 20 do // Начало цикла
begin // Начало составного оператора
s:=s+i; // Тело цикла
a:=a*i;
end; // Конец цикла. Значение i увеличивается на 1 for i:=l to 10 do // Начало внешнего цикла begin // Начало составного оператора
for j:=10 downto 1 do // Начало внутреннего цикла begin
s:=s+j; // Тело внутреннего цикла а:=s+а;
end; // Конец внутреннего цикла. i уменьшается на 1
a:=a*s; end; // Конец внешнего цикла. i увеличивается на 1 Цикл с предусловием
Цикл с предусловием применяется в том случае, если число повторений заранее неизвестно и если при некоторых условиях тело цикла может не выполняться совсем. Данный цикл выглядит следующим образом:
while условие do оператор;
Условие представляет собой логическое выражение, которое может быть ложным или истинным.
Оператор — это тело цикла. Он может быть простым или составным.
Данный Цикл выполняется в том случае, когда условие имеет значение True. Как только условие примет значение False, цикл выполняться не будет.
Переменные, входящие в условие цикла, могут быть произвольными (не обязательно порядковыми).
Пример оператора цикла с предусловием представлен ниже (листинг 3.7).
Пример цикла с предусловием
Листинг 3.7, Пример цикла с предусловиемwhile I >
0 do // Начало цикла
begin // Начало составного оператора
S : = S+I; // Тело цикла
I := I - 1; // Изменяем переменную i самостоятельно end; // Конец цикла. Переменная i не изменяется
Примечание
В отличие от цикла с параметром, при использовании других видов циклов следите за тем, чтобы условие цикла когда-нибудь изменилось. Для этого нужно изменять переменные, входящие в условие цикла в теле цикла.
Данный цикл не выполняется совсем, если при первоначальной проверке условия оно имеет значение False.
Цикл с постусловием
Цикл с постусловием используется в случае, когда желательно, чтобы тело цикла выполнилось хотя бы один раз, а общее количество повторений цикла заранее неизвестно.
Данный цикл имеет следующий вид:
repeat
оператор1;
...
операторN; until условие;
Операторы, расположенные между словами repeat и until, представляют собой тело цикла. Условие — это логическое выражение.
Операторы цикла выполняются, по крайней мере, один раз, а затем происходит проверка истинности условия. Если условие является ложным (False), то операторы цикла выполняются повторно. Цикл будет выполняться до тех пор, пока условие цикла не станет истинным (True).
Рассмотрим пример применения цикла с постусловием (листинг 3.8).
Пример цикла с постусловием
Листинг 3.8. Пример цикла с постусловиемrepeat // Начало цикла
К : = I mod J; // Тело цикла I : = J;
J : = К; until J = 0; // Условие цикла Назад
Описание функции Mах
Листинг 4.1. Описание функции Mахfunction Max(A: array of Real; N: Integer): Real; var
X: Real;
I: Integer; begin
X := A[0]; for I := 1 to N - 1 do
if X < A[I] then X : = A[ I ];
Max := X; end;
Вызов данной функции может выглядеть так:
М : = Мах(В, 12) ;
При этом переменная м должна иметь тип Real, массив в — тоже Real, a вторым параметром должно быть целое число (в нашем примере 12). Таким образом, вызов данной функции при этих параметрах поместит в переменную м самое большое значение из всех, хранящихся в элементах одномерного 12-элементного массива B.
Назад Вперед
Описание процедуры NumString
Листинг 4.2. Описание процедуры NumStringprocedure NumString(N: Integer; var S: string);
var
V: Integer; begin V := Abs(N) ;
S : = " ;
repeat
S := Chr(V mod 10 + Ord('0')) + S; V := V div 10;
until V = 0;
if N < 0 then S := '-' + S; end;
Для вызова данной процедуры можно в любом месте основной программы поступить следующим образом:
NumString(17, MyString);
В результате выполнения данного оператора, который называется оператором вызова процедуры, в строковую переменную с именем MyString будет помещено значение "17".
Назад Вперед
Описание свойств объекта
Листинг 5.1. Описание свойств объектаtype TMyObject = class // Объявление нового класса private
FInt: integer; // Объявление целочисленного поля FReal: real; // Объявление вещественного поля FChar: char; // Объявление поля символьного типа published
property Prop1: integer read FInt write FInt; // Объявление // свойства Prop1, с помощью которого можно читать значение поля // FInt и записывать данные в это же поле
property Prop2: real read FRea1; // Свойство Ргор2 предназначено // только для чтения значения поля FReal
property РrорЗ: char write FChar; // Свойство Рrор3 предназначено // только для записи данных в поле FChar end;
После такого объявления программист получает доступ к полям объекта через три свойства Prop1, Prop2 и Рrор3.
Назад Вперед
Листинг 7.1. Область видимости объекта Form1
procedure TForml.ButtonlClick (Sender: TObject);
begin
Color := clGray; // Задаем цвет формы Caption := 'Форма с одной кнопкой'; // Изменяем заголовок формы Button1.Caption := 'OK'; // Изменяем заголовок кнопки end;
Итак, на приведенном выше листинге изменим значения свойств формы Form1 без указания имени формы, т. к. данная часть программного кода является областью видимости для формы Form1. Метод Button1Click является частью объекта Form1.
Две строки
Color := clGray; // Задаем цвет формы
Caption := 'Форма с одной кнопкой'; // Изменяем заголовок формы
будут равносильны строкам
Form1.Color := clGray; // Задаем цвет формы
Form1.Caption := 'Форма с одной кнопкой'; // Изменяем заголовок формы
Последняя строка листинга 7.1 изменяет значение свойства другого компонента (Button1), поэтому нуждается в указании его имени.
Назад Вперед
Освобождение ресурсов графической подсистемы
Листинг 8.1. Освобождение ресурсов графической подсистемы// загрузка картинки в Bitmap1
Bitmap1. LoadFromFile ('mypicture.bmp') ;
//копирование в Bitmap2 из Bitmap1
Bitmap2.Assign (Bitmap1);
// применение метода Dormant и освобождение ресурсов графической подсистемы
Bitmap2.Dormant;
Image1.Canvas.Draw (10, 10, Image2.Picture.Bitmap);
Таким образом, в координаты (10,10) канвы картинки Image1 будет занесен рисунок из канвы картинки Image2.
Image1.Canvas.DrawFocusRect (Rect (0,0,30,30);
List.Error ('Ошибка в элементе %u списка List', I);
Выполнение данной строки вызовет сообщение об ошибке в какой-либо строке списка.
Не применяйте метод Exchange для отсортированных списков— это может нарушить упорядоченность списков.
with Image1.Canvas do
FillRect (Rect (0, 0, Width, Height) );
будут ли при поиске учитываться компоненты, в которых свойство TabStop установлено в false. Если значение данного параметра равно true, то такие компоненты не учитываются, иначе — учитываются. Последний параметр CheckParent применяется для того, чтобы указывать, учитывать ли при поиске только те компоненты, которые являются прямыми потомками данного оконного компонента. Если данный параметр равен false, то просматриваются все компоненты, иначе — только прямые потомки.
with Image1.Canvas do begin Brush.Color := clRed; FrameRect ( Rect (10,10,150,100) );
end;
Component.Visible := false;
Если данный компонент является оконным и содержит в себе другие компоненты, то эти компоненты также становятся невидимыми.Примечание
Обратите внимание на тот факт, что хотя компонент является невидимым, все его свойства и методы являются доступными.
Например:
Image1.Canvas.Polygon ( [ Point (10, 10), Point (30,10),
Point (130, 30), Point (240, 120) ] );
Вышеприведенный код рисует на канве компонента Image1 закрашенный четырехугольник, координаты которого заданы непосредственно.
Обработка события OnDragOver
Листинг 8.2.Обработка события OnDragOverprocedure TForm1.ListBox2DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := Source is TListBox; end;
В данном обработчике мы указываем, что на компонент ListBox2 можно перетаскивать компоненты типа TListBox. Затем в обработчике события OnDragDrop запишем следующий код (листинг 8.3).
Код обработки OnDragOver
Листинг 8.3. Код обработки OnDragOverprocedure TForm1.ListBox2DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
ListBox2. Items .Add (ListBox1. Items[ListBox1. ItemIndex]);
end;
Таким образом, мы добавляем выбранную строку компонента ListBox1 в компонент ListBox2.
Все! Можно запускать приложение при помощи клавиши
. Попробуйте перетащить любую строку из первого списка, во второй.
Oбработчик события OnEndDrag
Листинг 8.4.Oбработчик события OnEndDragprocedure TForm1.Component1EndDrag (Sender,
Target: TObject; X, Y: Integer);
begin
If Target = Nil then ShowMessage ('Перенесение объекта '+
(Sender as TControl).Name + ' завершалось неудачно') else
ShowMessage((Sender as TControl).Name + ' перенесен в '
+ (Target as TControl).Name);
end;
Добавим код, записанный в листинге 8.3, в вышеописанное приложение. При этом код нужно поместить в обработчике события OnEndDrag для первого списка (ListBox1). В результате, при каждом успешном перетаскивании строки из первого списка во второй будет выдаваться окно-сообщение (Рисунок 8.18), а при неудачном — окно-сообщение, изображенное на рис, 8.19.
Синтаксис конструкции try except try
Листинг 9.1. Синтаксис конструкции try...except try// здесь находятся операторы защищенного кода
except
on Exception1 do // операторы, выполняемые в случае
// возникновения ошибки 1
on Exception2 do // операторы, выполняемые в случае // возникновения ошибки 2
. . . else
// операторы, выполняемые в случае возникновения ошибки, не являющейся ни ошибкой 1
//ни ошибкой 2 end;Таким образом, вы размещаете "опасный" участок кода после слова try, и если при выполнении этого кода произойдет исключительная ситуация, оно прекратится и начнут выполняться команды, расположенные после слова except.
В разделе except могут находиться или только операторы обработки исключений, которые начинаются со слова-приставки on, или только произвольные операторы, не являющиеся операторами обработки исключений. В вышеприведенном листинге представлена ситуация, когда в разделе except находятся только операторы обработки исключений. Если в блоке операторов, расположенных после слова try, произошла ошибка Exception1, то будут выполнены только те команды, которые расположены после слов on Exception1 do. Далее объект исключения уничтожается и программа продолжает выполнять операторы, расположенные после слова end; рассматриваемой конструкции.
Раздел после слова else является необязательным и может отсутствовать. Он предназначен для обработки любых других исключений, не предусмотренных в разделе except. Если же раздел else отсутствует, но в защищенном коде произошла исключительная ситуация, не предусмотренная ни одним обработчиком исключений on Exception do, то произойдет стандартная (определенная операционной системой) обработка данной исключительной ситуации с появлением соответствующего информационного окна с сообщением об ошибке.
Рассмотрим оператор обработки исключений более подробно. Как видно из листинга 9.1, данный оператор может присутствовать внутри раздела except или принимать одну из двух форм:
on <класс исключения>
do <оператор>
;
или
on <имя>
: <класс исключения>
do // операторы, в которых можно использовать свойства исключения
В листинге 9.1 мы привели только первую форму представления оператора. Но, так как исключение является объектом, то было бы иногда очень удобно обратиться к его свойствам. Однако для того, чтобы обращаться к свойствам какого-либо объекта, необходимо знать его имя. Вторая форма оператора обработки исключений применяется именно тогда, когда нам нужно обратиться к свойствам возникшего исключения. Для этого исключению присваивается временное имя <имя>
и к его свойствам можно обращаться через точку:
<имя>
.<свойство>
В листинге 9.2 приведена та же конструкция, что и в листинге 9.1, только в блоке except нет операторов обработки исключений. Таким образом, при возникновении любой исключительной ситуации в защищенном блоке будут выполняться операторы, расположенные после слова except.
Конструкция try except без операторов обработки исключений
Листинг 9.2. Конструкция try...except без операторов обработки исключенийtry
// здесь находятся операторы защищенного кода
except
Operator1; // операторы, выполняемые в случае
Operator2; // возникновения любой исключительной ситуации, Operator3; // возникшей в защищенной области
...
end;
Приведем небольшие примеры использования защищенных блоков программы. В листинге 9.3 представлен пример обработки исключительной ситуации деления на ноль.
Обработка деления на ноль
Листинг 9.3.Обработка деления на нольtry
а:=8;
b:=0;
с:=а/b; except
on EZeroDivide do MessageBox{'Внимание! Деление на ноль!') end;
При выполнении данного кода будет сгенерирована исключительная ситуация, принадлежащая к классу EZeroDivide (деление целых чисел на ноль). Данная исключительная ситуация обработается в секции except и приложение выдаст на экран окно с сообщением Внимание! Деление на ноль! (Рисунок 9.1).
Использование временного имени объекта ислючения
Листинг 9.4. Использование временного имени объекта ислюченияtry
ScrollBar1.Max:=ScrollBar.Min-1; except
on E: EInvalidOperation do
MessageDlg('Произошло исключение: '+Е.Message, mtlnformation, [mbOK],0)
end;
В защищенном блоке кода программы будет осуществлена недопустимая для объекта ScrollBox1 операция присвоения максимального значения списка меньшего, чем минимальное значение. Возникнет исключение класса EInvalidOperation. Таким образом, мы присваиваем объекту исключения, принадлежащего к классу EinvalidOperation, временное имя Е, после чего можем обращаться к свойствам объекта исключения Е. Мы самостоятельно выводим в окне сообщения текст ошибки Е.Message, который выдается по умолчанию (в том случае, если бы нашего обработчика исключения не было). Результат работы кода листинга 9.4. представлен на Рисунок 9.2.
Регенерация исключения
Листинг 9.5.Регенерация исключенияtry
{ операторы } except
on <класс исключения>
do begin
{операторы обработки исключения} raise; // Регенерация исключения end; end;
После выполнения операторов обработки исключения, написанных программистом, выполняется команда raise, которая снова принудительно вызывает это исключение, после чего управление передается стандартному обработчику исключений.
В случае, если исключение успешно проходит через все блоки try в коде приложения, вызывается метод HandleException. Он показывает диалоговое окно ошибки. Вы можете вызвать этот метод так, как показано в листинге 9.6.
Вызов метода HandleException
Листинг 9.6.Вызов метода HandleExceptiontry { операторы } except
Application,HandleException(Self);
end;
Теперь рассмотрим конструкцию, предназначенную для защиты ресурсов приложения.
Конструкция try ... finally служит для защиты кода, записанного в разделе finally от исключительных ситуаций, которые в силу каких-либо причин могут происходить в разделе try. Синтаксис этой конструкции представлен в листинге 9.7.
Конструкция try finally
Листинг 9.7.Конструкция try...finallytry
{операторы, способные создать исключительную ситуацию}; finally
{защищенные операторы, выполняемые в любом случае}; end;
Таким образом, операторы, которые размещены после ключевого слова finally, будут выполняться в любом случае, независимо от того, была сгенерирована исключительная ситуация или нет.
Если в разделе try была сгенерирована исключительная ситуация, то управление немедленно передается разделу finally. Если исключительной ситуации в разделе try не было, блок finally все равно будет выполняться. Даже если в разделе finally произойдет ошибка, выполнение операторов этого раздела будет продолжено до конца без выдачи сведений об ошибке.
В конструкции try . . . finally не происходит обработки исключений, она используется в основном для освобождения ресурсов памяти. Таким образом, в данной конструкции нуждаются операции с файлами, памятью, ресурсами операционной системы и объектами.
Код обработки исключения можно разбить на блоки try . . . except . . . end и try . . . finally . . . end. Эти блоки могут быть вложенными (Рисунок 9.3).
Генерация молчаливого исключения
Листинг 9.8. Генерация молчаливого исключенияprocedure TForm1.Button1Click(Sender: TObject);
var
I: Integer; begin for I := 1 to 10 do {цикл 10 paз} begin
ListBox1.Items.Add(IntToStr(I));
{добавляем номер в список} if I = 7 then Abort; {прерываем добавление номеров в список после
добавления седьмого номера} end; end;
Запустим программу. В результате работы программы, после нажатия кнопки Button1, в список будет добавлено семь строк с номерами от 1 до 7 (Рисунок 9.5).
Если нажать кнопку несколько раз, то в список будут добавлены новые строки с номерами от 1 до 7 после имеющихся (Рисунок 9.6).
модуля справочных систем CLX и VCL
справочных систем CLX и VCLНиже приведен листинг файла /kylix/source/clx/HelpIntfs.pas, который обеспечивает необходимые интерфейсы файла справки, а также менеджер файлов.
{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * }
{ }
{ Kylix и Delphi кросс-платформенная библиотека визуальных компонентов }
{ }
{ Copyright (с) 2000, 2001 Borland Software Corporation }
{ }
{ Этот файл может распространяться и/или модифицироваться в соответствии с условиями GNU General Public License (GPL) версии 2 }
{ http://www.borland.com/kylix/gpl.html. }
{ }
{ Файл лицензии license.txt прилагается к составу данного программного обеспечения. }
{ }
{************************************************************************}
unit Helplntfs;
{***********************************************************************}
{ }
{ Этот модуль является главным для различных справочных систем VCL/CLX }
{ TApplication содержит указатель на интерфейс IHelpSystem, через }
{ который обеспечиваются вызовы менеджера помощи. Менеджер помощи }
{ содержит список программ, обеспечивающих показ файлов справки, и }
{ реализует поддержку интерфейса ICustomHelpViewer. Программы для }
{ просмотра файлов справки взаимодействуют с менеджером помощи через }
{ интерфейс IHelpManager. }
{ }
{ Такой же механизм применяется при разработке пакетов, которые }
{ интегрируются в систему помощи IDE; вызов HelpIntfs.RegisterViewer( ) }
{ внутри процедуры Register() вызовет регистрацию просмотрщика. }
{ }
{*********************************************************************}
interface
uses SysUtils, Classes;
type
{ IHelpSelector. IHelpSelector используется системой помощи для того, чтобы узнать у приложения, какие ключевые слова оно поддерживает. }
IHelpSelector - interface(IInterface)
['{B0FC9358-5F0E-11D3-A3B9-00C04F79AD3A}']
function SelectKeyword(Keywords: TStrings) : Integer;
function TableOfContents(Contents: TStrings): Integer;
end;
{ IHelpSystem. IHelpSystem - это интерфейс, с помощью которого приложение посылает запрос об отображении файла справки. ShowHelp( ) использует функциональность, которая гарантированно поддерживается всеми программами для просмотра файлов справки. ShowContextHelp( ) и ShowTopicHelp( ) поддерживаются только расширенными просмотрщиками файлов справки. В случае, когда расширенные просмотрищики не установлены, ShowTableOfContents запрашивает систему об отображении содержания файла справки и показывает окно диалога, с помощью которого пользователь может выбрать один из просмотрщиков. Если ни один из установленных просмотрщиков не поддерживает отображение содержания, генерируется исключительная ситуация EHelpSystemException. Hook( ) представляет собой механизм, с помощью которого приложение запрашивает
систему помощи для упаковки специфичных winhelp-команд в команды, которые понимают установленные просмотрщики файлов справки.}
IHelpSystem = interface(IInterface)
['{B0FC9353-5F0E-11D3-A3B9-00C04F79AD3A} ' ]
procedure ShowHelp(const HelpKeyword, HelpFileName: String);
procedure ShowContextHelp(const ContextID: Longint; const HelpFileName: String);
procedure ShowTableOfContents;
procedure ShowTopicHelp(const Topic, HelpFileName: String);
procedure AssignHelpSelector(Selector: IHelpSelector);
function Hook(Handle: Longint; HelpFile: String; Comand: Word; Data: Longint): Boolean;
end;
{ ICustomHelpViewer. Справочная система взаимодействует с просмотрщиками
файлов справки с помощью данного интерфейса. В случае, когда в системе
зарегистрировано более одного просмотрщика, справочная система вызывает
функцию UnderstandsKeywordО для каждого из них. Данная функция
возвращает число доступных ключевых слов. В случае, когда более чем один
просмотрщик может работать с нужными ключевыми словами, эти
просмотрщики запрашиваются на список поддерживаемых ключевых строк
с помощью метода GetHelpStrings( );
менеджер помощи предлагает пользователю выбрать один из просмотрщиков
и затем вызывает метод ShowHelp( ) только для выбранной пользователем
программы просмотра файлов помощи. Во время регистрации менеджер
помощи вызывает метод NotifyID для того, чтобы присвоить просмотрщику
уникальный номер. В случае, когда связь с просмотрщиком по каким-либо
причинам оборвалась, вызывается метод Release( ) и менеджеру помощи будет
передан этот номер. Если менеджер помощи сам разрывает связь, будет
вызван метод ShutDown( ) для всех просмотрщиков. Если менеджер помощи
получает просьбу о завершении работы всех просмотрщиков помощи, он
вызывает метод SoftShutDown( ) для всех просмотрщиков. }
ICustomHelpViewer = interface(IInterface)
['{B0FC9364-5F0E-11D3-A3B9-00C04F79AD3A}']
function GetViewerName : String;
function UnderstandsKeyword(const HelpString: String): Integer;
function GetHelpStrings(const HelpString: String): TStringList;
function CanShowTableOfContents : Boolean;
procedure ShowTableOfContents;
procedure ShowHelp(const HelpString: String);
procedure NotifyID(const ViewerID: Integer);
procedure SoftShutDown;
procedure ShutDown;
end;
IExtendedHelpViewer = interface(ICustomHelpViewer)
['{B0FC9366-5F0E-11D3-A3B9-00C04F79AD3A}']
function UnderstandsTopic(const Topic: String): Boolean;
procedure DisplayTopic(const Topic: String);
function UnderstandsContext(const ContextID: Integer;
const HelpFileName: String): Boolean;
procedure DisplayHelpByContext(const ContextID: Integer;
const HelpFileName: String);
end;
ISpecialWinHelpViewer - interface(IExtendedHelpViewer)
['{B0FC9366-5F0E-11D3-A3B9-OOC04F79AD3A}']
function CallWinHelp(Handle: LongInt; const HelpFile: String; Command: Word;
Data: LongInt): Boolean;
end;
IHelpManager = interface
['{B0FC9366-5F0E-11D3-A3B9-OOC04F79AD3A}']
function GetHandle: LongInt; { sizeof(LongInt) = sizeof (HWND) }
function GetHelpFile: String;
procedure Release(const ViewerID: Integer);
end;
EHelpSystemException = class(Exception);
function RegisterViewer(newViewer: ICustomHelpViewer;
out Manager: IHelpManager) : Integer;
function GetHelpSystem(out System: IHelpSystem) : Integer;
{$IFDEF LINUX}
const
HELP_CORTEXT = 1;
HELP_QUIT = 2;
HELP_INDEX = 3;
HELP_CONTENTS = HELP_INDEX;
HELP_HELPONHELP = 4;
HELP_SETINDEX = 5;
HELP_SETCONTENTS = HELP_SETINDEX;
HELP_CONTEXTPOPUP = 8;
HELP_FORCEFILE = 9;
HELP_CONTEXTMENU =10;
HELP_FINDER =11;
HELP_WM_HELP =12;
HELP_SETPOPUP_POS =13;
HELP_TCARD_OTHER_CALLER =17;
HELP_KEY = 257;
HELP_COMMAND = 258;
HELP_PARTIALKEY = 261;
HELP_MULTIKEY = 513;
HELP_SETWINPOS = 515;
HELP_TCARD__DATA = $10;
HELP_TCARD = $8000;
{$ENDIF}
implementation
{$IFDEF MSWINDOWS}
uses Contnrs, Windows, RTLConsts;
{$ENDIF}
{$IFDEF LINUX}
uses Libc, Contnrs, RTLConsts;
{$ENDIF}
type
THelpViewerNode = class(TObject)
private
FViewer: ICustomHelpViewer;
FViewerID: Integer;
public
constructor Create(Viewer: ICustomHelpViewer);
property Viewer: ICustomHelpViewer read FViewer;
property ViewerID : Integer read FViewerID write FViewerID;
end;
ТНеlpManager = class(TInterfacedObject, IHelpSystem, IHelpManager)
private
FHelpSelector: IHelpSelector;
FViewerList: TObjectList;
FExtendedViewerList: TObjectList;
FSpecialWinHelpViewerList: TObjectList;
FMinCookie : Integer;
FHandle: LongInt;
FHelpFile: String;
procedure UnloadAllViewers;
procedure DoSoftShutDown;
procedure DoTableOfContents;
function CallSpecialWinHelp(Handle: LongInt; const HelpFile: String;
Command: Word; Data: LongInt): Boolean;
public
constructor Create;
function RegisterViewer(newViewer: ICustomHelpViewer): IHelpManager;
{ IHelpSystem }
procedure ShowHelp(const HelpKeyword, HelpFileName: String );
procedure ShowContextHelp(const ContextID: Longint; onst HelpFileNawe: String);
procedure ShowTableOfContents;
procedure ShowTopicHelp(const Topic, HelpFileName: String);
procedure AssignHelpSelector(Selector: IHelpSelector);
function Hook(Handle: Longint; HelpFile: String;
Command: Word; Data: Longint) : Boolean;
{ IHelpManager }
function GetHandle: Longint;
function GetHelpFile: String;
procedure Release(const ViewerID: Integer);
property Handle : Longint read FHandle write FHandle;
property HelpFile : String read FHelpFile write FHelpFile;
destructor Destroy; override;
end;
var
HelpManager : THelpManager;
function RegisterViewer(newViewer: ICustomHelpViewer;
out Manager: IHelpManager): Integer;
begin
if not Assigned(HelpManager) then
HelpManager := THelpManager.Create;
Manager := HelpManager.RegisterViewer(newViewer);
Result := 0;
end;
function GetHelpSystem(out System ; IHelpSystem) : Integer;
begin
if not Assigned(HelpManager) then
HelpManager := THelpManager.Create;
System := HelpManager as IHelpSystem;
System._AddRef;
Result := 0;
end;
{ THelpViewerNode }
constructor THelpViewerNode.Create(Viewer: ICustomHelpViewer);
begin
FViewer := Viewer;
Viewer._AddRef;
end;
{ THelpManager }
constructor THelpManager.Create;
begin
inherited Create;
FViewerList := TObjectList.Create;
FExtendedViewerList := TObjectList.Create;
FSpecialWinHelpViewerList := TObjectList.Create;
FHelpFile := ";
FMinCookie := 1;
end;
function THelpManager.RegisterViewer(NewViewer: ICustomHelpViewer): IHelpManager;
var
ExtendedViewer: IExtendedHelpViewer;
SpecialViewer: ISpecialWinHelpViewer;
NewNode: THelpViewerNode;
begin
NewNode := THelpViewerNode.Create(NewViewer);
NewNode.ViewerID := FMinCookie;
FViewerList.Insert(FViewerList.Count, NewNode);
NewViewer.NotifyID(NewNode.ViewerID);
if Supports(NewViewer, IExtendedHelpViewer, ExtendedViewer) then
begin
NewNode := THelpViewerNode.Create(ExtendedViewer);
NewNode.ViewerID := FMinCookie;
FExtendedViewerList.Insert (FExtendedViewerList.Count, NewNode);
end;
if Supports(NewViewer, ISpeciquWinHelpViewer, SpecialViewer) then
begin
NewNode := THelpViewerNode.Create(SpecialViewer);
NewNode.ViewerID := FMinCookie;
FSpecialWinHelpViewerList.Insert(FSpecialWinHelpViewerList.Count, NewNode);
end;
FMinCookie := FMinCookie + 1;
Result := Self as IHelpManager;
end;
procedure THelpManager.UnloadAllViewers;
var
I: Integer;
begin
for I:=0 to FViewerList.Count-1 do
begin
THelpViewerNode(FViewerList[I]).Viewer.ShutDown;
end;
FViewerList.Clear;
FExtendedViewerList.Clear;
FSpecialWinHelpViewerList.Clear;
end;
procedure THelpManager.DoSoftShutDown;
var
I : Integer;
begin
for I:= 0 to FViewerList.Count-1 do
begin
THelpViewerNode(FViewerList[ I ]).Viewer.SoftShutDown;
end;
end;
procedure THelpManager.DoTableOfContents;
var
ViewerNames : TStringList;
I : Integer;
HelpNode : THelpViewerNode;
begin
if FViewerList.Count = 1 then
begin
if THelpViewerNode(FViewerList [ 0 ]).Viewer.CanShowTableOfContents then
THelpViewerNode(FViewerList[0]).Viewer.ShowTableOfContents;
end
else if FHelpSelector <>
nil then
begin
ViewerNames := TStringList.Create;
try
for I := 0 to FViewerList.Count -1 do
begin
HelpNode := THelpViewerNode (FViewerList [I] );
if HelpNode.Viewer.CanShowTableOfContents then
ViewerNames,AddObject(HelpNode.Viewer.GetViewerName, TObject(HelpNode));
end;
if ViewerNames.Count >
1 then
begin
ViewerNames.Sort;
I := FHelpSelector.TableOfContents(ViewerNames);
THelpViewerNode(ViewerNames.Objects[I]).Viewer.ShowTableOfContents; end
else begin
THelpViewerNode(ViewerNames.Objects[0]).Viewer.ShowTableOfContents; end; finally
ViewerNames.Free;
end;
end
else if (FViewerList.Count >
0) and
(THelpViewerNode(FViewerList[0]).Viewer.CanShowTableOfContents) then
begin
THelpViewerNode(FViewerList[0]).Viewer.ShowTableOfContents;
end
else raise EHelpSystemException.CreateRes(ShNoTableOfContents);
end;
function THelpManager.CallSpecialWinHelp(Handle: LongInt;
const HelpFile: String;
Command: Word; Data: LongInt): Boolean;
var
View : ICustomHelpViewer;
begin
Result := false;
if FSpecialWinHelpViewerList.Count >
0 then
begin
if FSpecialWinHelpViewerList.Count = 1 then
begin
View := THelpViewerNode(FSpecialWinHelpViewerList[0]).Viewer;
Result := (View as ISpecialWinHelpViewer).CallWinHelp(Handle, HelpFile, Command, Data);
end else
begin
View := THelpViewerNode(FSpecialWinHelpViewerList[0]).Viewer;
Result := (View as ISpecialWinHelpViewer).CallWinHelp(Handle, HelpFile, Command, Data);
end;
end;
end;
{ THelpManager - IHelpSystem }
procedure THelpManager.ShowHelp(const HelpKeyword, HelpFileName :
String);
var
I, J: Integer;
AvailableHelp: Integer;
HelpfulViewerCount : Integer;
ViewerIndex: Integer;
AvailableHelpList: TStringList;
ViewerHelpList: TStringList;
HelpNode : THelpViewerNode;
KeywordIndex : Integer;
Obj: TObject;
ObjString: String;
begin
ViewerIndex := 0;
HelpfulViewerCount := 0;
if HelpFileName <>
'' then
HelpFile := HelpFileName;
if FViewerList.Count >
0 then
begin
for I := 0 to (FViewerList.Count - 1) do
begin
AvailableHelp := THelpViewer-
Node (FViewerList [I] ).Viewer.UnderstandsKeyword(HelpKeyword);
if AvailableHelp >
0 then
begin
ViewerIndex := I;
HelpfulViewerCount := HelpfulViewerCount + 1;
end;
end;
if HelpfulViewerCount = 0 then
raise EHelpSystemException.CreateResFmt(@hNothingFound,
[PChar(HelpKeyword)]);
if HelpfulViewerCount = 1 then
begin
THelpViewerNode (FViewerList [ViewerIndex]) . Viewer. ShowHelp (HelpKeyword) ;
end;
if HelpfulViewerCount >
1 then
begin
AvailableHelpList := TStringList.Create( );
for I := 0 to FViewerList.Count -1 do
begin
HelpNode := THelpViewerNode(FViewerList [ I ]) ;
AvailableHelp := HelpNode.Viewer.UnderstandsKeyword(HelpKeyword);
if AvailableHelp >
0 then
begin
ViewerHelpList := HelpNode.Viewer.GetHelpStrings(HelpKeyword);
for J ;= 0 to ViewerHelpList.Count - 1 do
begin
AvailableHelpList.AddObject(ViewerHelpList.Strings[J], TOb-
ject(HelpNode));
end;
ViewerHelpList.Free;
end;
end;
if FHelpSelector <>
nil then
begin
AvailableHelpList.Sort;
KeywordIndex := FHelpSelector.SelectKeyword(AvailableHelpList);
if Keywordlndex >
= 0 then
begin
Obj := AvailableHelpList.Objects[KeywordIndex] ;
ObjString := AvailableHelpList.Strings[KeywordIndex];
THelpViewerNode(Obj).Viewer.ShowHelp(ObjString);
end;
end
else begin
Obj := AvailableHelpList.Objects[0];
ObjString := AvailableHelpList.Strings[0];
THelpViewerNode(Obj).Viewer.ShowHelp(ObjString);
end;
AvailableHelpList.Free;
end;
end;
end;
procedure THelpManager.ShowContextHelp(const ContextID: Longint; const
HeIpFileName: String);
var
I : Integer;
View: ICustomHelpViewer;
begin
if FExtendedViewerList.Count = 0 then
raise EHelpSysteroException.CreateRes(@hNoContext)
else begin
for I := 0 to FExtendedViewerList.Count -1 do
begin
View := THelpViewerNode(FExtendedViewerList[ I ]).Viewer;
if (View as IExtendedHelpViewer).UnderstandsContext(ContextID, HelpFile-
Name) then
begin
(View as IExtendedHelpViewer).DisplayHelpByContext(ContextID, HelpFile-
Name) ;
break;
end;
end;
end;
end;
procedure THelpManager.ShowTableOfContents;
begin
DoTableOfContents;
end;
procedure THelpManager.ShowTopicHelp(const Topic, HelpFileName: String);
var
I: Integer;
View: ICustomHelpViewer;
begin
if FExtendedViewerList.Count = 0 then
raise EHelpSystemException.CreateRes(@hNoTopics)
else begin
for I := 0 to FExtendedViewerList.Count - 1 do
begin
View := THelpViewerNode(FExtendedViewerList[ I ]).Viewer;
if (View as IExtendedHelpViewer).UnderstandsTopic(Topic) then
begin
(View as IExtendedHelpViewer).DisplayTopic(Topic);
break;
end;
end;
end;
end;
procedure THelpManager.AssignHelpSelector(Selector: IHelpSelector);
begin
if FHelpSelector <>
nil then FHelpSelector := nil;
FHelpSelector := Selector;
Selector._AddRef;
end;
function THelpManager.Hook(Handle: Longint; HelpFile; String;
Command: Word; Data: Longint): Boolean;
begin
case Command of
HELP_CONTEXT:
begin
ShowContextHelp(Data, HelpFile);
end;
HELP_CONTEXTPOPUP:
begin
ShowCoritextHelp (Data, HelpFile) ;
end;
HELP_QUIT:
begin
DoSoftShutDown;
end;
HELP_CONTENTS:
begin
FHelpFile := HelpFile;
DoTableOfContents;
end;
else
CallSpecialWinHelp(Handle, HelpFile, Command, Data);
end;
Result := true;
end;
{ THelpManager —— IHelpManager }
function THelpManager.GetHandle: LongInt;
begin
Result := Handle;
end;
function THelpManager.GetHelpFile: String;
begin
Result := HelpFile;
end;
procedure THelpManager.Release(const ViewerID: Integer);
var
I : Integer;
begin
for I := 0 to FViewerList.Count-1 do
begin
if THelpViewerNode(FViewerList[ I ]).ViewerID = ViewerID then
FViewerList.Delete( I );
end;
for I := 0 to FExtendedViewerList.Count-1 do
begin
if THelpViewerNode(FExtendedViewerList [ I ]).ViewerID = ViewerID then
FExtendedViewerList.Delete( I );
end;
for I := 0 to FSpecialWinHelpViewerList.Count-1 do
begin
if THelpViewerNode(FSpecialWinHelpViewerList[I]).ViewerID = ViewerID then
FSpecialWinHelpViewerList.Delete( I );
end;
end;
destructor THelpManager.Destroy;
begin
if FHelpSelector <>
nil then FHelpSelector := nil;
inherited Destroy;
end;
initialization
finalization
if HelpManager <>
nil then
begin
HelpManager.UnloadAllViewers;
end;
end.
Вперед
П2 1 Модуль WinHelpViewer pas
Листинг П2.1.Модуль WinHelpViewer.pasunit WinHelpViewer;
{********************************************************************* }
{ }
{ Этот модуль обеспечивает поддержку просмотрщика помощи WinHelp (под
{ Windows) или HyperHelp (эмулятор WinHelp) под Linux.}
{ }
{********************************************************************* }
interface
uses Classes;
type
IWinHelpTester - interface(IInterface)
['{B0FC9354-5F0E-11D3-A3B9-00C04F79AD3A}']
function CanShowALink(const ALink, FileName: String): Boolean;
function CanShowTopic(const Topic, FileName: String): Boolean;
function CanShowContext (const Context; Integer;
const FileName: String): Boolean;
function GetHelpStrings(const ALink: String): TStringList;
function GetHelpPath : String;
function GetDefaultHelpFile: String;
end;
var
WinHelpTester : IWinHelpTester;
ViewerName : String;
{$IFDEF LINUX}
HyperHelpWindowName : String;
{$ENDIF}
{====================================================================}
{$IFDEF MSWINDOWS}
uses HelpIntfs, SysUtils, Windows;
{$ENDIF}
{$IFDEF LINUX}
uses HelpIntfs, SysUtils, Libc;
{$ENDIF}
{$IFDEF LINUX}
const
winhelpmodulename = 'winhelp.so';
function WinHelp(HWND: LongInt; HelpFile: PChar; Conmand: LongInt;
Data: LongWord): Boolean; cdecl;
external winhelpmodulename name 'WinHelp';
{$ENDIF}
type
TWinHelpViewer = class(TInterfacedObject, ICustomHelpViewer, IExtended-
HelpViewer, ISpecialWinHelpViewer)
private
FViewerID: Integer;
public
FHelpManager: IHelpManager;
constructor Create;
function HelpFile(const Name: String) : String;
procedure InternalShutDown;
{ ICustoroHelpViewer }
function GetViewerName : String;
function UnderstandsKeyword(const HelpString: String): Integer;
function GetHelpStrings(const HelpString: String): TStringList;
function CanShowTableOfContents: Boolean;
procedure ShowTableOfContents;
procedure ShowHelp(const HelpString: String);
procedure NotifуID(const ViewerID: Integer);
procedure SoftShutDown;
procedure ShutDown;
{ IExtendedHelpViewer }
function UnderstandsTopic(const Topic: String): Boolean;
procedure DisplayTopic(const Topic: String);
function UnderstandsContext(const ContextID: Integer;
const HelpFileName: String): Boolean;
procedure DisplayHelpByContext(const ContextID: Integer;
const HelpFileName: String);
{ ISpecialWinHelpViewer }
function CallWinHelp(Handle: LongInt;
const HelpFileName: String;
Command: Word; Data: LongInt) : Boolean;
property ViewerID : Integer read FViewerID;
property HelpManager : IHelpManager read FHelpManager write FHelpManager;
destructor Destroy; override;
end;
var
HelpViewer : TWinHelpViewer;
{----------------------------------------------------------------------}
{ TWinHelpVIewer }
constructor TWinHelpViewer.Create;
begin
inherited Create;
end;
function TWinHelpViewer.HelpFile(const Name: String): String;
var
FileName : String;
begin
Result := ";
if (Name = '') and Assigned(FHelpManager) then
FileName := HelpManager. GetHelpFile
else FileName := Name;
if FileName = '' then if Assigned(WinHelpTester) then
FileName := WinHelpTester.GetDefaultHelpFile;
{$IFDEF LINUX}
if Assigned(WinHelpTester) then
FileName := WinHelpTester.GetHelpPath + PathDelim + FileName;
{$ENDIF}
Result := FileName; end; procedure TWinHelpViewer.InternalShutDown;
begin
SoftShutDown;
if Assigned(FHelpManager) then
begin
HelpManager.Release(ViewerID);
if Assigned(FHelpManager) then HelpManager := nil;
end;
end;
{----------------------------------------------------------------------}
{ TWinHelpViewer - ICustomHelpViewer }
function TWinHelpViewer.GetViewerNaroe : String;
begin
Result := ViewerName;
end;
function TWinHelpViewer.UnderstandsKeyword(const HelpString: String):
Integer;
var
CanShowHelp : Boolean;
begin
if Assigned(WinHelpTester) then
begin
CanShowHelp := WinHelpTester.CanShowALink(HelpString, HelpFile( ''));
if CanShowHelp then Result := 1
else Result := 0;
end
else begin
{$IFDEF WINDOWS}
Result := 1;
{$ENDIF}
{$IFDEF LINUX}
Result := 0;
{$ENDIF}
end;
end;
function TWinHelpViewer.GetHelpStrings(const HelpString: String): TStringList;
begin
if Assigned(WinHelpTester} then
begin
Result := WinHelpTester.GetHelpStrings (HelpString);
end else
begin
Result := TStringList.Create;
{$IFDEF MSWINDOWS}
Result.Add(GetViewerName +':'+ HelpString);
{$ENDIF}
end;
end;
function TWinHelpViewer.CanShowTableOfContents : Boolean;
begin
Result := true;
end;
procedure TWinHelpViewer.ShowTableOfContents;
begin
WinHelp(HelpManager.GetHandle, PChar(HelpFile(HelpManager.GetHelpFile)),
HELP_CONTENTS, 0);
end;
{$IFDEF MSWINDOWS}
procedure TWinHelpViewer.ShowHelp(const HelpString: String);
const
Macro - 'IE(AL("%s",4),"AL(\"%0:s\",3)","JK(\"%l:s\",\"%0:s\")")';
begin
WinHelp(HelpManager.GetHandle, PChar(HelpFile(" )),/ HELP_COMMAND,
LongInt (PChar (Format (Macro, [HelpString, HelpFile (")]))));
end;
{$ENDIF}
{$IFDEF LINUX}
procedure.TWinHelpViewer.ShowHelp(const HelpString: String);
const
Macro= 'AL(%0s,3,,%ls)';
begin
WinHfelp(HelpManager.GetHandle, PChar(HelpFile(")), HELP_COMMAND,
LongInt(Pchar(Format(Macro, [HelpString, HyperHelpWindowName]))));
end;
{$ENDIF}
procedure TWinHelpViewer.NotifylD(const ViewerID: Integer);
begin
FViewerID := ViewerID;
end;
procedure TWinHelpViewer.SoftShutDown;
begin
WinHelp(0, PChar( " ), HELP_QUIT, 0);
end;
procedure TWinHelpViewer.ShutDown;
begin
SoftShutDown;
if Assigned(FHelpManager) then HelpManager := nil;
if Assigned(WinHelpTester) then WinHelpTester := nil;
end;
{-----------------------------------------------------------------------}
{ TWinHelpViewer —— IExtendedHelpViewer }
function TWinHelpViewer.UnderstandsTopic(const Topic: String): Boolean;
begin
{$IFDEF MSWINDOWS}
Result := true;
{$EMDIF}
{$IFDEF LINUX}
Result := false;
{$ENDIF}
if Assigned(WinHelpTester) then
Result := WinHelpTester.CanShowTopic(Topic, HelpFile(''));
end;
procedure TWinHelpViewer.DisplayTopic(const Topic: String);
var
HelpCommand; array[0..255] of Char;
begin
StrLFmt (HelpCommand, SizeOf (HelpCommand) -1, ' JtmpIDC'", "%s") ', [Topic]);
WinHelp(HelpManager.GetHandle, PChar(HelpFile( " )), HELP_COMMAND,
Longint(@HelpCommand));
end;
function TWinHelpViewer.UnderstandsContext(const ContextID: Integer;
const HelpFileName: String) : Boolean;
begin
{$IFDEF MSWINDOWS}
Result := true;
{$ENDIF}
{$IFDEF LINUX}
Result := false;
{$ENDIF}
if Assigned(WinHelpTester) then
Result := WinHelpTester.CanShowContext(ContextID, Help-
File (HelpFileName));
end;
procedure TWinHelpViewer.DisplayHelpfeyContext(const ContextID: Integer;
const HelpFileName: String);
begin
WinHelp(HelpManager.GetHandle, PChar(HelpFile(HelpFileName)),
HELP_CONTEXT, ContextID);
end;
{------------------------------------------------------------------------}
{ TWinHelpViewer —— ISpecialWinHelpViewer }
function TWinHelpViewer.CallWinHelp(Handle: LongInt; const HelpFileName: String;
Command: Word; Data: LongInt) : Boolean;
begin
Result := WinHelp(Handle, PChar(HelpFile(HelpFileName)), Command, Data);
end;
destructor TWinHelpViewer.Destroy;
begin
inherited Destroy;
end;
{============================================================================}
initialization
HelpViewer := TWinHelpViewer.Create;
Helplntfs.RegisterViewer(HelpViewer, HelpViewer.FHelpManager);
WinHelpTester := nil;
finalization
if Assigned(HelpViewer.FHelpManager) then
begin
HelpViewer.InternalShutDown;
end;
if Assigned(WinHelpTester) then
begin
WinHelpTester := nil;
end;
end.
П2 2 Модуль ManViewer pas
Листинг П2.2.Модуль ManViewer.pasunit ManViewer;
{*********************************************************************}
{ }
{ Этот модуль поддерживает просмотрщик страниц man в среде Linux. }
{ Он не был опробован на различных unix-системах и формах Linux, }
{ за исключением RedHat. }
{ }
{ *******************************************************************}
interface
{ = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = }
implementation
uses HelpIntfs, Classes, SysUtils, LibC;
type
TManPageViewer = class(TInterfacedObject, ICustomHelpViewer)
private
FHelpStrings : TStringList;
FLastQuery : String;
FViewerID : Integer;
ChildPid : Integer;
procedure ProcessHelpStrings(StringBuf: PChar; HelpString: String);
procedure KillChild;
public
FHelpManager : IHelpManager;
constructor Create;
procedure InternalShutDown;
{ ICustomHelpViewer }
function GetViewerName : String;
function UnderstandsKeyword(const HelpString: String): Integer;
function GetHelpStrings(const HelpString: String): TStringList;
function CanShowTableOfContents : Boolean;
procedure ShowHelp(const HelpString: String);
procedure ShowTableOfContents;
procedure NotifyID(const ViewerID: Integer);
procedure SoftShutDown;
procedure ShutDown;
property HelpManager : IHelpManager read FHelpManager write FHelpManager;
property ViewerID : Integer read FViewerID;
destructor Destroy; override;
end;
var
HelpViewer : TManPageViewer;
const
{ man and its switches }
ExeName = 'man';
AllSwitch = '-a'; { отображает все man-страницы раздела }
WhereSwitch = '-w'; { где располагается man-страница? }
ViewerName = 'xterm';
MoreBugSwitch = '-cu';
ExecSwitch = '-e';
TitleSwitch = '-Т'; {установка заголовка окна }
ViewerTitle = 'Kylix man page viewer';
{ сигнал, используемой для завершения дочерних процессов }
KillSignal = SIGINT;
sFatalFork = 'Unable to fork(). Please consult the disaster manual.';
sNoTableOfContents = 'Unable to provide table of contents for man pages.';
{----------------------------------------------------------------------}
{ TManPageViewer }
constructor TManPageViewer.Create;
begin
inherited Create;
end;
procedure TManPageViewer.ProcessHelpStrings(StringBuf: PChar;
HelpString: String);
var
bufptr, lineptr, valptr, delim: PChar;
searching: boolean;
addstr : String;
begin
bufptr := StringBuf;
searching := true;
while searching do
begin
delim := #10#13;
lineptr := strsep(@bufptr, delim);
if (lineptr = nil) then
begin
searching := false;
end else
begin
delim := '.';
strsep(@lineptr, delim);
valptr := strsep(@lineptr, delim);
if valptr <>
nil then
begin
addstr := HelpString + ' (' + valptr + ') (' + GetViewerName + ')';
FHelpStrings.Add(addstr) ;
end;
end;
end;
end;
procedure TManPageViewer.KillChild;
begin
if ChildPid <>
0 then
begin
kill (ChildPid, KillSignal) ;
waitpid(ChildPid, nil, WNOHANG or WUNTRACED);
ChildPid := 0;
end;
end;
procedure TManPageViewer. IntemalShutDown;
begin
KillChild;
if Assigned(FHelpManager) then FHelpManager.Release(ViewerID);
ShutDown;
end;
{---------------------------------------------------------------------}
{ TManPageViewer —— ICustomHelpViewer }
function TManPageViewer.GetViewerName;
begin
Result := ExeName;
end;
function TManPageViewer.UnderstandsKeyword(const HelpString: String):
Integer;
var
SuccDescr, ErrDescr : TPipeDescriptors;
pid: Integer;
Args : array of PChar;
DescriptorSet : TFDSet;
WaitTime : TTiraeVal;
WaitStatus: Integer;
PipeStream : THandleStream;
ReadBuf : Pointer;
BytesRead: Integer;
Reading : Boolean;
begin
Result := 0;
if FHelpStrings <>
nil then FHelpStrings := nil;
SetLength(Args, 5);
Args[0] := ExeName ;
Args[ l ] := AllSwitch;
Args[2] := WhereSwitch;
Args[3] := PChar(HelpString);
Args[4] := nil;
pipe(SuccDescr) ;
pipe(ErrDescr) ;
pid := fork;
if pid = 0 then
begin
_close(SuccDescr.ReadDes);
_close(ErrDescr.ReadDes) ;
dup2(SuccDescr.WriteDes, stdout);
dup2(ErrDescr.WriteDes, stderr);
execvp (PChar(Args[0]), @Args[0]);
end
else begin
if pid = -1 then
begin
raise EHelpSystemException.Create(sFatalFork);
end else
begin
WaitStatus := waitpid(pid, nil, WUNTRACED);
if WaitStatus >
0 then
begin
WaitTime.tv_sec := 0;
WaitTime.tv_usec := 0;
FD_ZERO(DescriptorSet);
FD_SET(TSocket(SuccDescr.ReadDes), DescriptorSet);
FD_SET(TSocket(ErrDescr.ReadDes), DescriptorSet);
select(__FD_SETSIZE, @DescriptorSet, nil, nil, @WaitTime);
if FD_ISSET(TSocket(SuccDescr.ReadDes), DescriptorSet) then
begin
if FHelpStrings = nil then FHelpStrings := TStringList.Create;
PipeStream := THandleStream.Create(SuccDescr.ReadDes);
ReadBuf := Libc.malloc(1024);
memset(ReadBuf, 0, 1024);
Reading := true;
while Reading do
begin
BytesRead := PipeStream.Read(ReadBuf^, 1024);
if (BytesRead < 1024) then Reading := false;
ProcessHelpStrings(ReadBuf, HelpString);
memset(ReadBuf, 0, 1024);
end;
Libc.free(ReadBuf);
PipeStream.Free;
Result := FHelpStrings.Count;
FLastQuery := HelpString;
end else
begin
end;
end else
begin
if FHelpStrings = nil then FHelpStrings := TStringList.Create;
end;
end;
end;
_close(SuccDescr.WriteDes);
_close(ErrDescr.WriteDes);
_close(SuccDescr.ReadDes);
_close(ErrDescr.ReadDes);
end;
function TManPageViewer.GetHelpStrings(const HelpString: String): TStringList;
begin
Result := FHelpStrings;
end;
function TManPageViewer.CanShowTableOfContents:Boolean;
begin
Result := false;
end;
procedure TManPageViewer. ShowTableOfContents ;
begin
raise EHelpSystemException.Create(sNoTableOfContents);
end;
procedure TManPageViewer.ShowHelp(const HelpString: String);
var
KeywordEnd, Section, CompResult, CompString, Comparator: PChar;
Args : array of PChar;
pid : Integer;
begin
KillChild;
SetLength (Args, 9) ;
Args[0] = ViewerName;
Args[1 ] = MoreBugSwitch;
Args[2] = TitleSwitch;
Args[3] = ViewerTitle;
Args[4] = ExecSwitch;
Args[5] = ExeName;
Args[6] = AllSwitgh;
Args[7] = PChar(HelpString);
Args[8] = nil;
CompString := PChar(HelpString);
Comparator := Libc.malloc(2);
Comparator[0] := '(';
Comparator[1] := #0;
CompResult := strstr(CompString, Comparator);
Libc.free(Comparator);
if (CompResult <>
nil) then
begin
Section := Libc.malloc(2) ;
KeywordEnd := AnsiStrPos(PChar(HelpString), '(');
Section[0] := KeywordEnd[1];
Section [1] :=" #0;
Args[6] := Section;
{ #DEFINE DUMB_НАСК_ВУ_ТIRED_РROGRAMMER }
Args[7] := PChar(FLastQuery);
end
else begin
Section := nil;
end;
pid := fork;
if pid = 0 then
begin
execvp(PChar(Args[0]), @Args[0]);
end
else begin
if pid = -1 then
begin
raise EHelpSystemExceptiorv.Create (sFatalFork);
end
else begin
ChildPid := pid;
end;
end;
if Section о nil then Libc.free(Section);
end;
procedure TManPageViewer.NotifyID(const ViewerID: Integer);
begin
FViewerID := ViewerID;
end;
procedure TManPageViewer.SoftShutDown;
begin
KillChild;
end;
procedure TManPageViewer.ShutDown;
begin
KillChild;
if Assigned(FHelpManager) then FHelpManager := nil;
end;
destructor TManPageViewer.Destroy;
begin
inherited Destroy;
end;
{====================================================================}
initialization
if not Assigned(HelpViewer) then
begin
HelpViewer :=TManPageViewer.Create;
HelpIntfs.RegisterViewer(HelpViewer, HelpViewer.FHelpManager);
end;
finalization
if Assigned(HelpViewer) then
begin
HelpViewer.InternalShutDown;
end;
end.
Назад Вперед
Листинги модулей для создания системы
для создания системыЛистинги всех трех файлов приводятся
Листинги всех трех файлов приводятся в конце книги, в Приложении 2.Методы
МетодыМетоды — это процедуры или функции, принадлежащие объекту. Методы определяют поведение объекта. Для вызова метода объекта нужно указать имя объекта, с которым ассоциирован данный метод, затем, через точку, — название метода. Например:
MyObject.Method1;
Вызывается метод Method1 объекта MyObject.
Для создания метода его нужно сначала объявить внутри описания класса или компонента, содержащего данный метод. Например:
type
TMyObject = class(TObject)
. . . procedure DoSomething; // Объявление метода DoSomething
. . . end;
Здесь, внутри описания нового класса, объявляем метод DoSomething с помощью служебного слова procedure. Эта процедура может находиться где угодно внутри модуля, в котором был описан данный класс. Например:
procedure TMyComponent.DoSomething; begin
// Здесь размещаем команды и операторы, которые должны выполняться
// при вызове метода DoSomething на выполнение end;
Заметим, что при создании процедуры DoSomething мы должны указывать ее полное имя, вместе с указанием имени компонента или класса (procedure TMyComponent.DoSomething;).
В зависимости от вида метода, он может вызываться различными способами. Методы бывают следующих видов:
По умолчанию методы являются статическими и вызываются как любые другие подпрограммы.
Более подробно о методах мы расскажем в пятой части книги, где речь пойдет о создании собственных компонентов и пакетов компонентов.
Назад Вперед
Модуль данных
Рисунок 18.10. Модуль данныхМодули
МодулиКроме рассмотренных выше программ и подпрограмм, язык Object Pascal позволяет создавать так называемые модули.
Модуль (unit) — предназначен для записи в него различных элементов, таких как подпрограммы, переменные, константы и др.
Модуль не может быть запущен на исполнение как программа. Чтобы использовать модуль в программе, его необходимо подключить. Для этого имя модуля указывается в разделе uses основной программы.
Наиболее успешные сделки совершаются в направлении тренда
Наиболее успешные сделки совершаются в направлении тренда
Преимущество торговли по тренду состоит в том, что это то направление, в котором торгуют трейдеры крупного масштаба, а импульс, вызванный новыми деньгами, приходящими на рынок, вероятно, продолжит двигать цены в направлении тренда, пока не появятся серьезные причины для разворота. Причины могут быть фундаментальными событиями или просто взятием прибыли. Ниже приводятся несколько способов определить направление тренда.
Написание переносимого кода
Написание переносимого кодаДля создания кроссплатформенного приложения следуйте приведенным ниже советам:
Непереносимые возможности
Непереносимые возможностиПри создании объекта CLX с помощью палитры компонентов или написания кода, использующего метод Create, компилятор создает экземпляр widget. Этот экземпляр принадлежит данному объекту CLX. Если вы вызываете метод Free для уничтожения объекта CLX или автоматически уничтожаете родительский контейнер, содержащий объект CLX, экземпляр widget данного объекта будет также уничтожен. Эта функция характерна для VCL в приложениях Windows.
Если вы создаете объект GLX с помощью метода Create (AHandle), то этот объект не будет иметь в собственности Qt widget. Таким образом, при вызове метода Free будет уничтожен только объект GLX. В VCL Windows это невозможно.
Назад Вперед
Объекты и классы
Объекты и классыВ этой главе мы кратко рассмотрим основы объектно-ориентированного программирования. Изучим такие понятия, как инкапсуляция, наследование и полиморфизм. Рассмотрим классы, поля, свойства, события, методы объектов. В заключение мы узнаем, что такое типы времени выполнения (RTTI).
Основы объектно-ориентированного программирования
Язык Object Pascal является объектно-ориентированным языком. Таким образом, готовое приложение, написанное на данном языке, будет иметь в своем составе объекты.
Итак, рассмотрим, что такое класс. Класс — это тип данных, который включает в себя какие-либо данные и операции над ними.
Объект — это экземпляр какого-либо класса.
Таким образом, класс — это описание (тип), а объект — это то, что создано в соответствии с этим описанием. Например, все вы хорошо представляете, что такое стол. Стол — это нечто, имеющее столешницу и четыре ножки. Такое вот описание стола и будет классом, а конкретный экземпляр стола, за которым вы сейчас сидите, читая эту книгу, является объектом данного класса.
До создания объектно-ориентированных языков программирования данные и операции над данными рассматривали как отдельные элементы. Что такое объект, достаточно просто можно понять, если вспомнить работу с записями. Записи состоят из областей, которые содержат данные разных типов (каждая область записи имеет собственный тип данных).
Объекты — это тоже хранилища разных типов данных. Данные объекта называются полем (field) и аналогичны полям записи. Но объекты, в отличие от записей, содержат еще процедуры и функции, которые применимы к полям данного объекта. Эти процедуры и функции называются методами (methods). Изменять поля объекта можно при помощи свойств (properties) объекта. Каждое свойство объекта в Kylix представляет собой поле и методы (так называемые методы доступа), которые позволяют считывать значение поля и задавать его. Свойства можно изменять в процессе разработки приложения с помощью инспектора объектов.
Примечание
Информацию о работе с инспектором объектов Kylix, а также другими окнами вы найдете во второй части этой книги.
К основным принципам объектно-ориентированного программирования относятся:
Наследование обозначает, что объекты могут получать свои свойства и методы от других объектов (которые называют в данном случае предками). Объекты-наследники берут от предков все свойства, методы и поля. Эти свойства, методы и поля в объекте-наследнике могут сохраняться либо в неизменном виде, либо в измененном. Кроме того, объекты-наследники могут иметь в своем составе дополнительно новые поля, методы или свойства.
Полиморфизм подразумевает, что методы различных объектов могут иметь одинаковые имена, но отличаться по своему содержанию. Это получается в результате переопределения метода объекта-предка в объекте-наследнике. При этом обращение к одному и тому же методу у объекта-предка и объекта-потомка может привести к разным результатам.
Вперед
Области видимости объектов (компонентов)
Области видимости объектов (компонентов)Область видимости объекта (компонента) — это часть программного кода, в пределах которой существует прямой доступ к свойствам, событиям и методам объекта (компонента) без явного указания его имени.
Таким образом, когда вы пишите код, находящийся в области видимости объекта (компонента), можно не указывать его имя для доступа к его свойствам, событиям и методам.
В качестве примера приведем часть программы (см. листинг 7.1), которая показывает действие области видимости объекта (в данном примере формы Form1).
Обновление экрана
Обновление экранаВо время работы приложения многие объекты на экране изменяют свое состояние. Может измениться текст или графика, содержащаяся внутри объекта. Для того чтобы эти изменения отображались на экране, необходимо обновление объектов.
Обновление (refresh) объектов — это процесс, выполняемый операционной системой для перерисовки окон и компонентов, расположенных внутри окон.
Для самостоятельного вызова метода обновления компонента вы можете использовать метод Refresh, который имеется у всех компонентов CLX, поддерживающих обновление.
При обновлении объекта генерируется событие OnPaint. Вы можете написать собственный обработчик события OnPaint. Приведем пример перехвата события обновления формы. Будем выводить окно c текстовым сообщением всякий раз, когда произойдет обновление формы. Создадим новое приложение — File/New Application. Теперь разместим на форме Form1 кнопку Button1 (Рисунок 13.1).
Обозначения окна проводника
Рисунок 6.9. Обозначения окна проводникаДля перехода из окна проводника в окно просмотра и редактирования кода и наоборот можно использовать комбинацию клавиш
Для добавления (переименования) объекта в окне проводника достаточно щелкнуть правой кнопкой мыши в соответствующем узле окна проводника и выбрать в контекстном меню New (Rename).
Окно проводника также можно настроить с помощью окна настройки среды (Environment Options) (Рисунок 6.10). Оно вызывается с помощью пункта меню главного окна Kylix Tools/Environment Options (Средства/Настройки среды).
Обработка исключительных ситуаций
Обработка исключительных ситуацийЧтобы сделать свое приложение устойчивым к ошибкам, вам необходимо распознать исключение и обработать его. Если вы не напишете обработчик исключения, приложение отобразит окно сообщения об ошибке.
Обработчик исключения — это программа, которая начинает свое выполнение в случае возникновения определенной исключительной ситуации. Обработник исключения выполняется вместо стандартной реакции приложения на ошибку.
При обработке исключительных ситуаций Kylix работает с так называемыми объектами исключений. Так как Kylix — объектно-ориентированная среда программирования, то логично, что и исключительная ситуация — тоже объект. Для работы с этим объектом в Kylix присутствуют специальные языковые конструкции, которые мы и рассмотрим далее.
Программисту чаще всего известно, в каком именно месте программы может возникнуть исключительная ситуация (например, место, где происходит открытие файла, расположенного на диске). Для того чтобы обработать ее, нужно этот кусок кода защитить. Таким образом, данный блок кода будет называться защищенным.
Рассмотрим языковые конструкции, предоставляемые средой Kylix, которые обеспечивают защищенный код.
Первая конструкция имеет вид, представленный в листинге 9.1.
Общий обзор языка
Общий обзор языкаВ этой главе мы расскажем о языке Object Pascal. Для начала, небольшой исторический экскурс в историю языка Pascal.
Исторически первый, недоступный широкой аудитории технический отчет языка Pascal был сделан Швейцарским федеральным технологическим институтом ЕТН (Eidgenoessische Technische Hochschule) в ноябре 1970 года. Официальной же датой рождения языка считается начало 1971 года, когда вышеупомянутый отчет был перепечатан в первом номере журнала Acta In-formatica. Автором языка является швейцарский профессор Никлаус Вирт (Niklaus К. Wirth).
Во время активного использования языка наблюдалось острая конкуренция с языком С. Большую роль в массовом распространении языка Pascal сыграла компания Borland, создавшая версию Тurbo Раsсаl. После этого уже стали появляться многочисленные модификации: в версии 3.0 появилась возможность работы со встроенной графикой, в версии 4.0 — модули, в версии 5.5 — возможность работы с объектами. Версия 7.0 поменяла название и стала называться Borland Pascal. Наконец, при появлении Delphi язык стал называться Object Pascal. Среда Kylix также использует язык Object Pascal.
Вперед
Общий обзор потоков
Общий обзор потоковПоток (Thread) — это объект операционной системы, заключенный в процесс и реализующий какую-либо задачу. Любое приложение (процесс) содержит несколько потоков (как минимум, один, который называется основным, стандартным. В большинстве приложений вы можете использовать объект потока, который позволяет вам использовать потоки в ваших приложениях. Объекты потоков инкапсулируют в себе основные свойства и методы, необходимые для написания многопоточных приложений.
Итак, любой поток — это объект, получающий определенное процессорное время. Всякое приложение Linux является процессом операционной системы.
Примечание
Объекты потоков не позволяют вам управлять атрибутами безопасности или размером стека ваших потоков. Для того чтобы контролировать их, вам необходимо использовать функцию BegmThread, которая рассматривается далее.
Для того чтобы использовать объекты потоков в вашем приложении, вам нужно создать потомок класса TThread.
Класс TThread был создан для облегчения написания приложений с несколькими потоками. Он гарантирует совместимость при работе с библиотекой визуальных компонентов (CLX) Kylix.
Вообще, при создании многопоточных приложений необходимо следовать приведенным ниже рекомендациям:
Окно Environment Options
Рисунок 6.10. Окно Environment Options
Окно настройки
Рисунок 6.2. Окно настройкиВ окне настройки имеются три вкладки: Toolbars, Commands и Options.
Вкладка Toolbars (см. Рисунок 6.2) позволяет показывать или скрывать вкладки панели инструментов.
На вкладке Commands (Рисунок 6.3) располагаются категории команд и сами команды, которые можно выбирать, щелкнув на их названии и на необходимой панели инструментов. В результате вышеописанных действий на выбранной панели инструментов появится новая кнопка. Для удаления ненужной кнопки с панели инструментов достаточно щелкнуть на кнопке мышью и, удерживая ее, переместить на любое место экрана вне панелей инструментов.
Вкладка Commands — это очень удобное средство добавления практически любых команд на панель инструментов для быстрого доступа.
Наконец, вкладка Options (Рисунок 6.4) позволяет работать со всплывающими подсказками (tips) панелей инструментов. Если вы обратили внимание, когда вы подводите курсор к любому объекту панелей инструментов, появляются надписи, объясняющие назначение этого объекта.
Окно New Items
Рисунок 18.1. Окно New Items
Окно появляющееся при обработке события OnKeyDown
Рисунок 8.21. Окно, появляющееся при обработке события OnKeyDownПримечание
С помощью данного события невозможно обработать нажатие функциональных клавиш и клавиш
Параметры X и Y содержат координаты указателя мыши в области компонента.
Примечание
При нажатой левой кнопке мыши данное событие не возникает. Эта особенность почему-то не документирована.
Данное событие имеет следующие параметры: Shift, X и Y, аналогичные вышеописанным.
Canvas.Draw (0, 0, BitMap );
Окно сообщения об исключении
Рисунок 9.2. Окно сообщения об исключенииПримечание
С объектами исключений нужно работать очень осторожно. Ни в коем случае самостоятельно не уничтожайте объекты исключения — это может привести к ошибке работы программы. После завершения обработки исключения Kylix самостоятельно позаботится об его уничтожении.
Рассмотрим теперь классы исключений. Они необходимы для обработки конкретных исключительных ситуаций. Мы представляем классы исключений не в иерархии, а в алфавитном порядке.
Intercept.
Окно сообщения
Рисунок 9.1. Окно сообщенияПримечание
Знание имен классов исключений необходимо при обработке исключительных ситуаций. Мы рассмотрим их далее в этой главе.
В листинге 9.4 приведен пример использования временного имени объекта исключения в своих целях.
Окно свойств редактора
Рисунок 6.8. Окно свойств редактораС помощью окна свойств редактора можно настроить практически все параметры отображения текстов программ в окне просмотра и редактирования кода, а также проверки синтаксиса.
Окно проводника служит для упрощения навигации между модулями проекта. Окно проводника можно закрыть, щелкнув левой кнопкой мыши в верхнем правом углу данного окна. С помощью пункта главного меню Kylix View/Code Explorer (Просмотр/Окно проводника) можно снова активизировать это окно.
Окно проводника содержит в себе дерево диаграмм, которые отображают все типы, классы, свойства, методы, глобальные переменные и глобальные программы, определенные в модуле. Оно отображает также другие модули, перечисленные в модуле после слова uses.
В окне проводника для обозначения всего вышеперечисленного используются следующие значки (Рисунок 6.9):
Событие OnExit является противоположным по
Рисунок 8.19. Окно, выдаваемое при неудачном перетаскивании строки из ListBox1 в ListBox2
выдаваемое при успешном перетаскивании
Рисунок 8.18. Окно, выдаваемое при успешном перетаскивании строки из ListBox1 в ListBox2
Операторы манипулирования данными
Операторы манипулирования даннымиГлавным оператором манипулирования данными является оператор SELECT. Этот оператор используется для отбора данных, соответствующих сложным условиям. Оператор SELECT имеет вид:
SELECT [ DISTINCT ]
<Список полей> или *
FROM <Список таблиц>
[ WHERE <Условия выбора записей>]
[ORDER BY <Список полей для сортировки>]
[GROUP BY <Список полей для группировки>]
[HAVING <Условия группировки полей>]
[UNION <Вложенный оператор SELECT>]
Результатом выполнения данного оператора будет набор записей, удовлетворяющих заданным условиям.
Параметр DISTINCT определяет, будут ли включаться в результирующий набор данных повторяющиеся записи. Если он присутствует в операторе SELECT, то повторяющиеся записи будут исключены из набора данных.
Если в список полей входят поля нескольких таблиц, для указания принадлежности поля к той или иной таблице используют составной оператор, включающий имя таблицы и, через точку, имя поля:
<Имя таблицы>.<Имя поля>
Операнд WHERE определяет критерии, которым должны удовлетворять записи в результирующем наборе данных.
Операнд GROUP BY позволяет группировать записи. Иногда бывает необходимо выполнить какие-либо операции над группой записей.
Операнд HAVING используется вместе с GROUP BY и позволяет выбирать записи внутри групп.
Операнд ORDER BY содержит список полей, определяющих порядок сортировки записей результирующего набора данных. По умолчанию сортировка выполняется в порядке возрастания значений. Для сортировки в порядке убывания значений необходимо после имени поля поставить параметр DESC.
Операнд UNION используется для организации вложенных операторов SELECT. Вложенные операторы SELECT называют иногда подзапросами.
Приведем примеры выбора записей с использованием оператора SELECT.
Пример 17.1. Выбор всех полей таблицы
SELECT * FROM MyTable
В результате выполнения этого запроса будут выбраны все поля и записи из таблицы MyTable. Значок * обозначает, что выбраны все поля таблицы. Вместо него можно просто перечислить через запятую все поля таблицы.
Пример 17.2. Выбор данных из трех полей таблицы
SELECY Number, Surname, Telefon FROM MyTable
В результате выполнения примера 17.2 будут выбраны все записи из полей Number, Surname и Telefon таблицы MyTable.
Пример 17.3.Выборуникальных значений
SELECT DISTINCT Surname FROM MyTable
В результате мы получим набор данных, который содержит все фамилии (Surname), входящие в таблицу MyTable. В этот набор данных не будет дважды включена одна и та же фамилия, т. е. будут исключены все однофамильцы.
Пример 17.4.Выбор данных из двух таблиц
SELECT * FROM MyTable1, MyTable2
Выбирает все данные из таблиц МуTable1 и MyTable2. Первыми будут располагаться поля таблицы MyTable1, а затем — поля второй таблицы.
Пример 17.5.Выбор записей по значениям числового поля
SELECT Name, Surname FROM МуТаble WHERE (Number>l) and (Number<100);
Результирующим набором данных будут имена и фамилии первых ста человек, занесенных в таблицу МуTable.
Пример 17.6. Выбор записей по значению символьного поля
SELECT Name
FROM MyTable WHERE Surname='Иванов' ;
Результатом будет набор имен, фамилии которых Иванов.
Пример 17.7.Проверка частичного совпадения по символьному полю
SELECT Name, Surname FROM MyTable WHERE Surname LIKE 'И';
Будут выбраны имена и фамилии людей, занесенных в таблицу МyTable, фамилии которых начинаются на букву И.
В выражениях операции LIKE можно использовать шаблоны. Символы шаблонов:
SELECT Name, Surname FROM MyTable WHERE Surname LIKE '%' || 'OB' || '%';
Будут выбраны имена и фамилии людей, в состав фамилий которых входят символы ов.
Операнд ORDER BY служит для упорядочения (сортировки) значений полей.
Пример 17.9. Сортировка записей по полю
SELECT * FROM MyTable ORDER BY Name
Таким образом, набор данных будет отсортирован в порядке возрастания по полю Name.
Пример 17.10. Сортировка по двум полям
SELECT * FROM MyTable
ORDER BY Name, Surname DESC
Будет произведена сортировка данных сначала по полю Name в порядке возрастания, затем — по полю Surname в порядке убывания.
Оператор UPDATE служит для изменения значений полей в группе записей и имеет следующий формат:
UPDATE <Имя таблицы>
SET <Имя поля> = <Выражение>,
. . . SET <Имя поля> = <Выражение> [WHERE <Условия выбора>];
Во всех записях, которые удовлетворяют условию отбора, будут изменяться значения полей.
Пример 17.11. Изменение значений поля
UPDATE MyTable
SET Oklad = Oklad + 1000; WHERE Oklad < 1000;
Изменит сумму оклада (Oklad) сотрудника, если оклад менее 1000 руб. К сумме оклада прибавится еще 1000 руб.
Оператор INSERT служит для вставки записей в таблицу и имеет следующий формат:
INSERT INTO <Имя таблицы> (<Список полей>) VALUES (<Список значений>);
Таким образом, к таблице <Имя таблицы> будет добавлена одна запись.
Пример 17.12. Добавление записи в таблицу
INSERT INTO MyTable
(Name, Surname, Telefon) VALUES ('Иван', 'Иванов', 2341234);
В таблицу MyTable будет добавлена новая запись, содержащая имя и фамилию нового сотрудника, а также номер его телефона.
Оператор DELETE служит для удаления записей из таблицы и имеет следующий формат:
DELETE* FROM <Имя таблицы> [WHERE <Условия выбора>];
Из таблицы будут удалены все записи, которые удовлетворяют условию выбора.
Пример 17.13.Удаление записей из таблицы
DELETE FROM MyTable
WHERE Surname = 'Иванов';
Удаляет из таблицы МуТаble все записи, содержащие фамилию Иванов.
На этом мы заканчиваем обзор основных операторов и функций языка SQL. Дополнительную информацию вы можете почерпнуть из специальной литературы, посвященной данному языку.
Назад
Операторы определения данных
Операторы определения данныхДавайте рассмотрим более подробно операторы определения данных.
Оператор CREATE TABLE служит для создания новой таблицы базы данных и имеет следующий формат:
CREATE TABLE <Имя таблицы> (<Имя поля> <Тип данных>,
...
<Имя поля> <Тип данных>);
В этом операторе обязательно указание хотя бы одного имени поля и его типа данных.
Приведем пример создания простой таблицы:
CREATE TABLE MyTable (Number INTEGER, Name CHAR(20), Surname CHAR(20));
При этом в каталоге текущей базы данных создастся новая таблица MyTable, состоящая из полей Number, Name и Surname. Первое поле имеет целочисленный тип (INTEGER), остальные поля — символьного типа и ограничены длиной в 20 символов.
Если при выполнении этого запроса выяснится, что таблица с таким именем уже существует, будет сгенерирована исключительная ситуация.
Оператор DROP TABLE <Имя таблицы> служит для удаления имеющейся таблицы. Если таблицы с таким именем не существует, будет сгенерирована исключительная ситуация:
DROP TABLE MyTable;
При выполнении этой операции будут удалены все файлы, относящиеся к таблице MyTable.
Оператор ALTER TABLE предназначен для добавления или удаления полей существующей таблицы базы данных. Во время действия этого оператора никакие другие приложения не должны обращаться к таблице. Этот оператор имеет следующий формат:
ALTER TABLE <Имя таблицы>
ADD <Имя поля> <Тип данных>, DROP <Имя поля>,
...
ADD <Имя поля> <Тип данных>, DROP <Имя поля>;
При этом операнд ADD добавляет к таблице новое поле, а оператор DROP удаляет из таблицы существующее поле. Операнды могут располагаться внутри оператора ALTER TABLE произвольно:
ALTER TABLE MyTable
ADD Telefon INTEGER, ADD Address CHAR (50), DROP Number;
При выполнении данного примера в таблицу МуTable добавятся два поля: Telefon и Address, целочисленного и символьного типа соответственно. Кроме того, будет удалено поле Number.
Назад Вперед
Операторы
ОператорыОператор — это законченное предложение языка Object Pascal, которое выполняет какое-либо действие. Операторы могут быть:
Структурированные операторы — операторы, которые влияют на ход выполнения программы. К таким операторам относятся операторы ветвления, цикла и некоторые другие.
Все операторы должны разделяться символом "точка с запятой". Если между операторами присутствует несколько точек с запятой, это не является ошибкой. Такие операторы (пустоты между двумя точками с запятой) называют пустыми операторами:
А:=5 ; ; ; / / один оператор присваивания и два пустых оператора
Заметим, что лишние точки с запятой недопустимы в описательной части программы. Их наличие может привести к ошибке компиляции.
Операторы языка Object Pascal мы подробно рассмотрим в главе 3 книги.
Назад Вперед
Основы баз данных
Основы баз данныхВ этой главе мы рассмотрим основные определения и термины, использующиеся при разработке баз данных. Изучим основные архитектуры приложений баз данных, которые поддерживает Kylix. Кроме того, мы рассмотрим средства для работы с базами данных, предоставляемые средой программирования.
Основные понятия
База данных — это хранилище для большого количества определенных данных, с которыми можно производить некоторые действия (добавление, удаление, изменение, копирование, упорядочивание и т. д.).
Для обеспечения вышеописанных действий с данными необходимы специальные программы.
Приложения баз данных — это программы, которые позволяют пользователям работать с данными, хранящимися в базах данных.
Отметим, что все базы данных условно делятся на три основных типа.
Основы языка SQL
Основы языка SQLВ этой главе мы рассмотрим команды языка структурированных запросов SQL (Structured Query Language). Вы узнаете, что такое запрос и как с ним работать.
Основные сведения о языке SQL
Язык SQL существует в нескольких стандартах. Наиболее поддерживаемыми и распространенными являются стандарты SQL-89 и SQL-92. Последний стандарт также называют стандартом ANSI. Из-за наличия множества стандартов языка существует множество его диалектов. Мы рассмотрим только основные команды SQL для простых операций с таблицами баз данных.
В языке SQL нет многих типов команд, которые присущи большинству языков программирования. Так, в нем нет операторов цикла, перехода и т. д.
SQL-запрос — это команда на языке SQL.
Язык SQL по своей сути ориентирован на доступ к данным, и его обычно включают в состав различных средств разработки. Среда Kylix не осталась в стороне. Более того, все ее компоненты для работы с базами данных поддерживают язык SQL.
Все SQL-запросы можно условно разделить на два вида:
Операторы определения данных — предназначены для создания, удаления и изменения структуры данных. Основные из них перечислены в табл. 17.1.
Отличия CLX от VCL
Отличия CLX от VCLХотя многое в CLX и VCL выполнено одинаково, они имеют некоторые отличия. Рассмотрим их.
Пакеты компонентов
Пакеты компонентовПакеты — это специальные динамически присоединяемые компоненты (аналоги файлов so — разделяемых объектов, Shared Objects). По своему использованию пакеты делятся на:
Так же, как и остальные динамические библиотеки, пакеты содержат код, который может быть использован одновременно несколькими приложениями. Например, самым часто используемым пакетом Kylix является bplclx. Когда вы создаете Практически любое приложение в Kylix, вы используете данный пакет. Сама среда Kylix также использует данный пакет. При этом достаточно, чтобы в памяти компьютера находилась всего одна копия данного пакета для скольких угодно приложений, использующих bplclx. Ту же копию пакета будет использовать и сама среда Kylix.
Вы можете строить ваши приложения с помощью пакетов или без них. Но если вы хотите использовать в своем приложении самостоятельно созданные компоненты, вам придется установить пакет, применяемый во время разработки приложения и содержащий данные компоненты.
В этой главе мы рассмотрим, для чего предназначены пакеты, как они применяются в приложениях и как можно их динамически загружать. Кроме того, рассмотрим процедуру инсталляции пакетов компонентов, научимся создавать новые пакеты и редактировать уже имеющиеся и изучим общую структуру пакета.
Вперед
Палитра компонентов Kylix
Палитра компонентов KylixВ этой главе мы изучим стандартные компоненты, поставляемые вместе с Kylix и последовательно рассмотрим вкладки палитры компонентов Kylix и компоненты, расположенные на них, а также свойства, события и методы стандартных компонентов Kylix. На небольших примерах покажем способы их применения в программах.
Описание основных компонентов Kylix
Итак, как уже было сказано ранее, Kylix поставляется со стандартным набором компонентов, доступ к которым осуществляется при помощи палитры компонентов. Рассмотрим вкладки палитры компонентов.
Вкладка Standard (Рисунок 8.1).
Параметры и аргументы
Параметры и аргументыПараметры — это элементы подпрограммы, которые используются при описании блока подпрограммы.
Аргументы — это элементы, которые указываются при вызове подпрограмм. Они замещаются соответствующими параметрами подпрограммы.
В качестве параметров могут выступать:
Все параметры разделяются на группы, в зависимости от того, чем они являются:
function Max(A: array of Real; N: Integer): Real;
Здесь массив А и переменная N являются параметрами-значениями. Параметры-значения рассматриваются компилятором как локальные переменные, которые присутствуют только внутри подпрограммы. Все изменения этих параметров происходят только внутри подпрограммы и никак не влияют на значения соответствующих им аргументов.
Параметры-константы — это параметры, перед которыми в заголовке подпрограммы стоит слово const. За параметрами-константами через двоеточие ставится их тип. Например:
procedure MyProc1(const X: Integer);
Здесь единственный параметр х является параметром-константой. Значение параметра-константы в теле подпрограммы изменить нельзя. Параметры-константы применяются для того, чтобы запретить нежелательные изменения параметров в подпрограмме. Кроме того, использование параметров-констант позволяет компилятору создать более эффективный код.
Параметры-переменные — это параметры, перед которыми в заголовке подпрограммы стоит слово var. За параметрами-переменными через двоеточие ставится их тип. Например:
procedure MyProc2(var a,b:char; c,d:string);
В этом примере параметры а и b являются параметрами-переменными.
Параметры-переменные используются, когда необходимо передать значение из подпрограммы в основную программу. При этом все изменения параметра внутри подпрограммы приводят к аналогичным изменениям соответствующего аргумента.
Указание типов параметров обязательно лишь для параметров-значений. Для других видов параметров тип можно не указывать. В таком случае параметры считаются нетипизированными. Например:
function MyFunc(var a,b; const c,d): Integer;
В данном примере параметры а, b, с и d являются нетипизированными. При вызове такой подпрограммы программист может использовать в качестве аргументов элементы любого типа.
Назад Вперед
Перечисляемое свойство MyEnumProp в новом компоненте TMyButton
Рисунок 19.3. Перечисляемое свойство MyEnumProp в новом компоненте TMyButtonСоздание свойств-множеств в компоненте
Тип множества часто использовался в Object Pascal, и некоторые свойства компонентов Kylix имеют данный тип. Когда вы используете свойство типа множество, вы должны учитывать, что каждый элемент множества будет являться отдельным свойством, имеющим логический тип в инспекторе объектов.
Для создания свойства-множества сначала зададим нужный тип:
TMySetTypeFirst = (poFirst, poSecond, poThird);
TMySetType = set of TMySetTypeFirst;
Первая строка задает перечисляемый тип TMySetTypeFirst, который определяет диапазон множества. Вторая строка задает само множество TMySetType.
Пример добавления свойства-множества в компонент TMyButton приведен в листинге 19.4.
Перенос кода ассемблера в Linux
Перенос кода ассемблера в LinuxЕсли ваше Windows-приложение содержит код на языке ассемблера, вы, скорее всего, не сможете использовать этот же самый код в Linux, т. к. среда Linux требует независимый от позиции код (position-independent code, PIC).
Для использования кода ассемблера в платформо-независимом приложении вы можете использовать директиву компилятора {$IFDEF PIC}. Кроме того, вы можете пожертвовать скоростью выполнения и переписать процедуру, написанную на ассемблере, на языке Object Pascal.
Назад Вперед
Перенос Windowsприложений в cреду Linux
Перенос Windows-приложений в cреду LinuxСложность переноса приложений из одной среды в другую зависит от сложности самого приложения. Если в приложении используются специфичные вызовы функций ядра одной из операционных систем, то перенос значительно затрудняется. Если же вы в своем приложении используете стандартные компоненты CLX, проблемы будут возникать значительно реже.
Итак, для переноса приложения из одной операционной системы в другую вы можете использовать три метода.
Перечислим семь главных шагов, которые нужно выполнить для переноса приложения из Windows в Linux:
1. Перенесите все исходные файлы вашего Windows-приложения на компьютер с установленной средой Linux. Исходные файлы должны включать файлы модулей (pas), файл проекта (dpr) и файлы используемых пакетов (dpk). Кроме того, необходимо перенести файлы, связанные с файлом проекта: файлы форм (dfm), файлы ресурсов (res) и файлы опций проекта (dof). Если вы хотите откомпилировать файл только из командной строки, вам необходим файл конфигурации (cfg).
2. Если вы планируете использование совместных ресурсов для приложений Windows и Linux, переименуйте dfm файлы в файлы xfm, сохранив их названия (например, переименуйте unit1.dfm в unit1.xfm). Переименуйте ссылки на .dfm файлы в модулях приложения из {$R .dfm} в {$R .xfm}.
Примечаниe
Файлы dfm работают в среде Kylix, но после изменения могут и не работать в Delphi.
3. Смените все разделы uses с указанием правильных названий модулей Kylix (см. далее в этой главе).
4. Перепишите код, использующий специфические для Windows процедуры, чтобы сделать приложение более независимым от операционной системы. Сделайте это с помощью встроенных библиотек Kylix.
5. Найдите эквиваленты для команд, которые не поддерживаются в Linux. Используйте директиву компилятора $IFDEF (умеренно) для разграничения кода под Linux и Windows.
Например, вы можете для вашего межплатформенного приложения воспользоваться следующим кодом (листинг 21.1):
Переносимые приложения баз данных
Переносимые приложения баз данныхВ Windows среда Delphi обеспечивает программисту три пути для доступа к информации, содержащейся в базах данных;
Прежде чем перенести приложения баз данных из Windows в Linux, вы должны понять отличия Между использованием dbExpress и механизмом доступа к данным, который вы применяли в Windows. Эти отличия существуют на нескольких уровнях.
На самом низком уровне имеется механизм, обеспечивающий связь между вашим приложением и сервером баз данных. Это может быть клиентская часть программного обеспечения ADO, BDE или InterBase. Этот слой достаточно легко заменяется dbExpress, который содержит драйверы для работы с запросами SQL.
На низком уровне вы устанавливаете на форме компоненты, которые будут использоваться для работы с наборами данных. Эти компоненты включают компонент соединения с базой данных, который обеспечивает подключение к серверу базы данных, и компонент набора данных, который представляет собой выборку данных из таблиц базы данных. Несмотря на то, что имеются некоторые достаточно важные отличия, они являются наименее заметными на данном уровне.
На уровне интерфейса пользователя также имеются некоторые отличия. Компоненты CLX, предназначенные для отображения данных, разработаны таким образом, чтобы по возможности быть наиболее похожими на соответствующие компоненты Windows.
Рассмотрим эти отличия более подробно.
Отличия в dbExpress
В Linux dbExpress управляет соединением с сервером базы данных. dbExpress состоит из набора небольших драйверов, которые поддерживают набор наиболее используемых интерфейсов. Каждый драйвер является файлом библиотеки разделяемых объектов (so), который может быть присоединен к вашему приложению. Так как dbExpress был разработан как межплатформенный набор
драйверов, он доступен в среде Windows как набор динамически присоединяемых библиотек (dll).
Как и любой другой слой доступa к данным, dbExpress требует наличия клиентского программного обеспечения, которое поставляется разработчиком базы данных. dbExpress использует специфичный для базы данных драйвер и два конфигурационных файла: dbxconnections и dbxdrivers. Это значительно меньше, чем вам необходимо в BDE, который требует главную библиотеку Borland Database Engine (Idapi32.dll) плюс специфичный драйвер для базы данных и несколько других файлов-библиотек для поддержки базы данных.
Ниже перечислены основные отличия между dbExpress и другими слоями доступа к данным:
Когда вы создаете приложение, использующее dbExpress, необходимо применять различные наборы компонентов доступа к данным.
В табл. 21.7 приведен список наиболее важных компонентов для работы с базами данных, которые применяются в InterBase Express, BDE и ADO в среде Windows, и показано их соответствие компонентам dbExpress для использования в среде Linux и кроссплатформенньк приложениях.
Пиктограмма Data Module окна New Items
Рисунок 18.2. Пиктограмма Data Module окна New Items
Подпрограммы и модули
Подпрограммы и модулиВ этой главе мы расскажем о принципах описания функций и процедур языка Object Pascal. Вы узнаете, чем отличается параметр подпрограммы от аргумента и научитесь сами создавать процедуры и функции. В конце главы мы рассмотрим понятие модуля.
Подпрограммы
Подпрограмма — это небольшая законченная программа, состоящая из операторов и команд языка и оформленная специальным образом.
Подпрограммы используются для сокращения объема программы и могут вызываться из любого места основной программы. Уменьшение объема программы достигается за счет того, что в программах часто имеются одинаковые участки кода, которые можно вынести в подпрограмму и вызывать ее в нужных местах программы.
По своей структуре подпрограмма аналогична обычной программе, но блок uses в подпрограмме отсутствует. Подпрограмма также имеет некоторые отличия в оформлении заголовка.
Прежде чем работать с подпрограммой, ее необходимо описать.
При описании и вызове подпрограммы записываются имя подпрограммы, список и значения параметров (аргументов), которые передаются данной подпрограмме для работы, а также действия, выполняемые этой подпрограммой.
В качестве параметров функции могут выступать любые описанные в ней переменные. Параметры используются для передачи данных из основной программы в подпрограмму. Однако подпрограмма может не иметь параметров.
В модулях Kylix имеется несколько десятков стандартных подпрограмм, которые могут вызываться без предварительного их описания.
Все подпрограммы в языке Object Pascal делятся на две группы:
Для досрочного выхода из подпрограммы и передачи управления основной программы достаточно вызвать процедуру Exit. Подпрограммы допускается вызывать из других подпрограмм.
Вперед
Поля ID и Name
Рисунок 18.7. Поля ID и NameПравой кнопкой мыши щелкнем на компоненте Clients и выберем в выпадающем меню пункт CreateDataSet, а затем — пункт Save To MyBase Xml UTF-8 table. В появившемся диалоговом окне укажем имя xml-файла, который будет хранить данные о клиентах — Clients.xml и являться главной таблицей нашей базы данных (Рисунок 18,8).
Для того чтобы при запуске программы клиентский набор данных Clients читал данные из созданного нами xml-файла, значение его свойства FileName должно быть равно полному имени xml-файла.
Поля компонента Clients
Рисунок 18.9. Поля компонента ClientsРазместим в модуле данных компонент DataSource, установим его свойство Name в ds_Clients и свяжем его с компонентом Clients (свойство DataSet компонента ds_Clients установим равным Сlients). Затем установим свойство DataSource в ds__Clients. Окончательный вид модуля данных показан на Рисунок 18.10.
Посмотрим, как устроен внутри файл базы данных xml. После создания набора данных типичный файл базы данных выглядит, как представлено в листинге 18.1.
Поля
ПоляПоле объекта предназначено для хранения данных, содержащихся в объекте. Описание поля не отличается от описания обычной переменной и может быть любого типа. Приведем пример описания поля объекта:
type TNumber = class
FInt: Integer; end;
Данный пример создает в классе TNumber новое поле FInt целочисленного типа.
Примечание
По взаимному соглашению разработчиков, имена полей должны начинаться с буквы F (по-английски field означает поле).
Обратите внимание на то, что данный класс TNumber является прямым потомком класса TObject. Так как после слова class в круглых скобках не указывается класс-предок. Поэтому объявление типа в первой строке примера может быть таким:
type TNumber = class(TObject)
После создания нового класса он наследует все поля своего класса-предка. Удалить или переопределить поля класса-предка невозможно.
Назад Вперед
Помощи
помощиЗдесь представлены листинги модулей для создания системы помощи.
Понятие исключения
Понятие исключенияСреда Kylix предназначена для быстрой разработки довольно сложных программных комплексов. Сложная программа может по-разному взаимодействовать с операционной системой и уже запущенными в ней приложениями. Кроме того, пользователи вносят частичку непредсказуемости при работе с программой. В результате любое из вышеописанных взаимодействий может не выполниться или завершиться неправильно. Такие ситуации мы и будем рассматривать далее в этой главе. Ошибочных ситуаций, которые могут возникнуть, достаточно много. Простейшим примером может являться попытка программы выполнить деление на ноль или открытие несуществующего файла на диске. Все возможные ошибки программист предугадать не может. Для облегчения труда разработчика программ Kylix включает поддержку так называемых исключений или исключительных ситуаций.
Исключительная ситуация — это непредвиденное событие, произошедшее при выполнении программы и способное повлиять на ее дальнейшее выполнение.
Kylix предоставляет программисту механизм обработки исключительных ситуаций. Обработчик исключений позволяет приложению корректно обработать возникшую исключительную ситуацию (ошибку) и продолжить выполнение программы без потери данных и ресурсов. Для создания таких безопасных программ нужно лишь научиться писать обработчики исключительных ситуаций.
Далее мы рассмотрим задачи, которые можно решать с помощью исключений.
Назад Вперед
Построение компонентов
Построение компонентовТеперь дополним модуль — заготовку нового компонента всем необходимым: свойствами, событиями и методами. Создадим работоспособный компонент и зарегистрируем его в среде Kylix. Затем рассмотрим, как можно модифицировать уже существующие компоненты визуальной библиотеки компонентов Kylix.
Создание свойств компонента
Добавление новых свойств в компонент осуществляется очень просто. Достаточно задать поля и свойства, определив при этом их тип и доступ (чтение, запись). Пример простого задания свойств в новый компонент представлен в листинге 19.2.
Применение свойства Align
Рисунок 8.12. Применение свойства AlignВ случае, когда существует привязка к противоположным сторонам родительского компонента, при изменении его размеров будет происходить сжатие или растяжение дочернего компонента вплоть до полного исчезновения его изображения. Таким образом, данное свойство определяет как бы фиксацию расстояния от компонента до краев родительского компонента.
property BoundsRect: TRect;
Примечание
Настоящие координаты можно получить из следующих свойств компонента: Left (левый край компонента), Tор (верхний край), Width (ширина компонента) и Height (высота). Описание этих свойств приводится ниже.
R := Control.BoundsRect;
эквивалентна записи
R.Top := Control.Top;
R.Left := Control.Left;
R.Right :- Control.Left + Control.Width;
R.Bottom := Control.Top + Control.Height;
Началом координат считается левый верхний угол окна, содержащего данный компонент.
property Caption: TCaption;
property ClientHeight: Integer;
Оно применяется при изменении размеров компонента, которые содержат в себе другие компоненты. При таком изменении будет происходить изменение компонентов, содержащихся в компоненте-контейнере.
property ClientOrigin: TPoint;
property ClientRect: TRect;
ClientWidth и ClientHeight (они описаны ниже):
Rect (0, 0, ClientWidth, ClientHeight)
property ClientWidth: Integer;
Пример иллюстрирующий работу событий OnEnter и OnExit
Рисунок 8.20. Пример, иллюстрирующий работу событий OnEnter и OnExitЗапустим приложение. Фокус при запуске будет передан компоненту, который был размещен на форме первым (в нашем случае это кнопка Button1).
Если теперь выбрать щелчком мыши любой переключатель группы переключателей, то произойдет следующее:
Пример применения событий OnDragDrop и OnDragOver
Рисунок 8.17. Пример применения событий OnDragDrop и OnDragOverПримеры создания приложений баз данных
Примеры создания приложений баз данныхВ Kylix нет стандартных компонентов для создания многих локальных баз данных. Связано это с тем, что такие форматы данных являются отмирающими, тем более что преобразование их в формат XML не вызывает больших затруднений.
Базы данных типа MyBase предоставляют программисту дополнительные возможности.
Начнем с создания заготовки приложения. В главном меню Kylix выберем пункт File/New Application (Рисунок 18.1).
При этом среда создаст проект с пустой формой Form1. Добавим модуль данных. Для этого выберем в главном меню Kylix пункт File/New и в открывшемся диалоговом окне выберем пиктограмму Data Module (Рисунок 18.2).
Теперь в модуль данных поместим компонент ClientDataSet с вкладки DataAccess. Установим свойство Name данного компонента в компонент Clients. Этот набор данных будет хранить информацию о заказчиках (Рисунок 18.3).
Для создания файла базы данных необходимо указать поля и их типы. Сделать это можно двумя способами:
Проблемы переноса приложений
Проблемы переноса приложенийKylix предоставляет возможность разработки так называемых кроссплат-форменных (межплатформенных) 32-разрядных приложений, которые могут работать как в среде Linux, так и в Windows, Для этого вы можете выбрать один из двух вариантов:
Примечание
Большинство приложений, разработанных для работы в среде Linux (если не используются специфичные для Linux вызовы API), могут после перекомпиляции работать под Windows.
Процедуры
ПроцедурыПроцедура — это обыкновенная подпрограмма, которая не возвращает никакого значения под своим именем.
Описание процедуры также состоит из двух частей: заголовка и блока. Заголовок процедуры имеет следующий вид:
Procedure имя процедуры (параметры);
Имя процедуры должно быть уникальным и должно однозначно идентифицировать процедуру.
Параметры процедуры являются необязательными и служат для передачи каких-либо данных из основной программы в процедуру.
Блок процедуры содержит операторы и команды языка Object Pascal. Блок процедуры может быть пустым.
Вызов процедуры происходит по ее имени и списку аргументов, заключенных в круглые скобки.
Рассмотрим пример описания процедуры. Создадим процедуру, которая преобразует целое число в строку (листинг 4.2). Для этого в процедуру потребуется передавать два параметра — целое число и строку, в которую будет записан результат.
Процессы и потоки
Процессы и потокиВ этой главе мы рассмотрим проблему одновременного выполнения нескольких задач внутри одного приложения. Вы научитесь использовать объекты потоков и координировать их работу.
Первое определение, которое мы рассмотрим, — это многопоточность. Многопоточность используется для:
Примечание
Linux — это многопоточная операционная система с поддержкой архитектуры Intel MP. Процессы в Linux представляют собой отдельные задачи. Каждый процесс запускается в собственном виртуальном адресном пространстве и не способен взаимодействовать с другими процессами Исключение составляют лишь процессы, обеспечивающие механизмы защиты Linux, и процессы ядра операционной системы.
Простые операторы
Простые операторыДля выполнения каких-либо действий в программе на языке Object Pascal применяются операторы. Операторы — это команды компилятору языка на выполнение определенных действий. Как мы уже отмечали ранее, все операторы делятся на простые и структурированные.
Напомним, что простые операторы не влияют на ход выполнения программы, т. е. сохраняют линейность выполнения команд программы.
Кроме рассмотренных ранее арифметических логических и строковых операторов, к числу простых операторов относятся:
Данный оператор является наиболее часто используемым в программах на языке Object Pascal. Оператор присваивания записывается с помощью знака :=. Данный оператор применяется для присваивания значения, записанного справа от знака присваивания переменной, которая записана слева от знака присваивания:
А:=10; // Переменной А присваивается значение 10
Если справа от знака присваивания стоит не конкретное значение, а выражение, оно будет вычислено и присвоено переменной слева от знака присваивания:
А:=12*754+123; // В переменную А будет помещен конечный // результат вычисления Переменная и выражение справа должны быть одного и того же или совместимого типа. Слева от оператора присваивания допустимо помещать не только переменную, Но и элементы массивов, поля записей и другие объекты.
Пустой оператор
Пустой оператор мы уже рассматривали ранее. Он представляет собой точку с запятой и может быть расположен в любом месте программы, где допускается наличие операторов. Данный оператор не выполняет никаких действий, но бывает иногда необходим.
Составной оператор
Составной оператор — это группа операторов, которые заключены между операторными скобками begin и end и отделены друг от друга точкой с запятой.
Таким образом, составной оператор представляет собой следующую конструкцию:
begin
operator1; operator2;
. . . ; operatorn; end; Такой оператор рассматривается как единое целое и может располагаться в любом месте программы, где допустимо наличие операторов.
Составные операторы могут быть вложены друг в друга. Например,
begin // Начало внешнего составного оператора operator1; begin // Начало внутреннего составного оператора
operator2_1;
operator2_2;
. . . ;
operator2_k;
end; // Конец внутреннего оператора
. . . ; operatorn; end; // Конец внешнего оператора
Количество вложений операторов друг в друга языком Object Pascal не ограничивается.
Оператор доступа
Оператор доступа предназначен для быстрого и удобного доступа к составным частям отдельных объектов. Например, удобно использовать оператор доступа при работе с полями записи. Если вы помните, для доступа к отдельному полю записи необходимо сначала указать имя этой записи и через точку — имя поля. Если нужно проделать несколько операций с разными полями записи, то оператор доступа использовать очень удобно.
Оператор доступа представлен следующим образом:
with объект do действие
Чтобы быстрее понять работу этого оператора, обратимся к листингу 3.3.
Простые типы данных
Простые типы данныхРабота с буфером обмена
Работа с буфером обменаВы можете использовать системный буфер обмена для копирования и вставки графики внутрь вашего приложения, а также для переноса графики из вашего приложения в другие и из других приложений в ваше. Для этого используется специальный объект Kylix Сlipboard. Этот объект позволяет оперировать различным типом информации, включая графику и текст.
Прежде чем вы сможете воспользоваться данным объектом, необходимо добавить в блок uses модуля, в котором будет использоваться буфер обмена, имя модуля OClipbrd:
uses
SysUtils, Types, Classes, Variants, QGraphics, QControls, QForms, QDia-logs, QStdCtrls, OClipbrd;
Данный модуль позволит обращаться к объекту Clipboard.
Копирование графики в буфер обмена
Для копирования графической информации в буфер обмена нужно ассоциировать графический объект с объектом Clipboard. Это можно сделать с помощью метода Assign.
Код, приведенный в листинге 13.21, показывает, как можно скопировать графический образ, содержащийся в компоненте типа Timage, имеющем имя Image, в буфер обмена, выбрав пункт меню Edit/Copy формы Form1.
Работа с графикой
Работа с графикойРабота с мышью
Работа с мышьюВаше приложение может реагировать на действия пользователя, которые он выполняет с помощью мыши. В этой части главы мы расскажем, как можно обрабатывать события мыши.
Событие мыши происходит в тот момент, когда пользователь двигает мышью или нажимает кнопки мыши. CLX поддерживает три события мыши, которые перечислены в табл. 13.4.
Работа с сокетами
Работа с сокетамиВ этой главе мы рассмотрим некоторые сетевые возможности, предоставляемые средой Kylix на примере работы с сокетами.
Сокеты — это специальные компоненты, позволяющие вашему приложению соединяться с другими компьютерами, использующими сетевой протокол TCP/IP. Кроме того, сокеты дают возможность работать и с другими сетевыми протоколами, такими как XNS (Xerox Network System), DECnet и Novell IPX/SPX.
Используя сокеты, вы можете читать или посылать данные на другие компьютеры, не беспокоясь об установленном на компьютерах сетевом программном обеспечении. То есть сокеты предоставляют интерфейс между приложением-клиентом или приложением-сервером и сетевым программным обеспечением, установленным на данном компьютере.
Таким образом, сокеты позволяют создавать приложения как для клиентов, так и для серверов сети. Эти приложения могут предоставлять один из двух сервисов: Hypertext Transfer Protocol (HTTP) или File Transfer Protocol (FTP)
Перед написанием приложения клиента или сервера сети вы должны знать, какие услуги будет предоставлять ваше приложение, если это приложение-сервер, или какие услуги будет получать приложение-клиент. Если вы используете стандартные протоколы, такие как HTTP или FTP, то вопрос о предоставляемых услугах обычно не возникает.
Большинство стандартных услуг протоколов ассоциированы, по соглашению, с определенными номерами портов. Для получения конкретной услуги вы должны указать номер порта и цифровой код услуги. Если вы используете стандартные услуги, предоставляемые компонентом-сокетом TTCPClient, то он самостоятельно определит номер порта для нужной услуги. Если вы создаете собственные услуги, вы должны указать ассоциированный с ней номер порта в файле /etc/services. Данный файл представляет собой ASCII-файл, содержащий список сетевых услуг, включая их имя, номер порта и тип протокола передачи данных (листинг 11.1).
Различие сред Linux и Windows
Различие сред Linux и WindowsВ табл. 21.5 приводится список отличий сред Linux и Windows.
Регистрация компонента в среде Kylix
Регистрация компонента в среде KylixРегистрация компонента необходима для размещения компонента в палитре компонентов.
При использовании эксперта компонентов для создания нового компонента Kylix самостоятельно создает процедуру регистрации компонента в модуле-заготовке. Создателю компонента в данном случае ничего не нужно делать, кроме следующих шагов:
Если же вы создаете компонент без использования эксперта компонентов, вам придется самостоятельно дописывать процедуру регистрации компонента. В разделе interface модуля компонента нужно дописать строку:
procedure Register;
А в разделе implementation — добавить процедуру регистрации. Например:
procedure Register; begin RegisterComponent ('Samples', [TMyButton] ); end;
В результате, компонент с именем TMyButton будет размещен на вкладке Samples палитры компонентов (Рисунок 19.8).
Результат работы компонента TWeek
Рисунок 19.6. Результат работы компонента TWeekСоздание собственных редакторов свойств
Перед тем как создавать собственный редактор свойств компонента, рассмотрим сначала имеющиеся в Kylix редакторы свойств. Их достаточно легко видеть в окне инспектора объектов, когда вы пытаетесь изменить какое-либо свойство компонента. Например, когда вы изменяете свойство Color для какого-либо компонента, вы видите редактор свойства цвета. Важно заметить, что все свойства компонентов имеют свои редакторы, даже такие простейшие свойства, как Caption, Height, Enabled имеют свои редакторы свойств. Особенностью этих редакторов является то, что компоненты "не знают", какие редакторы вы используете для изменения их свойств. Это может навести на мысль использовать собственный редактор свойств вместо заданного. Например, можно написать редактор свойства Width, который будет ограничен каким-либо числом.
Редакторы свойств имеют свою иерархию. Рассмотрим ее.
Базовым классом в иерархии редакторов свойств является TPropertyEditor. Названия классов говорят сами за себя. Например, класс TColorProperty отвечает за свойство цвета компонента, класс TIntegerProperty связан с теми свойствами, которые имеют тип Integer, и т. д. В листинге 19.9 приведен код, определяющий базовый класс TPropertyEditor.
Результат выполнения метода Pie
Рисунок 8.15. Результат выполнения метода PieПримечание
Для рисования прямоугольника без рамки используйте метод FillRect. Для рисования прямоугольника со скругленными углами используйте метод RoundRect. Чтобы нарисовать незакрашенный прямоугольник, используйте метод FrameRect.
Form1.ScrollBy (-10, 0);
Form1.SelectFirst;
выберет первый находящийся в последовательности табуляции компонент для формы Form1.
Form1.SetChildOrder (Button1, 5);
Таким образом, кнопка Button1 будет расположена в последовательности дочерних элементов формы Form1 на шестом месте (нумерация начинается с нуля).
Memo1. SetFocus ;
Image1,Canvas.StretchDraw ( Rect (0,0,19,19), Image2.Picture.Bitmap) ;
Image1.Canvas.TextOut (10, 100, 'Мне нравится Kylix');
выведет строку 'Mне нравится Kylix' на канву компонента Image1, начиная с координаты (10, 100).
Поле (Field) компонента или класса - это данные, находящиеся в компоненте или классе. Можно представить поле в виде переменной, которая описывается внутри компонента или класса. Например:
type
TMyComponent = class private
FMyField1: char; FMyField2: real; FMyField3: string; FMyField4: boolean; end;
На приведенном выше примере, внутри описания компонента TmyComponent,описываются четыре поля FMyField1, FMyField2, FMyField3 и FMyField4, имеющие различный тип. Поля могут быть тех же типов, что и обычные переменные.
Примечание
При создании наследников компонента (класса) они будут наследовать все поля от своего класса предка. Например, на приведенном выше примере компонент TMyComponent будет содержать все поля своего предка — базового класса TObject , и дополнительные четыре поля, описанные выше. Заметим, что удалить или переопределить поля, перешедшие от класса-предка, невозможно, поэтому чем больше предков имеет компонент или класс, тем больше он имеет полей.
События
Любая программа, написанная в среде Kylix, постоянно обрабатывает какие-либо события. Событием может быть движение мышкой, нажатие клавиши на клавиатуре или на мышке, закрытие окна и т. д. Программисту остается лишь перехватывать эти события и писать методы, которые будут выполняться при генерации какого-либо события.
Событие (event) — это механизм, который связывает какое-либо системное происшествие с конкретным кодом, называемым обработчиком события (event handler).
Рассмотрим простой случай, когда происходит системное событие нажатия кнопкой мыши на форме. С точки зрения программиста, событие — это всего лишь имя, связанное с системным событием, в нашем случае — OnClick, которое связано с обработчиком события. Например, кнопка Button1 имеет метод OnClick. По умолчанию Kylix генерирует обработчик события — метод Button1Click, связанный с событием OnClick. Программист должен добавить код, который выполняется при нажатии на кнопку Button1 внутри метода Button1Click.
Итак, для наглядного представления процесса обработки рассмотрим про-стуш схему (Рисунок 8.16).
Диалоговое окно New Items
Рисунок 10.1. Диалоговое окно New Items
2. Щелкните на пиктограмме Application.
3. Нажмите кнопку ОК.
Для создания нового MDI-приложения выполните следующие шаги:
1. Выберите в главном меню Kylix пункт File/New для вызова диалогового окна New Items.
2. Выберите в диалоговом окне вкладку Projects и щелкните на пиктограмме MDI Application (Рисунок 10.2).
3 Нажмите кнопку ОК.
Вкладка Projects
Рисунок 10.2. Вкладка Projects
В MDI-приложении главная форма содержит несколько дочерних форм, которые могут размещаться внутри главной, но не могут выходить за ее пределы. Для определения, какая форма будет главной, а какая дочерней, установите свойство FormStyle каждой из форм в следующие значения:
Главная форма MDIприложения
Рисунок 10.3. Главная форма MDI-приложения
Более того, данная форма имеет необходимые компоненты для работы со многими дочерними окнами, а также главное меню для работы с файлами и окнами. Кроме того, меню содержит пункт Edit для работы с текстом. Таким образом, Kylix уже сделал для нас простейший многооконный текстовый редактор. Естественно, вы можете самостоятельно расширить его функциональность либо удалить ненужные компоненты.
Три расположенных рядом дочерних окна внутри главной формы
Рисунок 10.4. Три расположенных рядом дочерних окна внутри главной формы
Запустите эту форму и попробуйте создать новые дочерние окна с помощью пункта меню File/New или нажатия на соответствующую пиктограмму панели инструментов. Вы можете создать несколько файлов и располагать их каскадом, рядом и другими способами, с помощью нажатия на соответствующие пиктограммы панели инструментов (Рисунок 10.4).
Для поддержания всей этой функциональности Kylix создал специальный код, который размещен в модуле clxmain (листинг 10.6).
Пиктограмма Console Application
Рисунок 10.5. Пиктограмма Console Application
Kylix создаст файл проекта для консольного приложения и покажет окно редактора кода с текстом, приведенным в листинге 10.7.
Форма приложения
Рисунок 13.1. Форма приложения
Напишем в обработчике события OnPaint формы Form1 следующий код (листинг 13.1):
Формазаготовка для игровой программы
Рисунок 13.10. Форма-заготовка для игровой программы
Поле для игры
Рисунок 13.11. Поле для игры
Теперь два игрока могут последовательно щелкать левой кнопкой мыши в области сетки, в результате чего будут по очереди появляться красные нолики и синие крестики (Рисунок 13.12).
Программа в процессе работы
Рисунок 13.12. Программа в процессе работы
Итак, мы изучили основные графические возможности, которые предоставляет среда Kylix. Теперь вы можете создавать любые программы, использующие графику.
Назад
Информационное окно извещающее об обновлении формы
Рисунок 13.2. Информационное окно, извещающее об обновлении формы
Если вы используете компонент TImage для отображения графики на форме, вам не нужно будет заботиться об обновлении графического изображения, содержащегося в этом компоненте. Обновление будет произведено автоматически. Свойство Picture компонента TImage определяет текущий графический образ, рисунок или другую графику, которую отображает компонент.
Назад Вперед
Форма с диагональными линиями
Рисунок 13.3. Форма с диагональными линиями
Для рисования ломаных линий можно воспользоваться специальным методом Polyline.
Параметрами данного метода являются элементы массива Points. Приведем пример рисования ломаной линии:
Form1.Canvas.Polyline([Point(0, 0), Point(12,14), Point(50,30), Point (130, 120), Point(210,132)]);
Данный пример чертит ломаную линию, состоящую из прямых линий (Рисунок 13.4).
Ломаная линия
Рисунок 13.4. Ломаная линия
Рисование линий с помощью метода Polyline аналогично рисованию нескольких линий с помощью методов MoveTo и LinеТо. Ниже приведен пример (листинг 13.10), который строит такую же ломаную, как и предыдущий пример.
Эллипс вписанный в прямоугольник
Рисунок 13.5. Эллипс, вписанный в прямоугольник
Нижеприведенный пример (листинг 13.12) рисует прямоугольник со скругленными углами, которые скруглены по шаблону окружности, с диаметром 10 точек (Рисунок 13.6).
Прямоугольник со скругленными углами
Рисунок 13.6. Прямоугольник со скругленными углами
Для рисования многоугольников с любым количеством углов и сторон вы можете использовать метод Polygon.
Метод Polygon содержит в качестве параметров массив точек Points, которые определяют координаты вершин многоугольника. После рисований текущим пером линий многоугольника метод Polygon закрашивает текущим цветим кисти область внутри многоугольника.
Примечание
Данный метод аналогичен методу Polyline, только первая и последняя точки ломаной линии соединяются.
Назад Вперед
Обработка события OnMouseDown
Рисунок 13.7. Обработка события OnMouseDown
Еще один пример (листинг 13.26) устанавливает текущую позицию пера в координаты, в которых пользователь щелкнул мышью.
Пример рисования линий
Рисунок 13.8. Пример рисования линий
Обработка события OnMouseMove
Данное событие происходит периодически во время перемещения мыши. Для обработки этого события нужно написать программу-обработчик.
Нижеприведенный пример (листинг 13.28) показывает, как можно использовать событие OnMouseMove для немедленного рисования линий (Рисунок 13.9).
Обработка события OnMouseMove
Рисунок 13.9. Обработка события OnMouseMove
Назад Вперед
Добавление объекта потока в проект с помощью диалогового окна New Items
Рисунок 14.1. Добавление объекта потока в проект с помощью диалогового окна New Items
В появившемся диалоговом окне напишите имя для вашего нового объекта потока. После всего этого Kylix создаст новый модуль и в окне редактора кода появится новая закладка.
Примечание
В отличие от большинства диалоговых окон IDE Kylix, которые требуют ввода имени класса, диалоговое окно создания нового объекта потока не добавляет автоматически букву "T" перед названием нового класса потока Поэтому желательно самостоятельно правильно называть новые потоки, например TMyThread.
Если вы проделали все вышеописанное и назвали новый объект потока TMyThread, то в новом модуле, сгенерированном Kylix, вы можете увидеть код — заготовку для вашего нового объекта потока (листинг 14.2).
Форма приложения
Рисунок 14.2. Форма приложения
Далее запишем в метод Execute объекта TMyThread1 код, который должен выполняться в потоке. Пусть это будет код, который генерирует случайные числа и присваивает их глобальной переменной count. Для того чтобы генераций случайных чисел была бесконечной, зациклим ее с помощью так называемого "бесконечного цикла". В итоге модуль Unit2 должен выглядеть так, как показано на листинге 14.4.
Результат работы многопоточного приложения
Рисунок 14.3. Результат работы многопоточного приложения
Назад Вперед
Основные типы баз данных
Рисунок 15.1. Основные типы баз данных
Среда Kylix обеспечивает поддержку баз данных только реляционного типа. Реляционные базы данных содержат данные в таблицах, состоящих из строк (записей) и колонок (полей). C этими таблицами можно осуществлять определенные операции, которые известны как реляционные вычисления.
Вы можете создавать программы для работы с базами данных, которые имеют различную архитектуру.
Вперед
Схема приложения базы данных
Рисунок 15.2. Схема приложения базы данных
Рассмотрим все четыре части приложения баз данных:
Назад Вперед
Структура таблицы базы данных
Рисунок 15.3. Структура таблицы базы данных
Любая таблица реляционной базы данных состоит из столбцов (полей) и строк (записей). Каждое поле таблицы должно иметь свое уникальное имя.
Примечание
Название поля должно быть уникальным только в пределах данной таблицы. Различные таблицы одной базы данных могут иметь одинаковые имена.
Форма приложения базы данных
Рисунок 15.4. Форма приложения базы данных
Мы не будем вдаваться в подробности пользовательского интерфейса этого приложения. Рассмотрим лишь те особенности, которые относятся к работе с таблицей базы данных.
Итак, на форме располагаются компоненты DataSource1 и ClientDataSet1. Первый компонент обеспечивает взаимосвязь между компонентом ClientDataSet1 и компонентами, отображающими данные. Компонент ClientDataSet1 нужен для указания имени файла таблицы, из которой будут браться записи. Для отображения данных, находящихся в таблице, применяются компоненты DBImage1, DBText1, DBText2, DBMemo1 и DBGrid1.
Компонент DBImage1 будет отображать картинки, содержащиеся в таблице. Для этого в его свойство DataField помещено значение Graphic, обозначающее, что будет отображаться содержимое поля с именем Graphic. Компоненты DBText1 и DBText2 служат для отображения текста (длиной не более одной строки). В их свойства DataField помещено значение CommonName, также обозначающее название поля таблицы, значение которого будет отображать компоненты. Компонент DBMemo1 предназначен для отображения нескольких строк текста и может содержать горизонтальные и вертикальные полосы прокрутки. Данные берутся из поля Notes таблицы, т. к. именно это значение указано в свойстве DataField этого компонента. Наконец, компонент DBGrid1 — самый важный компонент в данном приложении. Он отображает полную запись таблицы и с помощью него происходит перемещение по записям. Запустим приложение. В результате появится форма с заполненными компонентами (Рисунок 15.5).
Приложение в работе
Рисунок 15.5. Приложение в работе
При перемещении по записям с помощью компонента DBGrid1 вы можете видеть, как изменяется содержимое компонентов. Таким образом, для просмотра данных из таблиц практически не требуется написание кода. Важным является лишь задание нужных свойств компонентов. Изучением этих свойств мы и займемся в главе 16.
Назад
Окно эксперта компонентов
Рисунок 19.1. Окно эксперта компонентовЗаполненное окно эксперта компонентов
Рисунок 19.2. Заполненное окно эксперта компонентов
После заполнения полей данного окна нажимаем кнопку ОК, и Kylix автоматически создаст заготовку модуля вашего компонента. Модуль заготовки для нашего примера представлен в листинге 19.1.
Результат обработки события OnMouseDown
Рисунок 19.7. Результат обработки события OnMouseDown
Пример создания нового события компонента
Попробуем теперь создать собственное событие. Для этого нужно сначала убедиться, что такого события нет в CLX Kylix. Предположим, возникла необходимость создания события, которое генерируется каждые 30 секунд. Естественно, для такого случая можно воспользоваться компонентом Timer, который расположен на вкладке System палитры компонентов Kylix. Но допустим, что наш компонент должен иметь такое событие для удобства работы с ним. Код для создания такого события представлен в листинге 19.14.
Результат регистрации компонента
Рисунок 19.8. Результат регистрации компонента
Обратите внимание на значок, которым обозначается новый компонент. Его можно поменять на другой. Для создания собственного значка можно использовать любой редактор растровых изображений.
Создайте значок для вашего компонента размером 24x24 пиксела. Данное изображение сохраните в файле формата DCR. Имя файла — это имя вашего компонента, в котором все буквы — заглавные. Например, для компонента TMyButton имя файла картинки будет TMYBUTTON.DCR. Затем поместите файл картинки в ту папку, в которой находится файл с модулем компонента. Перекомпилируйте модуль, и ваш компонент будет изображаться в палитре компонентов вашим рисунком.
Назад
Одномерный массив на десять переменных
Рисунок 2.1. Одномерный массив на десять переменных
Статический одномерный массив:
var MyArray: array[1..100] of Char;
Данная запись задает одномерный массив с именем MyArray, который будет содержать 100 символьных переменных. Данные переменные будут иметь индекс от 1 до 100. Так, например, для доступа к пятому элементу массива нужно использовать запись MyArray [5] .
Динамический одномерный массив:
var MyFlexibleArray: array of Real;
Данное объявление, в отличие от предыдущего, не занимает память под будущий массив. Для того чтобы это сделать, можно воспользоваться вызовом процедуры SetLength. Например, команда
SetLength(MyFlexibleArray, 20);
отводит в памяти массив на 20 вещественных чисел с индексами от 0 до 19.
Примечание
Индексами динамических массивов всегда являются целые числа. Стартовый индекс — всегда 0.
Доступ к элементам динамического массива аналогичен доступу к элементам статического массива.
Более сложным примером массива является двумерный массив. Его можно представлять как таблицу переменных, составленную из строк и столбцов (Рисунок 2.2).
Двумерный массив А на двадцать элементов Задание статического двумерного массива
Рисунок 2.2. Двумерный массив А на двадцать элементов Задание статического двумерного массива:
var MyMatrix: array[1..10, 1..50] of Real;
Многомерные массивы называют еще и массивами массивов. То есть можно записать задание того же двумерного массива как:
var MyMatrix: array[1..10] of array[1..50] of Real;
Обращение к элементу массива происходит по всем его индексам. Например, для нашего двумерного массива доступ к элементу может выглядеть так: MyMatrix[5,30], либо MyMatrix[5] [30].
Для задания многомерного динамического массива можно использовать конструкцию языка:
array of array of baseType;
Например, создать двумерный динамический массив можно следующим образом:
var MyArray: array of array of integer;
Для того чтобы установить длину многомерного динамического массива с помощью процедуры setLength, нужно выполнить ее для всех индексов массива. Например,
SetLength(MyArray, 10,20);
Записи
Записи являются аналогом структур в других языках программирования. Они объединяют фиксированное число разнородных элементов (элементов разных типов). Каждый элемент записи имеет свое уникальное в пределах записи имя и называется полем.
Записи делятся на:
Record
FieldList1: Type1;
...
FieldListN: TypeN;
End;
где FieldList1 — имя первого поля, a FieldListN — имя последнего, N-го поля записи.
Вариантная запись — это запись, которая состоит из фиксированного числа полей, но позволяющая по-разному рассматривать области памяти, занимаемые полями. Вариантная часть в объявлении записи начинается со слова case и должна располагаться после объявления других полей записи. Для объявления вариантной записи можно использовать следующую конструкцию:
Record
FieldList1: Type1;
...
FieldListN: TypeN;
case tag: ordinalType of
constantList1: (variant1);
...
constantListn: (variantn);
end;
Первая часть объявления записи, до слова case, такая же, как и в фиксированной записи. После слова case начинается вариантная часть. В этой части:
Вкладка Packages диалогового окна Project Options
Рисунок 20.1. Вкладка Packages диалогового окна Project Options
Окно добавления пакета в проект
Рисунок 20.2. Окно добавления пакета в проект
Примечание
При изменении пути поиска (Search path) в диалоговом окне добавления пакета (см. Рисунок 20.2) вы измените глобальные настройки путей к библиотекам Kylix
При вводе имени пакета с клавиатуры (в поле для редактирования без применения кнопки Add) вам не потребуется вводить расширение пакета. Обратите внимание, что названия пакетов записываются через точку с запятой:
baseclx; visualclx; visualdbclx; dataclx
Пакеты, перечисленные в поле для редактирования, при компиляции вашего приложения будут автоматически связаны с ним. Если в поле для ввода имен пакетов не будет ни одного названия пакета, ваше приложение от-компилируется как не использующее пакеты. В случае, если один и тот же пакет будет записан в поле для редактирования несколько раз, все лишние записи будут проигнорированы.
Примечание
Вся информация об используемых приложением пакетах будет сохранена только для данного приложения. Если вы хотите, чтобы настройки сохранялись для других приложений, установите флажок Default, находящийся в нижней части диалогового окна Project Options.
Очень важно помнить, что даже если вы используете в своем приложении пакеты, вы все равно должны прописывать имена модулей среды Kylix в блоке uses:
unit MainForm;
interface
uses
SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs;
Хотя все из вышеперечисленных модулей входят в один пакет bplclx, если убрать их описание из блока uses, компилятор сгенерирует ошибку.
Назад Вперед
Окно просмотра компонентов входящих в пакет
Рисунок 20.3. Окно просмотра компонентов, входящих в пакет
Назад Вперед
Пиктограмма Package диалогового окна New Items
Рисунок 20.4. Пиктограмма Package диалогового окна New Items
Редактор пакета включает в себя два раздела: содержания (Contains) и требований (Requires). Для добавления нового модуля в раздел содержания выберите раздел Contains щелчком мыши, затем щелкните на кнопке Add редактора пакета. Появится диалоговое окно Add (Рисунок 20.6).
Редактор пакета
Рисунок 20.5. Редактор пакета
Вкладка Add Unit диалогового окна Add
Рисунок 20.6. Вкладка Add Unit диалогового окна Add
На вкладке Add Unit диалогового окна Add запишите в поле имени файла модуля имя файла pas, который вы хотите включить в пакет, либо воспользуйтесь кнопкой Browse для непосредственного указания файла. В результате выбранный файл модуля будет добавлен в раздел Contains вашего пакета.
Можете повторить вышеперечисленные действия для добавления дополнительных модулей в пакет.
3. Для добавления пакетов в раздел Requires выберите этот раздел щелчком мыши, затем нажмите кнопку Add редактора пакета.
Диалоговое окно Add
Рисунок 20.7. Диалоговое окно Add
4. В появившемся диалоговом окне (Рисунок 20.7) в поле имени пакета (Package name) введите имя файла пакета (dcp), требуемого для работы вашего пакета. Вы также можете использовать кнопку Browse для непосредственного указания файла пакета. Повторяя данный шаг, вы можете добавить несколько файлов пакетов в раздел Requires вашего пакета.
5. Для выбора типа создаваемого пакета (runtime или design-time) щелкните на кнопке Options редактора пакета (см. Рисунок 20.5). Откроется диалоговое окно Project Options (Рисунок 20.8).
6. Теперь выберите нужный тип приложения с помощью переключателя в разделе Usage options.
7. Последний шаг — компиляция созданного пакета. Нажмите кнопку Compile редактора пакета.
Диалоговое окно Project Options
Рисунок 20.8. Диалоговое окно Project Options
Редактировать уже существующий файл пакета можно по-разному:
Package user;
Requires baseclx, vcl, visualclx;
Contains QMyButton, Week in 'home/kylix/lib';
end.
Назад Вперед
Форма приложения
Рисунок 4.1. Форма приложения
Для каждой формы приложения Kylix создается новый модуль. Например, при первоначальном запуске среды вы видите на экране форму с именем Form1 (Рисунок 4.1) и модуль формы с именем Unit1.pas (Рисунок 4.2).
Модуль Unitl pas
Рисунок 4.2. Модуль Unitl.pas
Рассмотрим состав модуля более подробно:
unit имя модуля; interface // Начало раздела интерфейса
uses // Список используемых модулей
const // Раздел объявления констант
type // Раздел объявления типов
var // Раздел объявления переменных
// Заголовки процедур // Заголовки функций implementation // Раздел реализации
uses // Список используемых модулей const // Раздел объявления констант
type // Раздел объявления типов
var // Раздел объявления переменных
// Описание процедур // Описание функций
initialization // Раздел инициализации // Операторы и команды finalization // Раздел завершения // Операторы и команды
end.
Первый раздел — раздел интерфейса, который является как бы "лицом" данного модуля. В нем размещены описания модулей, используемых данным модулем, а также объявляются типы, константы, переменные, функции и процедуры, описываются идентификаторы, являющиеся доступными всем модулям и программам, использующим данный модуль. Заметим, что для функций и процедур в данном разделе записываются только их заголовки. Непосредственно процедуры и функции размещены в следующем разделе — разделе реализации.
В разделе реализации, кроме процедур и функций, описываются типы, константы, переменные, а также модули, которые используются только в этом модуле, а за его пределами не видны. Кроме того, в данном разделе размещаются директивы компилятора — служебные команды среды разработки.
Последние два раздела не являются обязательными. В разделе инициализации размещаются операторы и команды, которые должны выполняться в начале работы программы, подключающей эти модули.
При наличии раздела инициализации в модуле может присутствовать раздел завершения. В данном разделе находятся операторы и команды, которые выполняются при завершении работы программы.
Назад
Иерархия классов Kylix
Рисунок 7.1. Иерархия классов Kylix
Следующий базовый класс, являющийся прямым потомком TObject, — класс TPersistent. Данный класс является предком всех классов, предназначенных для работы с потоками. Класс TPersistent наследует все свойства и методы своего предка — класса TObject, и может, кроме того, считывать данные из потока и записывать их в поток. Класс TPersistent обеспечивает:
Класс TGraphic — потомок класса Tpersistent, абстрактный класс. Данный класс является родительским для таких объектов, как иконки, растровые изображения и метафайлы, которые могут хранить и отображать визуальные изображения. Данный класс, кроме того, предоставляет методы для работы с объектом TPicture и буфером обмена.
Класс THandleComponent — является базовым для невизуальных компонентов, у которых имеется дескриптор окна.
Дескриптор окна — это число (индекс), индивидуальное для данного конкретного окна, назначаемое системой Linux.
Класс TField — является базовым для всех компонентов, содержащих поля. Данный класс инкапсулирует свойства, события и методы, которые используются для:
Нам осталось рассмотреть еще два класса, которые являются потомками класса TControl.
Первый из этих классов — класс TGraphicControl. Данный класс предназначен для создания визуальных компонентов, которые не являются окнами, т. е. не могут содержать в себе других компонентов и не могут получать фокус ввода. Главное предназначение данного класса — способность отображать графику или текст на компоненте. Примерами потомков класса TGraphicControl могут выступать такие компоненты, как, например, TBevel, TImage. Класс TGraphicControl передает своим потомкам свойство Сanvas, позволяющее получать доступ к поверхности компонента, на которой можно рисовать или писать. Кроме того, класс TGraphicControl передает своим потомкам метод Paint.
Примечание
Подробному изучению графических возможностей Kylix посвящена глава 13 книги.
Второй из этих классов — класс TWidgetControl. Данный класс является базовым классом для всех оконных визуальных компонентов.
Оконный визуальный компонент — это компонент, который:
Займемся теперь потомками класса TWidgetControl.
Класс TCustomControl — это базовый класс для оконных компонентов, которые имеют свойство Сanvas для рисования. Данный класс используется, в основном, для создания оконных компонентов, которые не соответствуют стандартным окнам.
Класс TFrameControl — это базовый класс для всех оконных компонентов, которые имеют различную окантовку (различные стили бордюра). Данный класс поддерживает 3D-эффекты и имеет специальные свойства для установки различных стилей бордюра.
Класс TScrollingWidget — это базовый класс для всех оконных компонентов, которые имеют полосы прокрутки (скроллинг). Такие компоненты обычно имеют горизонтальную и вертикальную полосы прокрутки содержимого окна. Примерами таких компонентов могут служить TForm и TScrollBox.
И наконец, класс TCustomForm — базовый класс для создания окна на основе желаний программиста. Данный класс объединяет в себе возможности всех своих классов-предков. Таким образом, он поддерживает различные стили бордюра окна, имеет свойство Canvas и может содержать полосы прокрутки.
Назад
Вложенные блоки в обработчике исключений (а) и в конструкции защиты кода (б)
Рисунок 9.3. Вложенные блоки в обработчике исключений (а) и в конструкции защиты кода (б)
При разработке приложений в среде Kylix могут возникнуть ситуации, когда программисту не требуется обрабатывать исключения, а необходимо лишь прервать нежелательное действие, вызывающее ошибку. Для этого применяются так называемые молчаливые исключения (silent exceptions).
Молчаливые исключения — это исключения, которые не отображают на экране сведений о том, что произошла ошибка. В результате будет пропущена команда, которая вызвала исключение, и приложение будет работать дальше.
Молчаливые исключения являются потомками стандартного исключения EAbort. По умолчанию обработчик ошибок CLX Kylix отображает на экране диалоговое окно ошибки для всех исключений, кроме наследников EAbort.
Примечание
При создании консольных приложений сведения об ошибке выводятся и для необработанных исключений EAbort.
Для того чтобы сгенерировать молчаливое исключение, можно вызвать процедуру Abort. Она автоматически сгенерирует исключение EAbort, которое прервет текущую операцию без вывода сведения об ошибке на экран. Рассмотрим пример. Пусть форма содержит пустой список ListBox1 и кнопку Button1 (Рисунок 9.4).
Форма с пустым списком
Рисунок 9.4. Форма с пустым списком и кнопкой Button1 Запишем в обработчик события кнопки OnClick следующий код (листинг 9.8):
Результат выполнения программы генерации молчаливого исключения
Рисунок 9.5. Результат выполнения программы генерации молчаливого исключения
Результат многократного нажатия кнопки
Рисунок 9.6. Результат многократного нажатия кнопки Button1
Назад Вперед
Схема обработки события
Рисунок 8.16. Схема обработки событияРассмотрим основные события, которые может обрабатывать компилятор Kylix. Для начала перечислим эти события:
• при выборе пользователем путем нажатия клавиш управления курсором элемента в сетке (Grid), дереве (Trее), списке (List) или выпадающем списке (DropDown List);
• при нажатии пользователем клавиши < Пробел> или
• при нажатии пользователем клавиши
• при нажатии пользователем клавиши
• при нажатии пользователем комбинации клавиш быстрого доступа ("горячих" клавиш) для доступа к кнопке или пункту меню. Например, в свойстве Caption кнопки формы записано &Пуск, при этом надпись на кнопке имеет вид Пуск. В этом случае, если пользователь нажимает комбинацию клавиш
• при установке приложением свойства Сhecked переключателя RadioButton в true;
• при изменении приложением свойства Checked индикатора CheckBox;
• при вызове метода Click элемента меню приложения.
Примечаниe
К одному и тому же компоненту нельзя написать обработчики событий OnClick и OnDblClick, поскольку первый из них всегда перехватит первый из щелчков.
State: TDragState; var Accept: Boolean); begin
// Данный комментарий нужен, чтобы компилятор не удалил этот пустой // обработчик end;Во время перетаскивания компонента форма указателя мыши может изменяться. Для установки этого свойства служит свойство DragCursor компонента, на который будет переноситься другой компонент.
Приведем простой пример использования событий OnDragDrop и OnDragOver.
Для наглядного применения события OnDragDrop создадим приложение, которое позволит пользователю перетаскивать строки одного списка в другой. Итак, расположим на форме два списка ListBox; ListBox1 и ListBox2. Добавим строки в первый список путем редактирования его свойства Items. Назовем строки Cтрока 1 Cтрока 10 (Рисунок 8.17).
Для простоты будем перетаскивать строки из первого списка во второй. Поменяем значение свойства DragMode списка ListBox1 на dmAutomatic, что обеспечит автоматическое начало перетаскивания. Теперь для второго списка (ListBox2) напишем обработчик события OnDragOver (листинг 8.2).
Системы
системыВ этой главе мы рассмотрим принципы, по которым подключается файл справки к вашему приложению.
CLX не обеспечивает прямую поддержку отображения файла справки. Он обеспечивает механизм, с помощью которого запросы об отображении справки вызывают внешние программы, отображающие справочные файлы (такие, как Man, Info или HyperHelp). Кроме того, для работы этого механизма на разработчика возлагается задача по созданию класса, который поддерживает интерфейс ICustomHelpViewer (и, по желанию, один из интерфейсов-потомков ICustomHelpViewer). После чего необходимо зарегистрировать экземпляр данного класса с помощью глобального менеджера помощи (global Help Manager).
Менеджер помощи содержит список всех зарегистрированных в системе программ для отображения файлов помощи и передает ему запросы вашего приложения. Запросы передаются в две фазы:
Примечание
Если более чем одна программа поддерживает данный формат ключевых слов или содержания, то менеджер помощи отобразит окно, с помощью которого пользователь сам сможет выбрать приложение для просмотра файла справки. В противном случае, файл справки отобразится в первой из программ, поддерживающих данный формат ключевых слов.
Интерфейс ICustomHelpViewer необходим для обеспечения поддержки помощи по ключевому слову. Интерфейс IExtendedHelpViewer необходим для поддержки контекстно-зависимой помощи.
Интерфейс ICustomHelpViewer предоставляет три метода для работы со справкой по ключевому слову:
Для того чтобы менеджер помощи мог работать с интерфейсами ICustomHelpViewer, IExtendedHelpViewer, ISpecialWinHelpViewer и IhelpSelector, необходимо осуществить регистрацию объекта справочной системы.
Модуль, который содержит описание данного объекта, должен иметь в списке используемых модулей модули HelpIntfs и QForms. Экземпляр объекта должен быть объявлен в секции var раздела реализации (implementing) модуля.
Вместе со средой Kylix поставляются файлы, помогающие создавать систему помощи для ваших приложений. Эти файлы находятся в каталоге
/kylix/demos/helpviewers/.
Здесь располагаются три основных файла:
Модуль WinHelpViewer обеспечивает связь между приложением и HyperHelp (эмулятором WinHelp под Linux).
Модуль ManViewer обеспечивает связь между приложением и системой Linux man.
Пакет HelpViewers представляет собой пример пакета, который содержит модуль ManViewer. Этот пакет зарегистрирован как пакет времени разработки в IDE и обеспечивает связь IDE со страницами man. Данный пакет не может быть использован во время работы приложения.
с конкретным кодом, называемым обработчиком
СобытияСобытие (event) — это механизм, который связывает какое-либо происшествие с конкретным кодом, называемым обработчиком события (event handler).
Механизм обработки событий будет подробно рассмотрен во второй части книги. Пока лишь отметим, что среда Kylix поддерживает два основных типа событий:
Системные события — это события, происходящие в операционной системе. Например, тикание системного таймера.
Назад Вперед
Сообщения и системные события
Сообщения и системные событияСообщения и события в Linux работают иначе, чем в Windows. Этот факт в первую очередь влияет на процесс создания своих компонентов. Несмотря на это, большинство компонентов и редакторов свойств переносятся в Linux достаточно легко. Так, например, интерфейс TObject. Dispatch замечательно функционирует в Linux.
Для подмены определенного системного сообщения Windows вы можете использовать один из методов, описанных в табл. 21.6. В этом случае вы сможете написать обработчик метода вместо обработчика сообщения операционной системы Windows.
Совместимости модулей Kylix и Delphi
Совместимости модулей Kylix и DelphiВсе компоненты и объекты VCL и CLX определены в файлах модулей (pas). Например, вы можете найти описание объекта TObject в модуле System.pas, а описание базового класса TCoroponent — в модуле Classes.pas. Когда вы помещаете объект на форму или используете его внутри своего приложения, имя модуля, который содержит данный компонент, помещается в раздел uses. Это позволяет компилятору узнать, какие модули использует ваше приложение при работе,
В табл. 21.3 приведен список модулей Delphi и совместимых с ними модулей Kylix. Некоторые модули Delphi имеются только в новой версии Delphi — Delphi 6.
Совместное использование файлов ресурсов Linux и Windows
Совместное использование файлов ресурсов Linux и WindowsЕсли вы хотите, чтобы ваше приложение успешно функционировало и в Windows и в Linux, вы можете распространять ваше приложение с ресурсными файлами, которые необходимы как для одной, так и для другой операционной системы. Для этого вы можете разместить файлы ресурсов на сервере, который является доступным для обеих систем или использовать Samba на Linux-компьютере для обеспечения доступа к файлам через сеть Microsoft.
Файлы форм (dfm в Delphi) имеют расширение xfm в Kylix. Если вы хотите использовать один и тот же файл формы для Linux и Windows, переименуйте dfm файлы в xfm. Иначе файлы dfm будут изменены средой Linux таким образом, что они не будут функционировать в среде Windows.
Примечание
Переименование файлов принесет результат лишь в том случае, если вы используете Delphi 6, которая поддерживает CLX.
Назад Вперед
Создание и редактирование пакетов
Создание и редактирование пакетовПроцесс создания пакета включает в себя:
1. Выберите в главном меню Kylix команду File/New.
2. В появившемся диалоговом окне выберите пиктограмму Package (Рисунок 20.4). Сгенерированный пакет будет отображен в редакторе пакета (Рисунок 20.5).
Создание методов компонента
Создание методов компонентаДобавление методов в новый компонент — операция несложная. Однако нужно обратить внимание на некоторые особенности, которые в дальнейшем облегчат взаимодействие пользователя с вашим компонентом.
Во-первых, необходимо, чтобы методы не были взаимозависимыми, т. е. каждый метод должен быть самостоятельным и законченным. Во-вторых, метод не должен блокировать компонент. И в-третьих, метод должен иметь имя, соответствующее выполняемым действиям.
Как вы уже знаете, методы объявляются в секциях private, public и protected. При создании нового метода важно учитывать, как он будет использоваться в дальнейшем, сможет ли данный компонент быть предком для других компонентов, и, в зависимости от этого, расположить методы в нужных секциях. Табл. 19.2 поможет вам при выборе секций для методов компонента.
Создание приложения наподобие графического редактора
Создание приложения наподобие графического редактораВ графическом редакторе обычно присутствует панель инструментов, на которой располагаются кнопки. Каждая из кнопок позволяет рисовать различные фигуры (линии, точки, геометрические фигуры и многое другое). Такие кнопки удобнее всего создавать с помощью компонента CLX TSpeedButton.
Приложение должно узнавать, какую кнопку нажал пользователь, и переходить в режим рисования данного объекта. Для этого вы можете сопоставить с каждым типом фигуры целое число, но в этом случае вам придется помнить, что обозначает каждое число. Если вы позволите пользователю создавать множество фигур, то это будет довольно трудно.
Однако все это можно значительно упростить, если вы сопоставите имена-константы каждому числу. Кроме того, вы можете прибегнуть к применe-нию перечисляемого типа.
Для объявления перечисляемого типа используйте слово Тyре. Например, нижеприведенный код объявляет перечисляемый тип, содержащий все типы фигур, которые приложение позволяет рисовать пользователю:
type
TDrawangTool = (dtLxne, dtRectangle, dtEllipse, dtRoundRect);
По соглашению, идентификатор типа (в нашем случае — это TDrawmgTool) начинается с буквы T, а группа перечисляемых констант начинается с двух-буквенного префикса (в нашем случае — букв dt).
Это объявление эквивалентно объявлению группы констант:
const
dtLine = 0;
dtRectangle = 1;
dtEllipse = 2;
dtRoundRect = 3;
Главное отличие объявления группы констант и перечисляемого типа заключается в том, что в случае объявления типа вы присваиваете константам не только значение, но и новый тип, который позволяет языку Object Pascal проверять соответствие типов и предотвращать возможные ошибки. Переменная, имеющая тип TDrawingTool, может иметь значение только из перечисленных (dtLine ... dtRoundRect). Любая попытка присвоения переменной других чисел (не входящих в диапазон от 0 до 3) вызовет ошибку компиляции.
Код, приведенный в листинге 13,13, объявляет все необходимые константы для будущего приложения, позволяющего пользователю выбирать инструмент для рисования.
Создание простой игровой программы
Создание простой игровой программыТеперь вы можете создавать графические приложения практически любой сложности. Рассмотрим пример создания игры "Крестики-нолики" на поле 10x10 клеток. Мы не будем касаться вопросов создания искусственного интеллекта, предоставив это читателю. Рассмотрим лишь вопрос создания графической оболочки игры.
Итак, пусть программа работает в качестве игрового поля, на котором игроки смогут последовательно ставить крестики и нолики. Создадим форму-заготовку (Рисунок 13.10), на которую поместим две кнопки Button1 и Button2. Первая будет готовить игровое поле, а вторая позволит выйти из программы.
Теперь напишем код для этих двух кнопок. Ниже приведен полный код модуля unit1 с соответствующими пояснениями и комментариями (листинг 13.29). Думаем, что читатель во всем разберется без особых проблем.
Создание SDI и MDIприложений
Создание SDI- и MDI-приложенийKylix позволяет создавать приложения двух моделей пользовательского интерфейса:
Примечание
По умолчанию свойство FormStyle у формы нового приложения устанавливается в fsNormal.
Для создания нового SDI-приложения выполните следующие шаги:
1. Выберите в главном меню Kylix пункт File/New. Появится диалоговое окно New Items (Рисунок 10.1).
Создание событий компонента
Создание событий компонентаСтандартные события компонентов CLX Kylix мы с вами уже рассматривали в предыдущих главах. В настоящий момент нам предстоит дать четкое определение событию, а также обработчику события.
Итак, событие — это любое действие, произошедшее благодаря операционной системе, действиям пользователя, работе программы.
Событие можно "перехватить" и обработать с помощью программы-обработчика события. Связь между событием и программой-обработчиком называется свойством-событием. Таким образом, когда происходит какое-либо событие компонента, он может обработать данное событие. Для этого сначала проверяется наличие кода обработки события. Если такой код есть — он выполняется.
Рассмотрим в качестве примера такое часто возникающее событие, как нажатие левой кнопки мыши OnClick. Данное событие, как и многие другие, имеет так называемые методы диспетчеризации событий (event-dispatching methods). Такие методы нужны для того, чтобы определять, создан ли код обработки данного события для данного компонента. Эти методы объявляются как защищенные (protected). Таким образом, для свойства OnClick определен метод диспетчеризации события Click (листинг 19.12).
Создание справочной
Создание справочнойСоздание заготовки компонента
Создание заготовки компонентаИтак, вы выбрали класс-предок для вашего компонента. Теперь можно приступать к созданию модуля вашего компонента. Создание модуля (заготовки) для нового компонента можно выполнить путем вызова окна Kylix, которое называется экспертом компонентов (Component Expert). Дан-ное окно можно вызвать путем выбора в главном меню Kylix пункта Component/New Component. При этом появляется окнo, изображенное на Рисунок 19.1.
Рассмотрим данное окно. Итак, первое поле ввода Ancestor type предназначено для ввода класса — предка для нового компонента. Данное поле ввода содержит в выпадающем списке все зарегистрированные классы библиотеки CLX. Предположим, что мы будем создавать компонент, предком которого является кнопка TButton. Для этогo выберем в выпадающем списке класс TButton. Следующее поле Class Name предназначено для ввода имени нового класса. Пусть в нашем случае это будет новый класс TMyButton. Заметьте, что та умолчанию Kylix заполняет это поле именем класса-предка с добавлением порядкового номера (в нашем случае TButton1). Следующее поле Palette Page показывает, на какой вкладке палитры компонентов будет расположен новый компонент после его регистрации. Оставим в этом поле значение, предлагаемое Kylix по умолчанию Samples. Следующие два поля Unit file name и Search path заполняются средой Kylix самостоятельно, но разработчик может их изменить. Мы не будем этого делать в нашем примере. В результате окно эксперта компонентов должно быть заполнено так, как показано на Рисунок 19.2.
Средства для работы с базами данных
Средства для работы с базами данныхСреда Kylix предоставляет набор драйверов, необходимых для работы с базами данных, которые описаны выше. Кроме того, Kylix предоставляет программисту несколько компонентов, обеспечивающих работу с базами данных. Мы их кратко рассматривали в восьмой главе книги. Попробуем рассмотреть методику использования этих средств для создания простого приложения. Для этого воспользуемся файлом примера, который поставляется вместе со средой Kylix. Его можно найти в каталоге /kylix/demos/db/fishfact/.
Итак, запустим Kylix и откроем проект Fishfaet.dpr. Данный проект представляет собой простой просмотрщик содержимого базы данных. Как вы можете видеть, он написан практически без использования кода. Есть лишь одна команда, которая активизируется при показе главной формы приложения. В листинге 15.1 представлен код главного модуля Ffactlin этого приложения.
Статические методы
Статические методыСтатические методы аналогичны обычным функциям или процедурам Kylix. Адрес такого метода известен среде Kylix на стадии компиляции, поэтому Kylix производит статический вызов метода во время выполнения программы. Статические методы работают быстрее других методов, но не могут быть перегружены (overload).
Перегрузка метода подразумевает, что класс или компонент может содержать несколько методов с одинаковым именем, но разными списками параметров.
Статический метод может быть описан так:
type TCortiponent = class
procedure MyProcedure; end; Здесь метод MyProcedure является статическим. Мы опустили в данном примере название базового класса TObject после слова class. По умолчанию компилятор создает наследников класса TObject.
Назад Вперед
Структура пакета
Структура пакетаВспомним все, что мы уже знаем о пакетах, и нам нетрудно будет понять, из чего состоит пакет.
Пакет состоит из: имени, раздела Requires и раздела Contains.
Package имя пакета;
Requires файлы пакетов, необходимые для работы данного пакета;
Contains файлы модулей, входящие в состав данного пакета;
end.
Имя пакета должно быть уникальным внутри проекта. Например, вы назвали пакет MyPack. При этом редактор пакета создает файл ресурсов с именем MyPack.dpk. При компиляции проекта создается еще два файла с именами MyPack.so и MyPack.dcp.
Файл MyPack.so является исполняемым файлом пакета (аналог so), а файл MyPack.dcp — двоичным файлом (аналог dcu),
Имя пакета необходимо для того, чтобы вызывать его из приложения или вписывать в раздел Requires другого пакета.
Раздел Requires, как уже говорилось ранее, содержит имена файлов пакетов, необходимых для работы рассматриваемого пакета. Следует заметить, что пакеты не могут содержать круговые ссылки, т. е. не должно возникать следующих ситуаций:
Назад Вперед
Структура программы
Структура программыТекст программы состоит из строк, в каждой из которых может находиться одно или несколько слов. Строка может начинаться с любой позиции, на размер компилируемой программы это не влияет.
Структура программы состоит из:
program Program1; / / здесь Program1 — имя программы
В стандартном Pascal заголовок программы может содержать параметры после имени программы:
program Program1(input, output);
Компилятор Kylix игнорирует данные параметры. Их можно указывать или не указывать, на работу программы это не повлияет.
Раздел uses содержит список программных модулей (units), которые используются данной программой:
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
Блок состоит из раздела описания и раздела исполнения. В первой, описательной части находится описание элементов программы, во второй части располагаются операторы, подлежащие исполнению.
Описательная часть обычно содержит (в строгом порядке):
Назад Вперед
Структурированные операторы
Структурированные операторыНапомним, что структурированные операторы — это операторы, которые изменяют ход выполнения команд программы.
К числу структурированных операторов можно отнести:
Оператор перехода
Оператор перехода позволяет перейти от текущего места выполнения программы к другому месту, которое не является следующим по порядку. Данный оператор нарушает нормальный ход выполнения программы.
Переход осуществляется при помощи так называемых меток. Метка — это идентификатор или целое число без знака в диапазоне от 0 до 9999, которое находится перед каким-либо оператором программы и отделено от него двоеточием. Все используемые в программе метки должны быть предварительно объявлены в разделе объявления меток, начинающемся словом label.
Оператор перехода выглядит так:
goto метка;
Приведем фрагмент программы, в которой используется метка:
label 1; // Объявляем метку с именем 1
var
а:integer; begin
а:=10;
goto 1; // Переход на метку 1
a:=sqrt(a); // Этот оператор не будет выполняться никогда! 1:а:=а+а; // Оператор, помеченный меткой 1 end;
Примечание
Использование меток и операторов перехода не является хорошим тоном программирования. Старайтесь по возможности не использовать этот оператор, т. к. это затрудняет чтение текста программы.
Оператор условия
Оператор условия предназначен для выполнения или невыполнения каких-либо действий, зависящих от результата условия типа Boolean. Этот оператор применяют для разветвления выполнения программы. То есть, если данное условие истинно (и только в этом случае!), выполняется некоторая последовательность операторов, иначе — выполняются другие операторы. Вид оператора условия таков:
If условие then оператор1 else оператор2;
Оператор условия может быть записан и в упрощенной форме:
If условие then оператор;
Приведем примеры использования операторов условия:
If a>0 then b:=sqrt(a) else b:=a*2; // Оператор условия
If a=10 then b:=b+l; // Упрощенная форма
Для того чтобы организовать ветвление на несколько направлений (более двух), можно использовать несколько операторов условия, вложенных друг в друга. Вложение операторов условия происходит по тем же правилам, что и вложение составных операторов.
Примечание
Старайтесь не злоупотреблять чрезмерным вложением операторов условия друг в друга, т. к. это может привести к трудно выявляемым ошибкам.
Оператор выбора
Оператор выбора — это конструкция языка, позволяющая сделать выбор из произвольного числа вариантов и выполнить в соответствии с этим выбором определенные действия. То есть оператор выбора позволяет обойтись без использования нескольких операторов if.
Оператор выбора имеет следующий вид:
case селектор of Список1: Оператор1;
. . . СписокN: ОператорN; else
Оператор; end;
Таким образом, оператор выбора case состоит из селектора, списка вариантов и необязательной части else.
Выражение-селектор должно быть обязательно порядкового типа. Нельзя использовать в качестве селектора строковые типы.
Каждое значение списка вариантов представляет собой вариант значения, принимаемого селектором. Оно должно быть:
Структурные типы данных
Структурные типы данныхСтруктурные типы данных — это такие типы, которые состоят из данных других типов, в том числе из данных структурного типа. К числу таких данных относятся:
Строки
В Object Pascal имеются строковые типы данных, которые перечислены в табл. 2.4.
Свойства сгруппированные по категориям
Рисунок 6.6. Свойства, сгруппированные по категориям
Свойства события и методы компонентов
Свойства, события и методы компонентовCLX представляет собой иерархию классов Kylix, написанных на языке Object Pascal. Все классы библиотеки имеют свои свойства, события и методы. Мы их подробно рассмотрим в следующей главе. Пока же дадим здесь общее описание.
Свойства компонентов позволяют управлять их внешним видом и поведением. Установка значений большинства свойств выполняется на этапе разработки приложения с помощью инспектора объектов (см. Рисунок 6.5). Значение практически всех свойств компонентов библиотеки CLX можно изменять в процессе выполнения программы.
Компоненты CLX могут генерировать и обрабатывать несколько десятков самых разнообразных событий. События всегда принадлежат определенному типу. Большинство событий имеет тип "уведомляющее" (то есть принадлежит типу TNotifyEvent). Данный тип описывается следующим образом:
type TNotifyEvent = procedure (Sender: TObject) of object;
Таким образом, события уведомляющего типа указывают на источник события. Источник события записывается в параметре Sender.
Напомним, что все события в Kylix делятся на:
Системные события — это события, которые происходят внутри системы независимо от действий пользователя (тикание таймера и т. д.).
Компоненты библиотеки CLX так же, как и другие объекты, могут иметь (и имеют) методы. Методы позволяют получать доступ к свойствам компонентов, скрывать и отображать компоненты, а также выполнять другие операции (в том числе создание и уничтожение компонентов).
Назад Вперед
Свойства события и методы основных компонентов Kylix
Свойства, события и методы основных компонентов KylixДавайте рассмотрим свойства, события и методы основных компонентов Kylix. Это необходимо для использования всех возможностей, предоставляемых средой Kylix. Более того, когда вы будете создавать собственные компоненты, знание основных компонентов очень вам пригодится (можно создавать компоненты на основе уже имеющихся в Kylix).
Типы свойств
Следует отметить, что к свойствам применимы те же правила, которые используются для описания типов в Object Pascal. Типы свойств компонента нужны в первую очередь для отображения и редактирования его в окне инспектора объектов. Перечислим основные типы свойств компонентов Kylix (табл. 8.12).
и поля, определяют атрибуты объекта.
СвойстваСвойства так же, как и поля, определяют атрибуты объекта. Но в отличие от полей свойства реализуют механизм доступа для чтения или изменения данных в полях объекта.
Вернувшись к примеру со столом, можно сделать следующее сравнение: поле "количество ножек" объекта "стол" будет хранить целое число, обозначающее количество ножек, а свойство "ножки" объекта "стол "может изменять это значение. С помощью данного свойства можно задать "количество ножек" равным трем, четырем и т. д.
Свойства позволяют изменять атрибуты объекта, в том числе, и вычисляемыми значениями. Объявление свойства объекта должно содержать его имя и тип, а также, как минимум, одно объявление способа доступа к данному свойству (описания). Синтаксис объявления свойства объекта имеет вид:
property Имя свойства: тип описания;
Синтаксис обязательных описаний read и write имеет следующий вид:
read поле илиметод
write поле или метод
где поле или метод — поле, из которого берется или в которое помещается значение свойства, или метод, который берет или помещает значение свойства компонента.
Несложно догадаться, что объявление read (читать) описывает поле или метод, предназначенные для чтения значения свойства, а объявление write (писать) описывает поле или метод, предназначенные для записи значения свойства компонента.
В листинге 5.1 приведен пример описания свойств объекта.
Свойствомножество MyOptions в новом компоненте TMyButton
Рисунок 19.4. Свойство-множество MyOptions в новом компоненте TMyButtonСоздание свойства-объекта в компоненте
Каждый компонент может содержать в себе свойство-объект. В качестве свойства-объекта может выступать любой компонент или объект Kylix. Кроме того, свойствами-объектами нового компонента могут быть новые компоненты или объекты, которые вы создали самостоятельно. Важным условием является тот факт, что свойства-объекты должны быть потомками класса TPersistent. Это необходимо для того, чтобы свойства объекта-свойства отображались в окне инспектора объектов. Приведем пример создания свойства-объекта в нашем компоненте TMyButton.
Для начала создадим произвольный новый объект, являющийся прямым потомком класса TPersistent (листинг 19.5).
Свойствообъект MyObject в новом компоненте TMyButton
Рисунок 19.5. Свойство-объект MyObject в новом компоненте TMyButtonОбратите внимание на реализацию метода TMyObject. Assign. Здесь сначала выполняется проверка на то, правильный ли передается экземпляр объекта TMyObject. Если он правильный, то значения свойств (Source) переносятся в поля FProperty1 и FProperty2 объекта TMyButton. Результатом исполнения вышеприведенного кода будет новый компонент TmyButton, содержащий в себе свойство-объект TMyObject. В окне инспектора объектов это будет выглядеть так, как представлено на Рисунок 19.5.
Создание свойства-массива в компоненте
Свойства компонента могут быть практически любого типа, которые поддерживает язык Object Pascal. Некоторые свойства могут быть массивами. Яркими примерами свойств такого типа являются TMemo. Lines и TDBGrib.Columns.. Такие свойства требуют собственных редакторов. Мы пока остановимся на создании простого свойства, которое представляет собой простой массив (о создании собственных редакторов свойств читайте далее в этой главе). Создадим новый компонент TWeek, который будет содержать два свойства: Month и Number. Свойство Month будет представлять собой массив, который будет возвращать название месяца по переданному целому числу от 1 до 12. Свойство Number — тоже массив, который возвращает число, Соответствующее названию месяца.
Итак, в листинге 19.8 приведен код компонента TWeek.
Типы графических объектов Kylix
Таблица 13.1. Типы графических объектов Kylix| Объект |
Описание |
| Picture |
Используется как контейнер для содержания произвольного графического образа. Для того чтобы объект Picture мог содержать файлы дополнительных графических форматов, используйте метод Register |
| Bitmap |
Мощный графический объект, который используется для создания, манипулирования (масштабирование, скроллинг, вращение, закраска) и хранения картинок как файлов на диске |
| Clipboard |
Представляет собой контейнер, хранящий текст или графические образы, которые могут быть скопированы, вырезаны из приложения или вставлены в него |
| Icon |
Представляет собой картинку, загруженную из файла пиктограммы |
| Drawing |
Содержит файл, в котором записаны операции, требующиеся для создания изображения. Не содержит самого изображения. Использование этого объекта позволяет свободно масштабировать изображение без потери деталей и обычно требует меньше памяти, чем хранение графического образа. В то же время, отображает рисунок значительно медленнее, чем другие объекты |
Назад Вперед
Свойства объекта Canvas
Таблица 13.2. Свойства объекта Canvas| Свойство |
Описание |
| Font |
Определяет шрифт, который будет использоваться для вывода текста на картинке |
| Brush |
Определяет цвет и образец кисти, которыми будут заполняться графические объекты и фон канвы |
| Pen |
Определяет тип пера канвы, которым будут чертиться линии и геометрические фигуры |
| PenPos |
Определяет текущую позицию пера |
Методы объекта Canvas
Таблица 13.3. Методы объекта Canvas| Метод |
Описание |
| Arc |
Предназначен для черчения дуги эллипса или окружности. В качестве параметров метода передаются координаты четырех точек. Первые две точки (x1, y1) и (х2, y2) определяют диагональ прямоугольника, в который вписан эллипс. Третья точка (х3, y3) задает начальную точку дуги. Точка (х4, y4) задает конечную точку дуги. Третья и четвертая точки принадлежат прямоугольнику, описывающему эллипс. Точки дуги получаются в результате пересечения прямой, проходящей через центр эллипса и точки (х3,y3) и (х4, y4). Дуга рисуется против часовой стрелки от начальной до конечной точки |
| Chord |
Чертит замкнутую фигуру, границами которой являются дуга окружности или эллипса и хорда. Параметры, передаваемые в данный метод, аналогичны параметрам метода Arc |
Рисует графическое изображение, которое содержится
Таблица 13.3 (окончание)| Метод |
Описание |
| StretchDraw |
Рисует графическое изображение, которое содержится в компоненте, указанном в параметре Graphic, в прямоугольную область канвы, указанную параметром Rect. Причем изображение растягивается или сжимается под размер данной области. Например, Image1. Canvas. StretchDraw (Rect (0, 0, 29, 29), Im-age2 . Picture . Bitmap) ; Уменьшает изображение, имеющее размер больше, чем 30x30 и хранящееся в компоненте Image2, и помещает его на канву компонента Image1 |
| TextHeight |
Возвращает значение, равное высоте текста, который предполагается вывести на канву с использованием текущего шрифта |
| TextOut |
Выводит строку текста, задаваемую параметром Text, на канву в позицию с координатами (х, y). Например, Image1. Canvas. TextOut (10, 10, 'Kylix - лучшая среда разработки под Linux ' ) ; |
| TextRect |
Похож по действию на метод TextOut, только текст, выходящий за пределы определенной прямоугольной области, не выводится |
| TextWidth |
Возвращает значение в пикселах, равное длине текста Text, который предполагается вывести на канву компонента текущим шрифтом |
| TiledDraw |
Рисует размноженное изображение внутри указанного прямоугольника |
Назад Вперед
с одной канвы на другую.
Таблица 13.3 (продолжение)| Метод |
Описание |
| CopyRect |
Копирует прямоугольную часть изображения с одной канвы на другую. Копирование осуществляется в том режиме, который , определен свойством CopyMode |
| Draw |
Рисует изображение, хранящееся в объекте, который определен параметром Graphic, на канву в координаты, задаваемые параметрами х и y. Например, Image1. Canvas. Draw (5, 24, Image2. Picture. Bitmap) ; Копирует в координаты (5, 24) рисунок, находящийся на канве компонента Image2, в, канву компонента Image1 |
| DrawFocusRect |
Рисует изображение пунктирного прямоугольника с автоматической установкой режима пера (свойство Mode) в pmXor. Данный метод имеет место лишь в том случае, когда подсвойство DefaultStyle свойства Style приложения установлено в dsWindows |
| DrawPoint |
Отображает одиночную точку на канве с использованием текущих установок пера |
| DrawPoints |
Рисует несколько точек с использованием текущих установок пера |
| Ellipse |
Чертит на канве эллипс или окружность. Параметрами являются две точки (x1, y1) и (х2, y2 ), которые определяют диагональ прямоугольника, описывающего эллипс |
| FillRect |
Заполняет указанную прямоугольную область канвы цветом, определенным текущим значением свойства кисти (Brush). Например, Image1. Canvas. FillRect (0, 0, 100, 100); Заполняет квадрат с главной диагональю, имеющей координаты (0, 0) и (100, 100), цветом, определенным в свойстве Color кисти |
| GetClipRegion | Возвращает указатель на текущую вырезаемую область канвы |
| LineTo |
Чертит на канве прямую линию, начало которой совпадает с текущим значением координат пера (значение свойства PenPos), а конец задается параметром (х, y) . Конечная точка не принадлежит линии и не отображается. После чего текущими координатами пера станет точка (х, y ) . Например, Image1. Canvas. LineTo (100, 130); Чертит линию от текущей позиции пера до точки с координатами (100, 130), не включая саму точку (100, 130), после чего значением, PenPos будет точка (100, 130) |
Таблица 13.3 (продолжение)
| Метод |
Описание |
| MoveTo |
Изменяет текущую позицию пера ( значение свойства PenРоs) на значение, заданное параметром (х, y). При перемещении пера на канве ничего не чертится. Метод аналогичен прямой установке значения свойства PenPos |
| Pie |
Чертит замкнутый сегмент эллипса или окружности. Параметры метода аналогичны параметрам метода Arc |
| PolyBezier |
Чертит на канве цветом пера Реn сглаженную кривую по заданному множеству точек, определенных в массиве Points. Начинает рисование с точки, определенной параметром Startlndex, используя следующие две точки как направляющие для изгибов кривой. Кривая заканчивается четвертой точкой массива. Например, Image1. Canvas. PolyBezier ( [Point (0, 0) , Point (100, 10), Point (20, 30) , Point (230, 100)], 0); Последний параметр, равный нулю, — это параметр Startlndex |
| PolyBezierTo |
То же самое, что и PolyBezier, только после черчения линии данный метод устанавливает значение свойства PenPos в последнюю точку массива Points |
| Polygon |
Чертит на канве многоугольник по заданному множеству точек, определенных в массиве Points, причем первая точка массива соединяется с последней, после чего многоугольник закрашивается цветом, определенным свойством кисти Brush. Например, Image1. Canvas. Polygon ( [Point (0, 0), Point (10, 10) , Point (20, 30) , Point (230, 100)]); |
| Polyline |
Чертит на канве незамкнутый многоугольник. Аналогичен методу Polygon, только не соединяет первую и последнюю точки массива Points |
| Rectangle |
Чертит на канве текущим пером Реn прямоугольник, закрашенный цветом, определенным в свойстве кисти Brush. В качестве параметров передаются координаты двух точек: левого верхнего и правого нижнего углов прямоугольника, т. е. его главная диагональ |
| RoundRect |
Чертит на канве закрашенный цветом, определенным в свойстве кисти Brush, прямоугольник со скругленными углами. Два параметра (x1, y1) и (x2, y2) задают координаты углов прямoугольника (как в методе Rectangle). Два следующих параметра х3 и y3 задают эллипс с шириной х3 и высотой y3 точек. Углы прямоугольника скругляются по шаблону данного эллипса |
когда пользователь отпускает кнопку мыши
Таблица 13.4 (окончание)| Событие мыши |
Описание |
| OnMouseUp |
Происходит, когда пользователь отпускает кнопку мыши в тот момент, когда указатель мыши расположен над компонентом |
События мыши
Таблица 13.4. События мыши| Событие мыши |
Описание |
| OnMouseDown |
Происходит, когда пользователь нажимает кнопку мыши в тот момент, когда указатель мыши расположен над компонентом |
| OnMouseMove |
Происходит, когда пользователь двигает мышью в тот момент, когда указатель мыши расположен над компонентом |
Параметры событий мыши
Таблица 13.5. Параметры событий мыши| Параметр |
Значение |
| Sender |
Имя объекта, над которым произошло событие мыши |
| Button |
Указывает, какая из трех кнопок мыши нажата. Может принимать значения: mbLeft — левая; mbMiddle — средняя и mbRight — правая |
| Shift |
Показывает состояние кнопок |
| X, Y |
Координаты клиентской части компонента, над которым произошло событие мыши |
Всякий раз, когда пользователь нажимает любую кнопку мыши, происходит событие OnMouseDown. Для использования этого события вам нужно написать обработчик события у желаемого компонента. Например, если вы хотите обработать событие OnMouseDown, когда пользователь нажмет кнопку мыши над формой Form1, нужно в окне инспектора объектов на вкладке Events найти событие OnMouseDown для формы Form1 и дважды щелкнуть на нем. В результате Kylix создаст заготовку обработчика события нажатия кнопки мыши для формы (листинг 13.24).
Листнг 13.24.Заготовка обработчика события OnMouseDown
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
end;
Приведем пример обработки данного события (листинг 13.25). Запустите названную программу. При каждом щелчке в области формы вы увидите надпись "Здесь!" на месте, где вы щелкнули мышью (Рисунок 13.7).
Лизинг 13.25.Пример обработки события OnMouseDown
procedure TForm1. FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Canvas.TextOut (X, Y, 'Здесь!'); { печатает текст на канве }
end;
Значения свойства Policy
Таблица 14.1. Значения свойства Policy| Значение |
Тип значения |
Возможные числовые значения для свойства Priority |
| SCHED_RR |
Real Time |
0-99 |
| SCHED_FIFO |
Real Time |
0-99 |
| SCHED_ОTHER |
Regular |
0 |
Значения SCHED_PR и SCHED_FIFO могут быть установлены только в том случае, когда вы вошли в Linux под администратором (root)
Для Windows-приложений свойство Priority может принимать значения, перечисленные в табл. 14. 2.
Значения свойства Priority для Windows
Таблица 14.2. Значения свойства Priority для Windows| Значение приоритета |
Приоритет |
Cоответствующее числовое значение |
| Tpldle |
Данный поток выполняется, когда система не занята и не выполняются никакие другие потоки Windows не будет прекращать работу других потоков для выполнения потока, имеющего приоритет tpldle |
-15 |
| TpLowest |
Низший приоритет выполнения. Данный поток занимает минимум процессорного времени |
-2 |
| TpLower |
Низкий приоритет. Данный поток занимает немного больше процессорного времени, чем имеющий приоритет tpLowest |
-1 |
| TpNormal |
Нормальный приоритет. Все потоки по умолчанию имеют приоритет tpNormal |
0 |
| TpHigher |
Высокий приоритет. Данный поток имеет приоритет выше нормального |
1 |
| TpHighest |
Высший приоритет. Данный поток имеет приоритет выше, чем tpHigher |
2 |
| TpTimeCntical |
Наивысший приоритет Поток с данным приоритетом занимает максимум процессорного времени |
15 |
Использование высших и наивысших приоритетов может привести к замедлению работы других потоков Применение данных видов приоритетов целесообразно использовать в случае, когда возникает острая необходимость в скорейшем выполнении одного из процессов
Поведение потока
при завершении его работы
Обычна при завершении своей работы поток просто освобождается. Однако иногда бывает необходимо, чтобы завершение работы и освобождение потока было согласовано с другими потоками. Например, вы можете ожидать какое-либо значение, возвращаемое одним потоком, перед выполнением другого потока. Для реализации этого вы не должны освобождать первый поток, пока второй не получит значение, возвращаемое первым. Для управления завершением работы потока существует свойство потока FreeOnTerminate. Пo умолчанию данное свойство установлено в true. При этом поток освобождается по завершении своей работы. Если же установить данное свойство в false, то вы можете сами завершить работу потока.
Кроме того, в Kylix имеется возможность прекратить выполнение одного потока подачей команды о прекращении из другого потока. Когда один поток пытается прекратить работу другого потока, он вызывает метод Terminate. В результате, свойство Terminate потока будет установлено в true, что можно проверить во время выполнения метода Execute (листинг 14.3).
Свойства компонента TDataSource
Таблица 16.1. Свойства компонента TDataSource| Свойство |
Описание |
| AutoEdit |
Определяет, будут ли компоненты, отображающие данные, переключаться в режим редактирования при попытке изменения данных пользователем. Имеет тип Boolean |
| DataSet |
Определяет имя набора данных, с которым связан источник данных. Имеет тип TdataSet |
| Enabled |
Определяет, будут ли отображаться данные в компонентах, предназначенных для показа данных, которые связаны с этим источником данных. Имеет тип Boolean |
| Name |
Определяет имя компонента TdataSource |
| Tag |
Свойство, которое может использоваться по усмотрению программиста и не имеет специального назначения. Многие компоненты содержат это свойство. Свойство имеет тип Integer |
Содержит список наименований полей таблицы,
Таблица 16.10 (окончание)| Свойство | Описание |
| IndexFieldNames | Содержит список наименований полей таблицы, по которым будет производиться сортировка набора данных. Имена полей разделяются точкой с запятой. Имеет тип String |
| IndexName | Содержит имя индекса, по которому будет произведена сортировка набора данных. Имеет тип String |
| MasterSource | Содержит имя главного источника данных при организации связи таблиц главная-подчиненная (master-detail). Имеет тип TdataSource |
| MasterFields | Содержит имена полей, по которым осуществляется связь между главной и подчиненной таблицей. Имеет тип String |
| ObjectView | Включает или выключает иерархические представления для вложенных полей. Имеет тип Boolean |
| Options | Содержит параметры работы с данными. Имеет тип TproviderOptions |
| PacketRecord | Определяет количество записей в одном пакете данных. Имеет тип Integer. Возможные значения: -1 — все записи; >0 — конкретное число записей; 0 — в пакет будут включаться только мета-данные |
| Params | Определяет список параметров набора данных. Имеет тип Tparams |
| Readonly | Определяет способ доступа к записям. Имеет тип Boolean. Если значение свойства — true, то данные доступны только для чтения. Если значение — false, то можно изменять существующие данные и записывать новые |
| Tag | Свойство, которое может использоваться по усмотрению программиста, и у него нет специального назначения. Свойство имеет тип Integer |
| UpdateMode | Определяет способ поиска записи, которую необходимо обновить. Имеет тип TupdateMode. Может принимать значения: UpWhereAll — искать по всем полям; UpWhereChanged — искать по ключевым и измененным полям; UpWhereKeyOnly — искать только по ключевым полям |
Имеет тип String. При установленном
Таблица 16.10 (продолжение)| Свойство | Описание |
| CommandText | Содержит текст SQL-запроса. Имеет тип String. При установленном значении свойства FileName это свойство игнорируется. Свойство игнорируется также и в случае, когда в свойстве Options сброшен флажок poAllowCommandText |
| CommandType | Определяет тип набора данных. Значение свойства имеет тип TSQLCommandType. Свойство может принимать следующие значения: Ct Query — обычный SQL-запрос; CtTable — таблица целиком, при этом автоматически будет сгенерирован запрос на выборку всех записей таблицы по всем полям; CtStoredProc — процедура, хранимая на сервере базы данных |
| ConnectionName | Содержит имя конфигурации. Имеет тип String. Является аналогом свойства AliasName в Delphi |
| Constraints | Определяет накладываемые ограничения на значение на уровне одной записи. Имеет тип Tconstraints |
| DBConnection | Определяет имя компонента TSQLConnection, с помощью которого будет производиться работа с базой данных. Имеет тип TSQLConnection |
| DisableStringTrim | Определяет, нужно ли удалять лишние пробелы в конце строки при вставке ее в таблицу базы данных. Имеет тип Boolean |
| FetchOnDemand | Определяет, должно ли приложение получать данные по мере необходимости. Имеет тип Boolean |
| FieldDefs | Содержит список полей, определяющих набор данных. Имеет тип TfieldDefs |
| FileName | Содержит имя файла, в котором хранятся кэшируемые данные. Имеет тип String |
| Filter | Задает фильтр, по которому будут выбираться данные из таблицы. Имеет тип String |
| Filtered | Определяет, включено или выключено свойство Filter. Имеет тип Boolean |
| FilterOptions | Определяет параметры фильтрации записей таблицы. Имеет тип TfilterOptions |
| IndexDefs | Содержит определения индексов. Имеет тип TindexDefs |
Свойства компонента TSQLClientDataSet
Таблица 16.10. Свойства компонента TSQLClientDataSet| Свойство | Описание |
| Active | Определяет, является ли набор данных активным. Свойство имеет тип Boolean |
| Aggregates | Содержит список доступных агрегатов. Имеет тип Taggregates |
| AggregatesActive | Определяет, нужно ли производить вычисления агрегатов. Имеет тип Boolean |
| AutoCalcFields | Определяет, нужно ли генерировать событие OnCalcFields и обновлять содержимое полей. Имеет тип Boolean. Принимает значение true при открытии набора данных, при переключении набора данных в состояние DsEdit или при передаче фокуса другому компоненту на форме |
Содержит список наименований полей таблицы,
Таблица 16.2 (окончание)| Свойство |
Описание |
| IndexFieldNames |
Содержит список наименований полей таблицы, по которым будет производиться сортировка набора данных. Имена полей разделяются точкой с запятой. Имеет тип String |
| IndexName |
Содержит имя индекса, по которому будет произведена сортировка набора данных. Имеет тип String |
| MasterSource |
Содержит имя главного источника данных при организации связи таблиц главная-подчиненная (master-detail). Имеет тип TdataSource |
| MasterFields |
Содержит имена полей, по которым осуществляется связь между главной и подчиненной таблицами. Имеет тип String |
| ObjectView |
Включает или выключает иерархическое представление для вложенных полей. Имеет тип Boolean |
| PacKetRecord |
Определяет количество записей в одном пакете данных. Имеет тип Integer. Возможные значения: -1 — все записи; >0 — конкретное число записей; 0 — в пакет будут включаться только мета-данные |
| Params |
Определяет список параметров набора данных. Имеет тип Tparams |
| ProviderName |
Определяет имя зарегистрированного провайдера для сервера. Имеет тип String |
| Readonly |
Определяет способ доступа к записям. Имеет тип Boolean. Если значение свойства — true, то данные доступны только для чтения. Если значение — false, то можно изменять существующие данные и записывать новые |
| RemoteServer |
Определяет компонент, с помощью которого клиентский набор данных соединяется с сервером. Имеет тип TcustomRemoteServer |
| StoreDefs |
Определяет, будут ли храниться определения полей и индексов в клиентском наборе данных. Имеет тип Boolean |
| Tag |
Свойство, которое может использоваться по усмотрению программиста, и у него нет специального назначения. Свойство имеет тип Integer |
Свойства компонента TClientDataSet
Таблица 16.2. Свойства компонента TClientDataSet| Свойство |
Описание |
| Active |
Определяет, является ли набор данных активным. Свойство имеет тип Boolean |
| Aggregates |
Содержит список доступных агрегатов. Имеет тип Taggregates |
| AggregatesActive |
Определяет, нужно ли производить вычисления агрегатов. Имеет тип Boolean |
| AutoCalcFields |
Определяет, нужно ли генерировать событие OnCalcFields и обновлять содержимое полей. Имеет тип Boolean. Принимает значение true при открытии набора данных, при переключении набора данных в состояние DsEdit или при передаче фокуса другому компоненту на форме |
| CommandText |
Содержит текст SQL-запроса. Имеет тип String. При установленном значении свойства FileName это свойство игнорируется. Свойство игнорируется также и в случае, когда в свойстве Options сброшен флажок poAllowCommandText |
| ConnectionBroker |
Определяет брокера соединения с сервером. Имеет тип TconnectionBroker |
| Constraints |
Определяет накладываемые ограничения на значение на уровне одной записи. Имеет тип TConstraints |
| DataSetField |
Указывает на объект TDataSetField, управляющий вложенными наборами данных. Имеет тип TDataSetField |
| DisableStringTrim |
Определяет, нужно ли удалять лишние пробелы в конце строки при вставке ее в таблицу базы данных. Имеет тип Boolean |
| FetchOnDemand |
Определяет, должно ли приложение получать данные по мере необходимости. Имеет тип Boolean |
| FieldDefs |
Содержит список полей, определяющих набор данных. Имеет тип TfieldDefs |
| FileName |
Содержит имя файла, в котором хранятся кэшируемые данные. Имеет тип String |
| Filter |
Задает фильтр, по которому будут выбираться данные из таблицы. Имеет тип String |
| Filtered |
Определяет, включено или выключено свойство Filter. Имеет тип Boolean |
| FilterOptions |
Определяет параметры фильтрации записей таблицы. Имеет тип TfilterOptions |
| IndexDefs |
Содержит определения индексов. Имеет тип т IndexDefs |
Свойства компонента TDataSetProvider
Таблица 16.3. Свойства компонента TDataSetProvider| Свойство |
Описание |
| Constraints |
Определяет накладываемые ограничения на значение на уровне одной записи. Имеет тип Tconstraints |
| DataSet |
Определяет набор данных, с которым взаимосвязан компонент TdataSetProvider. Имеет тип TdataSet |
| Exported |
Позволяет приложению осуществлять вызовы провайдера, если он расположен на сервере. Имеет тип Boolean |
| Name |
Определяет имя компонента TdataSetProvider |
| Options |
Содержит параметры работы с данными. Имеет тип TproviderOptions |
| ResolveToDataSet |
Определяет, будут ли автоматически применяться изменения в наборе данных или на сервере базы данных. Имеет тип Воolean |
| Tag |
Свойство, которое может использоваться по усмотрению программиста и у него нет специального назначения. Свойство имеет тип Integer |
| UpdateMode |
Определяет способ поиска записи, которую необходимо обновить. Имеет тип TUpdateMode. Может принимать значения: UpWhereAll — искать по всем полям; UpWhereChanged — искать по ключевым и измененным полям; UpWhereKeyOnly — искать только по ключевым полям |
Вперед
Содержит имя конфигурации. Имеет тип
Таблица 16.4 (окончание)| Свойство | Описание |
| ConnectionName | Содержит имя конфигурации. Имеет тип String. Является аналогом свойства AliasName в Delphi |
| DriverName | Содержит имя драйвера, необходимого для соединения с базой данных (DB2, Interbase, Oracle или My SQL). Имеет тип String. Данное свойство устанавливается автоматически после задания значения свойства ConnectionName |
| KeepConnection | Определяет, нужно ли поддерживать соединение с сервером базы данных, если в приложении нет активных наборов данных. Имеет тип Boolean. Если связь необходимо поддерживать, установите это свойство в true, иначе — false |
| LibraryName | Содержит имя библиотеки, в которой находится необходимый драйвер для связи с базой данных. Свойство имеет тип String |
| LoadParamsOnConnect | Определяет, нужно ли загружать параметры соединения перед его установкой во время работы приложения. Имеет тип Boolean |
| LoginPrompt | Определяет, нужно ли при установке соединения запрашивать имя пользователя и пароль. Имеет тип Boolean. Если true, то нужно, иначе — не нужно |
| Name | В этом свойстве вы можете указать имя компонента TSQLConriection. Имеет тип TcomponentName |
| Params | Устанавливает параметры соединения. Имеет тип TStrings |
| TableScope | Устанавливает параметры видимости таблиц базы данных. Имеет тип TTableScopes и может принимать следующие значения: TsSynonym— видимые синонимы; TsSysTable — видимые системные таблицы; ТsТаblе — видимые таблицы пользователей; TsView — видимые представления |
| VeridorLib | Указывает имя библиотеки клиентской части базы данных. Имеет тип String |
Свойства компонента TSQLConnection
Таблица 16.4. Свойства компонента TSQLConnection| Свойство | Описание |
| Connected | Определяет, установлена ли связь с базой данных. Данное свойство имеет тип Boolean. Если связь установлена, свойство имеет значение true, иначе — false |
Свойства компонента TSQLDataSet
Таблица 16.5. Свойства компонента TSQLDataSet| Свойство | Описание |
| Active | Определяет, является ли набор данных активным. Только активный набор данных может работать с записями таблиц. Свойство имеет тип Boolean. Если значение true — набор данных активен, иначе — неактивен |
| CommandText | Содержит текст запроса SQL на выполнение каких-либо действий о данными. Имеет тип String |
| CommandType | Определяет тип набора данных. Значение свойства имеет тип TSQLCommandType. Свойство может принимать следующие значения: CtQuery — обычный SQL-запрос; CtTable - таблица целиком, при этом автоматически будет сгенерирован запрос на выборку всех записей таблицы по всем полям; CtStoredProc — процедура, хранимая на сервере базы данных |
| DataSource | Указывает источник данных для этого набора данных. Имеет тип TdataSource |
| MaxBlobSize | Определяет максимальный размер BLOB-полей. Имеет тип Integer |
| ObjectView | Включает или выключает иерархические представления для вложенных полей. Имеет тип Boolean |
| ParamCheck | Указывает, нужно ли обновлять список параметров при изменении текста запроса (свойство CommandText). Имеет тип Boolean |
| Params | Определяет список параметров запроса. Имеет тип TParams |
| SortFieldNames | Содержит список наименований полей таблицы, по которым будет производиться сортировка набора данных. Имена полей разделяются точкой с запятой. Имеет тип String. Свойство активно только при установленном типе набора данных CtTable в свойстве CommandType |
| SQLConnection | Содержит имя компонента TSQLConnection, с помощью которого будет осуществляться соединение с базой данных. Имеет тип TSQLConnection |
| Tag | Свойство, которое может использоваться по усмотрению программиста, и у него нет специального назначения. Многие компоненты содержат это свойство. Свойство имеет тип Integer |
Свойства компонента TSQLQuery
Таблица 16.6. Свойства компонента TSQLQuery| Свойство | Описание |
| Active | Определяет, является ли запрос активным. Только активный запрос может работать с записями таблиц. Свойство имеет тип Boolean. Если значение true — запрос активен, иначе — неактивен |
| DataSource | Указывает источник данных для этого набора данных. Имеет тип TdataSource . |
| MaxBlobSize | Определяет максимальный размер BLOB-полей. Имеет тип Integer |
| ObjectView | Включает или выключает иерархические представления для вложенных полей. Имеет тип Boolean |
| ParamCkeck | Указывает, нужно ли обновлять список параметров при изменении текста запроса (свойство CommandText). Имеет тип Boolean |
| Params | Определяет список параметров запроса. Имеет тип TParams |
| SQL | В этом свойстве указывается текст SQL-запроса. Имеет тип Tstrings |
| SQLConnection | Содержит имя компонента TSQLConnection, с помощью которого будет осуществляться соединение с базой данных. Имеет тип TSQLConnection |
| Tag | Свойство, которое может использоваться по усмотрению программиста, и у него нет специального назначения. Свойство имеет тип Integer |
Определяет список параметров процедуры. Имеет
Таблица 16.7 (окончание)| Свойство | Описание |
| Params | Определяет список параметров процедуры. Имеет тип Tparams |
| SQLConnection | Содержит имя компонента TSQLConnection, с помощью которого будет осуществляться соединение с базой данных. Имеет тип TSQLConnection |
| Tag | Свойство, которое может использоваться по усмотрению программиста, и у него нет специального назначения. Свойство имеет тип Integer |
Свойства компонента TSQLStoredProc
Таблица 16.7. Свойства компонента TSQLStoredProc| Свойство | Описание |
| Active | Определяет, является ли процедура, хранимая на сервере, активной. Имеет тип Boolean |
| MaxBlobSize | Определяет максимальный размер BLOB-полей. Имеет тип Integer |
| ObjectView | Включает или выключает иерархические представления для вложенных полей. Имеет тип Boolean |
| ParamCheck | Указывает, нужно ли обновлять список параметров при изменении процедуры. Имеет тип Boolean |
Свойства компонента TSQLTable
Таблица 16.8. Свойства компонента TSQLTable| Свойство | Описание |
| Active | Определяет, является ли таблица активной. Только активная таблица может работать с записями. Свойство имеет тип Boolean |
| IndexFieldNames | Содержит список наименований полей таблицы, по которым будет производиться сортировка набора данных. Имена полей разделяются точкой с запятой. Имеет тип String |
| IndexName | Содержит имя индекса, по которому будет произведена сортировка набора данных. Имеет тип String |
| MasterSource | Содержит имя главного источника данных при организации связи таблиц главная-подчиненная (master-detail). Имеет тип TdataSource |
| MasterFields | Содержит имена полей, по которым осуществляется связь между главной и подчиненной таблицами. Имеет тип String |
| MaxBlobSize | Определяет максимальный размер BLOB-полей. Имеет тип Integer |
| ObjectView | Включает или выключает иерархические представления для вложенных полей. Имеет тип Boolean |
| SQLConnection | Содержит имя компонента TSQLConnection, с помощью которого будет осуществляться соединение с базой данных. Имеет тип TSQLGonnection |
| TableName | Содержит имя таблицы базы данных, с которой будет производиться работа. Имеет тип String |
| Tag | Свойство, которое может использоваться по усмотрению программиста, и у него нет специального назначения. Свой- ство имеет тип Integer |
Свойства компонента TSQLMonitor
Таблица 16.9. Свойства компонента TSQLMonitor| Свойство | Описание |
| Active | Определяет, является ли монитор активным. Свойство имеет тип Boolean |
| AutoSave | Определяет, будет ли производиться автоматическое сохранение журнала событий в файл, указанный в свойстве FileName данного компонента. Имеет тип Boolean |
| FileName | Определяет имя файла, в который будет производиться запись журнала событий. Имеет тип String |
| SQLConnection | Содержит имя компонента TSQLConnection, с помощью которого будет осуществляться соединение с базой данных. Имеет тип TSQLConnection |
| Tag | Свойство, которое может использоваться по усмотрению программиста, и у него нет специального назначения. Свойство имеет тип Integer |
| TraceList | Данное свойство содержит журнал событий. Имеет тип Tstrings |
Основные операторы определения данных
Таблица 17.1. Основные операторы определения данных| Оператор |
Описание |
| CREATE TABLE |
Предназначен для создания таблицы базы данных |
| ALTER TABLE |
Удаляет таблицу |
| DROP TABLE |
Изменяет структуру таблицы |
| CREATE INDEX |
Создает индекс |
| DROP INDEX |
Удаляет индекс |
| CREATE VIEW |
Создает представление |
| DROP VIEW |
Удаляет представление |
Основные операторы управления данными
Таблица 17.2. Основные операторы управления данными| Оператор |
Описание |
| GRAND |
Назначает привилегии пользователям |
| REVOKE |
Удаляет привилегии пользователей |
Основные операторы манипулирования данными
Таблица 17.3. Основные операторы манипулирования данными| Оператор |
Описание |
| SELECT |
Предназначен для выборки записей по определенному формату |
| UPDATE |
Предназначен для изменения и обновления записей |
| INSERT |
Вставляет новые записи в таблицу |
| DELETE |
Удаляет записи из таблицы |
Примечание
Обратите внимание на тот факт, что проверка синтаксиса запроса происходит только во время работы приложения. Компилятор Kylix не обрабатывает SQL-запросы во время разработки приложения.
Результатом выполнения запроса обычно является набор данных, который называется результирующим набором данных.
Осталось отметить, что регистр букв команд SQL-запросов не влияет на их выполнение. Мы для наглядности будем применять заглавные буквы для операторов языка SQL. Точка с запятой также не обязательна в конце каждой SQL-команды. Элементы списков, такие как имена таблиц и полей, обязательно разделяются запятыми. Имена таблиц и полей заключаются в одинарные или двойные кавычки, например 'Number', "Table 1". В случае если имя не содержит пробелов и других специальных символов, его можно не заключать в кавычки.
Вперед
Основные статистические функции
Таблица 17.4. Основные статистические функции| Функция |
Описание |
| AVG ( ) |
Получение среднего значения |
| COUNT ( ) |
Определяет количество значений |
| COUNT ( * ) |
Определяет количество ненулевых значений |
| MAX ( ) |
Максимальное значение |
| MIN( ) |
Минимальное значение |
| SUM ( ) |
Сумма значений |
S FROM N1 TO
Таблица 17.5 (окончание)| Функция |
Описание |
| SUBSTRING ( S FROM N1 TO N2) |
Выделяет из строки S подстроку, начиная с символа N1 и заканчивая символом N2 |
| TRIM(S) |
Удаляет в начале и конце строки S лишние пробелы |
| UPPER (S) |
Преобразует символы строки S в символы верхнего регистра |
Назад Вперед
Основные строковые функции
Таблица 17.5. Основные строковые функции| Функция |
Описание |
| | | |
Слияние (конкатенация) двух строк |
| САSТ (<Выражение> AS <Тип>) |
Приводит выражение <Выражение> к типу <Тип> |
| LOWER ( S ) |
Преобразует символы строки S в символы нижнего регистра |
Определения полей
Таблица 18.1. Определения полей| Имя поля | Описание | Тип данных | Размер |
| ID | счетчик | ftAutoInc | 0 |
| Name | имя клиента | FtString | 50 |
Поля определяемые в свойстве ChlidDefs
Таблица 18.2. Поля, определяемые в свойстве ChlidDefs| Имя поля | Описание | Тип данных | Размер |
| ID | счетчик | FtAutoInс | 0 |
| OrderName | описание заказа | FtString | 20 |
| Price | цена заказа | FtCurrency | 0 |
Базовые классы CLX
Таблица 19.1. Базовые классы CLX| Класс |
Возможности класса |
| TObject |
Классы, предком которых является данный класс, не являются компонентами. Данный класс применяется при создании объектов, которые обычно являются предками для других компонентов |
| TCoraponent |
Применяется для создания невизуальных компонентов |
| TGraphicControl |
Применяется для создания не оконных компонентов, т. е. компонентов без дескриптора окна. Потомки данного класса размещаются в клиентской области своих родительских компонентов и не требуют системных ресурсов |
| TWidgetControl |
Применяется для создания компонентов, имеющих дескриптор окна. Данные компоненты являются компонентами оконного типа и могут содержать в себе другие компоненты |
| TCustomControl |
Данный класс является потомком TWinControl и дополняет его областью вывода (канвой). В этот класс добавлен метод Paint. Рекомендуется использовать такой класс для создания пользовательских оконных компонентов |
Библиотека визуальных компонентов содержит несколько
Таблица 19.1 (окончание)| Класс |
Возможности класса |
| TCustomClassName |
Библиотека визуальных компонентов содержит несколько классов, у которых не все свойства объявлены как published, т. е. доступны из других модулей, но на основе данных классов можно создавать классы-потомки, в которых можно объявлять данные свойства. Таким образом, разработчик может создать несколько идентичных классов на основе одного класса ClassName и в каждом из этих классов определять необходимые свойства из набора предопределенных свойств |
| TComponentName |
Позволяет создавать компоненты-потомки, предками которых являются обычные компоненты или классы CLX Kylix. Таким образом, если перед разработчиком стоит задача расширить возможности какого-либо компонента Kylix, можно использовать данный класс |
Назад Вперед
Размещение методов компонента в различных секциях
Таблица 19.2. Размещение методов компонента в различных секциях| Секция |
Размещаемые методы |
| Private |
В данной секции лучше всего размещать те методы, которые не могут изменяться в компонентах-потомках. Данные методы не доступны вне данного компонента |
| Protected |
В этой секции размещают методы, которые будут доступны для изменения в компонентах-потомках |
| Public |
Данная секция предназначена для размещения методов, которые доступны любому пользователю компонента. Доступ полный во время работы приложения, но не во время разработки, т. е. данные методы недоступны в окне инспектора объектов |
| Published |
В этой секции размещаются свойства компонента, которые доступны во время разработки приложения в окне инспектора объектов |
Назад Вперед
Целочисленные типы данных
Таблица 2.1. Целочисленные типы данных| Тип данных |
Диапазон значений |
Формат чисел в памяти |
| Integer |
-2 147 483 648-2 147 483 647 |
32 бита со знаком |
| Cardinal |
0-4 294 967 295 |
32 бита без знака |
| Shortint |
-128-127 |
8 битов со знаком |
| Smallint |
-32 768-32 767 |
16 битов со знаком |
| Longint |
-2 147 483 648-2 147 483 647 |
32 бита со знаком |
| Int64 |
-2^63-2^63-1 |
64 бита со знаком |
| Byte |
0-255 |
8 битов без знака |
| Word |
0-65 535 |
16 битов без знака |
| Longword |
0-4 294 967 295 |
32 бита без знака |
Вещественные типы данных
Наиболее используемым вещественным типом является тип Real. Переменные этого типа могут содержать любые непорядковые числовые значения со знаком. Различия вещественных типов данных заключаются в основном в отличии числа знаков после запятой (точности). Табл. 2.2 содержит перечень вещественных типов данных языка Object Pascal.
Вещественные типы данных
Таблица 2.2. Вещественные типы данных| Тип данных |
Диапазон значений |
Точность (знаков) |
Количество байт |
| Real48 |
2,9x10^- 39-1,7х10^38 |
11-12 |
6 |
| Single |
1,5х10^- 45-3,4х10^38 |
7-8 |
4 |
| Double |
5,0x10^- 324-1,7х10^308 |
15-16 |
8 |
| Extended |
3,6х10^- 4951-1,1х10^4932 |
19-20 |
10 |
| Comp |
-2^63+1- 2^63-1 |
19-20 |
8 |
| Currency |
-922 337 203 685 477,5808 - 922 337 203 685 477,5807 |
19-20 |
8 |
| Real |
5,0x10^- 324 -1,7х10^308 |
15-16 |
8 |
Шестибайтовый тип Real 48 применялся в ранних версиях языка Object Pascal как Real. Если вы перекомпилируете код, который использовал ранний шестибайтовый тип Real, вы можете для удобства изменить его на Real 48. Кроме того, вы можете применить директиву компилятора {$REALCOMPATIBILITY ON} для автоматического перевода типа Real в шестибайтовый.
О вышеперечисленных типах можно еще сказать следующее:
Для хранения логических значений Object Pascal использует тип данных Boolean. Переменная логического типа занимает один байт памяти и может принимать два значения: 1 или 0. Значение 1 соответствует значению True (истина). Значение 0 соответствует значению False (ложь). Из-за того, что данный тип не совместим с подобными логическими типами, применяемыми в других языках программирования, Object Pascal имеет три дополнительных логических типа:
Основным символьным типом является Сhar.
Таблица 2.3 (окончание)| Тип данных Boolean |
Типы данных ByteBool, WordBool, LongBool |
| Ord(True) = 1 |
Ord(True) <> 0 |
| Succ (False) = True |
Succ (False) = True |
| Pred(True) = False |
Pred (False) = True |
Основным символьным типом является Сhar. Данный тип используется для хранения символа из таблицы ASCII. Каждый символ в данной таблице представлен числовым значением от 0 до 255, поэтому переменная такого типа занимает в памяти всего 1 байт.
Кроме типа Char, язык Object Pascal имеет еще два символьных типа:
Отличия результатов операций над логическими типами
Таблица 2.3. Отличия результатов операций над логическими типами| Тип данных Boolean |
Типы данных ByteBool, WordBool,LongBool |
| False < True |
False <> True |
| Ord(False) =0 |
Ord (False) = 0 |
Строковые типы данных
Таблица 2.4. Строковые типы данных| Тип данных |
Максимальная длина |
Занимаемая память |
Используется для: |
| ShortString |
255 символов |
2—256 байт |
совместимости с предыдущими версиями языка |
| AnsiString |
2^31 символов |
4 байт— 2 Гбайт |
символов ANSI, строк переменной длины |
| WideString |
2^30 символов |
4 байт— 2 Гбайт |
символов Unicode, COM-серверов и интерфейсов |
Строки, по своему определению, являются массивами символов. Поэтому для обращения к любому символу строки достаточно указать название строковой переменной и номер символа (как при обращении к элементу массива):
var
A: Char;
MyString: String;
begin
A:=MyString[10];
end;
Кроме перечисленных в табл. 2.4 строковых типов данных, имеется еще один тип PChar, который является строкой с нулевым окончанием, т. е. в конце строки стоит код 0. Длина строки типа PChar может быть любой, но, естественно, не более чем объем памяти компьютера.
Множества
Множество — это набор данных, относящихся к одному и тому же простому типу. Значения входящих в множество элементов ограничены только своим простым типом. Количество элементов множества не должно превышать 256. Описание множественного типа можно осуществить так:
set of Тип данных;
Рассмотрим способ задания множества целых чисел путем определения промежутка чисел:
type
TSomeInts = 1..250;
TIntSet = set of TSomeInts;
В данном примере мы создаем тип множества TIntSet, который содержит набор целых чисел от 1 до 250. Перед этим мы создали свой тип TSomeInts, который является частью типа integer. Мы можем создать это же множество другим способом:
type TIntSet = set of 1..250;
В общем случае, элементы множества задаются с помощью простого их перечисления в квадратных скобках через запятую. Например, если ранее была записана представленная выше строка определения типа TIntSet, можно задать множества Set1 и Set2:
var Set1, Set2: TIntSet ;
. . .
Set1 := [1, 3, 5, 7, 9]; Set2 := [2, 4, 6, 8, 10]
Кроме того, вы можете задавать множества непосредственно в объявлении переменных с помощью конструкции set of:
var MySet: set of ' a ' . . ' z ' ;
...
MySet := [ ' a ' , ' b ' , ' c ' ] ;
В табл. 2.5 приведен список операций, которые допустимы над множествами.
если множества не являются эквивалентными,
Таблица 2.5 (окончание)| Обозначение |
Название |
Тип результата |
Результат |
Пример |
| = |
Эквивалентность |
Логический |
Истина, если множества эквивалентны, иначе — ложь |
Set1 = Set2 |
| о |
Неравенство |
Логический |
Истина, если множества не являются эквивалентными, иначе — ложь |
Set1 <> Set2 |
| <= |
Подмножество |
Логический |
Истина, если первое множество входит во второе, |
Set1 <= Set2 |
| >= |
Расширенный набор |
Логический |
ложь — в противном случае Истина, если первое множество включает в себя второе, иначе — ложь |
Set1 >= Set2 |
| In |
Членство |
Логический |
Истина, если данный элемент входит в множество, иначе — ложь |
A in Set1 |
Массив — это упорядоченная совокупность элементов одного и того же типа. Элементы массива имеют уникальные индексы. Массив обязательно имеет имя.
Так как элементы массива имеют индексы, массивы могут содержать одинаковые значения неоднократно. Каждый элемент массива однозначно определяется именем массива и собственным индексом.
Массивы подразделяются на статические и динамические.
Статический массив — это массив, размеры которого задаются при объявлении, т. е. это массив с четкими границами индексов.
Статический массив определяется следующей конструкцией языка Object Pascal:
array[indexTypel , . . . , indexTypen] of baseType;
Каждый indexType внутри квадратных скобок является порядковым типом, диапазон которого не превышает 2 Гбайт. Диапазон каждого indexType ограничивает число элементов, входящих в массив.
Примечание
Хотя, по определению, индексом массива может быть любой порядковый тип, на практике обычно применяется тип Integer.
Для обращения к любому элементу массива нужно указать сначала имя этого массива, а затем — в квадратных скобках номер (индекс) элемента:
МуАггау[10];
Динамический массив — это массив, в котором при объявлении указывается только тип его элементов. Размеры динамических массивов изменяются в ходе выполнения программы.
Динамический массив задается с помощью нижеприведенной конструкции:
array of baseType;
Язык Object Pascal поддерживает многомерные массивы. Самым простым является одномерный массив. Его можно представить как пронумерованную строку переменных (Рисунок 2.1). Приведем пример создания простого одномерного массива.
Операции допустимые над множествами
Таблица 2.5. Операции, допустимые над множествами| Обозначение |
Название |
Тип результата |
Результат |
Пример |
| + |
Объединение множеств |
Множество |
Неповторяющиеся элементы первого и второго множества |
Set1 + Set2 |
| - |
Разность множеств |
Множество |
Элементы из первого множества, которые отсутствуют во втором |
Set1 - Set2 |
| * |
Пересечение множеств |
Множество |
Элементы, которые есть как в первом, так и во втором множестве |
Set1 * Set2 |
Типы файлов пакетов
Таблица 20.1. Типы файлов пакетов| Расширение файла |
Содержание файла |
| dpk |
Исходный файл пакета, содержащий список модулей данного пакета. Он создается при запуске редактора пакета (по своему назначению и функциональности похож на файл проекта Kylix .dpr) |
| dcp |
Двоичный файл, содержащий заголовок пакета и описание всех файлов dcp пакета, включая всю символьную информацию, которая требуется для компилятора. Всего один файл данного типа создается для одного пакета |
| dpu |
Двоичный файл, содержащий текст модуля, находящийся в пакете. Для каждого модуля создается один файл dpu |
| so |
Файл пакета, используемого во время работы приложения. Этот файл является аналогом библиотеки разделяемых объектов (so) Linux, которая содержит специфичные характеристики среды Kylix. Если это пакет времени выполнения, то вы должны передавать данный пакет пользователю вместе с файлом приложения. В случае, если это пакет разработки, он должен распространяться среди программистов, использующих его для написания приложений |
Назад Вперед
Основные runtime пакеты Kylix
Таблица 20.2. Основные runtime пакеты Kylix| Имя файла пакета |
Модули, входящие в пакет |
| bplclx.so.6 |
Classes, Consts, Contnrs, IniFiles, MaskUtils, QactnList, QButtons, Qclipbrd, QcomCtrls, QcomStrs, QConsts, Qcontrols, QDialogs, QextCtrls, QForms, Qgraphics, QGrids, QImgList, QMask, QMenus, Qsearch, QStdActns, QStdCtrls, QStyle, QTypes, SyncObjs, TypInfo |
| bpldataclx. so. 6 |
DB, DBClient, DBCommon, DBConnAdmin, DBConsts, DBXpress, DSIntf, MidConst, Midas, Provider, QDBCtrls, QDBGrids, SqlConst, SqlExpr |
Основные designtime пакеты Kylix
Таблица 20.3. Основные design-time пакеты Kylix| Имя файла пакета |
Вкладки палитры компонентов |
| dclstd |
Standard, Additional, Common Controls, Dialogs |
| dcldbdesign |
Data Controls, dbExpress, Data Access |
| dclnet |
Internet |
| dclindy |
Indy Clients, Indy Servers, Indy Mlsc |
В дополнение ко всем рассмотренным выше пакетам вы можете устанавливать в IDE пакеты собственного производства, а также пакеты, созданные другими разработчиками. Пакет Kylix dclusr является стандартным контейнером для новых компонентов.
Назад Вперед
Директивы компилятора пакетов
Таблица 20.4. Директивы компилятора пакетов| Директива |
Применение |
| {$IMPLICITBUILD OFF} |
Служит для предотвращения перекомпиляции пакета. Применяется в тех случаях, когда пакет не изменяется |
| {$G-} или {IMPORTEDDATA OFF} |
Применяется для предотвращения размещения модуля внутри пакета. Данная директива размещается внутри модуля. Желательно, чтобы этот модуль был напрямую связан с приложением |
| { $WEAKPACKAGEUNIT ON} |
Когда в файле модуля встречается данная директива, компилятор опускает данный модуль из файла so и создает локальную копию модуля тогда, когда это необходимо (при вызове данного модуля из приложения или из пакета). Модуль, имеющий данную директиву, называется слабым пакетом (weakly packaged) |
| { $DENYPACKAGEUNIT ON } |
То же, что и { IMPORTEDDATA OFF} |
| {$DESIGNONLY ON} |
Компилирует пакет как пакет design-time |
| {$RUNONLY ON} |
Компилирует пакет как пакет runtime |
Слабый пакет применяется, когда пакет ссылается на отсутствующие библиотеки so. Данная директива используется очень редко. Она позволяет обрабатывать специфические ситуации. Например, есть два компонента (в разных пакетах), которые обращаются к одному и тому же интерфейсному модулю so. Если приложение будет использовать сразу оба компонента, это приведет к загрузке двух экземпляров so, при этом могут возникнуть конфликты инициализации и использования глобальных переменных.
Примечание
Обратите внимание, что когда вы поставляете откомпилированную версию приложения вместе со всеми необходимыми пакетами, вам следует учитывать, что должна совпадать версия пакета. То есть пакет, созданный в Kylix более новой версии, не будет работать вместе с приложением, созданным в Kylix старой версии.
Назад Вперед
Ключи для компиляции пакета из командной строки
Таблица 20.5. Ключи для компиляции пакета из командной строки| Ключ |
Назначение |
| -$G- |
Отключает создание ссылок на импортируемые данные. Использование этого ключа повышает эффективность доступа к памяти, но не позволяет компилировать пакеты, внутри которых имеются ссылки на переменные других пакетов |
| -LEpath |
Определяет каталог, в котором будет расположен файл пакета cppackage.so |
| -LNpath |
Определяет каталог, в котором будет расположен файл пакета package. dcp |
| -LUpackage |
За этим ключом перечисляются файлы использующихся пакетов |
| -Z |
Предотвращает в дальнейшем перекомпиляцию данного пакета |
Использование ключа -$G- предотвращает возможность использования пакета другими пакетами приложения.
Назад
Части в которые сгруппированы компоненты CLX
Таблица 21.1. Части, в которые сгруппированы компоненты CLX| Часть |
Описание |
| VisualCLX |
Межплатформенные графические компоненты и графика. Компоненты этой части могут различаться под Windows и Linux |
| DataCLX |
Клиентские компоненты для доступа к данным. Код этих компонентов одинаков для Linux и Windows |
| NetCLX |
Компоненты Интернета, включающие Apache DSO и CGI WebBroker. Они одинаковы для Linux и Windows |
| BaseCLX |
Библиотека времени выполнения, включающая модуль Classes . pas. Код одинаков для Linux и Windows |
TWinControl = TWidgetControl;
которые предназначены для упрощения использования компонентов разными приложениями. Класс TWidgetControl и все его потомки имеют свойство Handle, которое представляет собой ссылку на объект Qt, а также свойство Hooks, ссылающееся на механизм обработки событий.
Названия модулей и расположение отдельных классов в CLX отличаются от VCL. Вам придется самостоятельно модифицировать разделы uses для исключения модулей, которых нет в Куliх и смены имен на имена модулей Kylix.
Назад Вперед
Различие возможностей Delphi и Kytix
Таблица 21.2. Различие возможностей Delphi и Kytix| Delphi/Windows возможность |
Kylix/Llnux возможность |
| Вызовы Windows API |
Методы CLX, вызовы Qt, вызовы libc или вызовы других системных библиотек |
| Компоненты СОМ (включая ActiveX) |
Не поддерживаются |
| Компоненты ADO |
Компоненты доступа к базам данных |
| Сообщения Windows |
События Qt |
| Winsock |
Сокеты BSD |
| Messaging Application Programming Interface (MAPI), включая стандартную библиотеку функций сообщений Windows |
SMTP/POP3 позволяют вам отсылать, получать и сохранять сообщения e-mail |
| Компоненты наследования (компоненты, расположенные на вкладке Win 3.1 палитры компонентов) |
Не поддерживаются |
В Kylix имеются два модуля,
Таблица 21.3 (окончание)| Модуль Delphi | Модуль Kylix |
| Grids | Qgrids |
| HelpIntfs | HelpIntfs |
| ImgList | QimgList |
| IniFiles | IniFiles |
| Mask | Qmask |
| MaskUtils | MaskUtils |
| Masks | Masks |
| Math | Math |
| Menus | Qmenus |
| Midas | Midas |
| MidConst | MidConst |
| Printers | QPrinters |
| Provider | Provider |
| Qt | Qt |
| Search | Qsearch |
| Sockets | Sockets |
| StdActns | QStdActns |
| StdCtrls | QStdCtrls |
| SqlConst | SqlConst |
| SqlExpr | SqlExpr |
| SqlTimSt | SqlTimSt |
| StdConvs | StdConvs |
| SyncObjs | SyncObjs |
| SysConst | SysConst |
| SysInit | SysInit |
| System | System |
| SysUtils | SysUtils |
| Types | Types и QTypes |
| TypInfo | TypInfo |
| VarCmplx | VarCmplx |
| Variants | Variants |
| VarUtils | VarUtils |
Совместимые модули Delphi и Kylix
Таблица 21.3. Совместимые модули Delphi и Kylix| Модуль Delphi | Модуль Kylix |
| ActnList | QactnList |
| Buttons | Qbuttons |
| CheckLst | QcheckLst |
| Classes | Classes |
| Clipbrd | Qclipbrd |
| ComCtrls | QcomCtrls |
| Consts | Consts, QConsts и RTLConsts |
| Contnrs | Contnrs |
| Controls | Qcontrols |
| ConvUtils | ConvUtils |
| DateUtils | DateUtils |
| DB | DB |
| DBActns | QDBActns |
| DBClient | DBClient |
| DBCommon | DBCommon |
| DBConnAdmin | DBConnAdmin |
| DBConsts | DBConsts |
| DBCtrls | QDBCtrls |
| DBGrids | QDBGrids |
| DBLocal | DBLocal |
| DBLocalS | DBLocalS |
| DBLogDlg | DBLogDlg |
| DBXpress | DBXpress |
| Dialogs | Qdialpgs |
| DSIntf | DSIntf |
| ExtCtrls | QExtCtrls |
| FMTBCD | FMTBCD |
| Forms | QForms |
| Craphicis | QGraphics |
Модули VCL не поддерживаемые средой Kylix
Таблица 21.4. Модули VCL, не поддерживаемые средой Kylix| Модуль VCL | Причина, по которой он не поддерживается в Kylix |
| ADOConst | Нет ADO |
| ADODB | Нет ADO |
| AppEvnts | Нет объекта TapplicationEvent |
| AxCtrls | Нет СОМ |
| BdeConst | Нет ВDЕ |
| ComStrs | Нет СОМ |
| CorbaCon | Нет Corba |
| CorbaStd | Нет Соrbа |
| CorbaVCL | Нет Сorbа |
| CtlPanel | Нет панели управления Windows |
| DataBkr | Может появиться в более поздних версиях |
| DBCGrids | Нет ВDЕ |
| DBExcept | Нет ВDЕ |
| DBInpReq | Нет ВDЕ |
| DBLookup | Устарело |
| DbOleCtl | Нет СОМ |
| DBPWDlg | Нет ВDЕ |
| DBTables | Нет ВDЕ |
| DdeMan | Нет DDE |
| DRTable | Нет ВDЕ |
| ExtDlgs | Нет графических диалогов |
| FileCtrl | Устарело |
| MConnect | Нет СОМ |
| Messages | Специфичная Windows-функция . |
| MidasCon | Устарело |
| MPlayer | Медиа-проигрыватель Windows |
| Mtsobj | Нет СОМ |
| MtsRdm | Нет СОМ |
по которой он не поддерживается
Таблица 21.4 (окончание)| Модуль VCL | Причина, по которой он не поддерживается в Kylix |
| Mtx | Нет COM |
| mxConsts | Нет COM |
| ObjBrkr | Может появиться в более поздних версиях |
| OleConstMay | Нет СОМ |
| OleCtnrs | Нет СОМ |
| OleCtrls | Нет СОМ |
| OLEDB | Нет СОМ |
| OleServer | Нет СОМ |
| Outline | Устарело |
| Registry | Специфичная для Windows поддержка системного реестра |
| ScktCnst | Заменено на Sockets |
| ScktComp | Заменено на Sockets |
| SConnect | Неподдерживаемый протокол связи |
| SvcMgr | Поддержка сервисов Windows NT |
| Tabnotbk | Устарело |
| Tabs | Устарело |
| ToolWin | Не поддерживается |
| VGLCom | Нет СОМ |
| WebConst | Константы Windows |
| Windows | Специфичные для Windows виртуальные коды клавиш |
Linux не использует расширения имен
Таблица 21.5 (окончание)| Отличие |
Описание |
| Расширения имен файлов |
Linux не использует расширения имен файлов для определения типов файлов или для ассоциаций файлов с приложениями |
| Права на файлы |
В Linux с файлами и каталогами сопоставлены права на чтение, запись и выполнение для владельца файлов, групп пользователей и отдельных пользователей. Например, -rwxr-xr-x обозначает "слева направо": • — тип файла (- — обычный файл, d — директорий, I — ссыпка); rwx— права для владельца файла (r — чтение, w — запись, х — запуск); r-х — права для группы пользователей (х — выполнение, r— чтение); r-х — права для всех остальных пользователей (чтение и выполнение). Пользователь может отменить все эти права. При использовании прав убедитесь, что приложение запущено пользователем, имеющим достаточные права |
| Утилита make |
Утилита фирмы Borland make не доступна в среде Linux. Вместо нее вы можете использовать собственную утилиту Linux GNU make |
| Многозадачность |
Linux полностью поддерживает многозадачность. Вы можете запустить несколько различных программ (называемых процессами Linux) одновременно. Вы можете запустить любой из процессов в фоновом режиме. Для этого используйте символ & после имени выполняемого файла |
| Пути к файлам |
Для указания пути к файлу в Linux используется прямой слэш 7", в то время как в DOS и Windows используется обратный слэш "V |
| Символические ссылки |
В Linux символические ссылки — это специальные файлы, которые указывают на другие файлы, расположенные на диске. Эти ссылки создаются с помощью команды ln (link). В Windows эквивалентом символических ссылок являются ярлыки рабочего стола |
Назад Вперед
Отличия Linux и Windows
Таблица 21.5. Отличия Linux и Windows| Отличие |
Описание |
| Чувствительность к регистру букв в именах файлов |
В Linux заглавные буквы не являются эквивалентом прописных букв. Таким образом, файлы Test.txt и файл test.txt — разные |
| Символ конца строки |
В Windows строки текста завершаются двумя байтами ASCII: 13 и 10 (перевод строки и переход на начало строки), в Linux — только одним переходом на начало строки. При переносе кода из Windows помните об этом отличии |
| Символ конца текстового файла |
В DOS и Windows символьное значение #26 (комбинация клавиш |
в Linux являются файлы скриптов
Таблица 21.5 (продолжение)| Отличие |
Описание |
| Пакетные файлы и файлы скриптов оболочки |
Эквивалентом пакетных bat-файлов Windows в Linux являются файлы скриптов оболочки. Файлы скриптов — это текстовые файлы, содержащие инструкции и команды. Такие файлы сохраняются и делаются выполняемыми с помощью команды chmod +x <имя файла скриптах>. Для выполнения этого файла достаточно набрать его имя и нажать |
| Подтверждение команды |
В DOS и Windows, если вы хотите удалить файл или папку, система запрашивает подтверждение "Вы уверены, что хотите удалить файл или папку?". Linux обычно не выдает такого запроса, а просто удаляет файл или папку. Поэтому будьте особенно внимательны при удалении файлов или папок |
| Обратная связь с командой |
Если команда Linux выполнена успешно, будет отображена командная строка без каких-либо сообщений |
| Ключи команд |
Linux использует дефис "-"для ключей команд и двойной дефис "--" — для множественных опций команды, в то время как DOS и Windows используют слэш "/" или дефис "*" |
| Файлы конфигурации |
В Windows сведения о конфигурации системы хранятся в системном реестре и в файлах, таких как autoexec.bat. В Linux файлы конфигурации созданы как скрытые файлы, имена которых начинаются с точки. Многие из них находятся в каталоге /etc и в вашем домашнем каталоге /home. Кроме того, для хранения системной информации Linux использует переменные среды, такие как LD_LIBRARY_PATH (путь поиска файлов библиотек), НОМЕ (ваш домашний каталог), TERM (тип терминала: xterm, vt100, console), SHELL (путь к файлам оболочки), USER (ваше имя для входа в систему), PATH (список путей к файлам программ). Эти переменные определяются в оболочке или в re-файлах, например bashrc |
| Динамически присоединяемые библиотеки |
В Linux используются файлы разделяемых объектов so, а в Windows — файлы динамически присоединяемых библиотек dll |
| Буква, обозначающая имя накопителя |
В Windows для указания накопителя используется буква, например А: для накопителя на гибких дисках. В Linux такие имена не используются. Об организации файловой системы Linux см. Приложение 3 |
| Исполняемые файлы |
В Linux исполняемые файлы не нуждаются в расширении. В Windows такие файлы должны иметь расширение ехе |
Методы для подмены системных сообщений Windows
Таблица 21.6. Методы для подмены системных сообщений Windows| Метод |
Описание |
| ChangeBounds |
Используется, когда компонент, относящийся к классу TwidgetControl, изменяет свой размер. Является приблизительным аналогом системных сообщений WM_SIZE и WM_MOVE в Windows |
| ChangeScale |
Вызывается автоматически при изменении размера оконного компонента. Используется для смены масштаба формы и всех ее оконных компонентов при смене разрешения экрана или размера шрифта. Так как этот метод изменяет значения свойств Top, Left, Width и Height у всех оконных компонентов, он изменяет положение компонентов и их дочерних элементов в зависимости от размеров |
| ColorChanged |
Вызывается в случае, когда цвет оконного компонента изменился |
| CursorChanged |
Вызывается, когда курсор (указатель мыши) изменяет свою форму |
| EnabledChanged |
Вызывается, когда приложение изменяет состояние активности окна или оконного компонента (то есть когда изменяется значение свойства Enabled) |
| FontChanged |
Приблизительный аналог системного сообщения WM_FONTCHANGE в Windows. Вызывается, когда изменя-ется набор шрифтов |
| PaletteChanged |
Вызывается в случае смены системной палитры. Является приблизительным аналогом WM_PALETTE CHANGED |
| ShowHintChanged |
Вызывается при показе и скрытии всплывающих подсказок (hints) |
| StyleChanged |
Вызывается при смене стиля окна или оконных элементов GUI. Является аналогом системного сообщения WM_STYLECHANGED в Windows |
| TabStopChanged |
Вызывается при смене порядка обхода компонентов по клавише табуляции <Таb> |
| VisibleChanged |
Вызывается при смене состояния видимости оконного компонента |
| WidgetDestroyed |
Вызывается при уничтожении окна |
Назад Вперед
Соответствие компонентов доступа к данным
Таблица 21.7. Соответствие компонентов доступа к данным| Компоненты InterBase Express |
Компоненты BDE |
Компоненты ADO |
Компоненты dbExpress |
| TIBDatabase |
Tdatabase |
TADOConnection |
TSQLConnection |
| TIBTable |
Ttable |
TADOTable |
TSQLTable |
| TIBQuery |
Tquery |
TADOQuery |
TSQLQuery |
| TIBStoredProc |
TstoredProc |
TADOStoredProc |
TSQLStoredProc |
| TIBDataSet |
|
TADODataSet |
TSQLDataSet |
Из-за этих недостатков многие приложения dbExpress не работают напрямую с наборами данных dbExpress. Чаще всего такие приложения соединяют наборы данных dbExpress с клиентскими наборами данных, которые размещают записи из таблиц базы данных в памяти и обеспечивают поддержку редактирования и перемещения по записям.
Примечание
При создании очень простых приложений вы можете воспользоваться компонентом TSQLClientDataSet вместо соединения набора данных dbExpress с клиентским. Но для большинства приложений рекомендуется использовать наборы данных dbExpress, соединенные с компонентом TClientDataSet, представляющим собой клиентский набор данных.
Отличия на уровне интерфейса пользователя
Как уже было сказано ранее, компоненты CLX, отображающие данные, разработаны таким образом, чтобы быть наиболее похожими на соответствующие компоненты Windows.
Главные различия на уровне интерфейса пользователя возникают из-за отличий способа предоставления данных между набором данных dbExpress и клиентским набором данных.
Если вы в своем приложении используете только набор данных dbExpress, то вы должны согласиться с фактом, что набор данных не поддерживает редактирование и обратное перемещение по записям. Так, например, вы должны удалить все элементы управления, которые позволяют пользователю перемещаться на предыдущую запись набора данных. Так как наборы данных dbExpress не заносят данные в буфер, вы не можете отобразить таблицу данных (наподобие TDBGrid). Вы можете отображать на экране только одну запись в данный момент времени.
Если вы связали набор данных dbExpress с клиентским набором данных, то элементы интерфейса пользователя, связанные с редактированием и перемещением по записям, должны работать. Все, что вам нужно в этом случае — это переключить их на клиентский набор данных. Главной проблемой будет только вопрос обновления данных, записываемых в базу данных. По умолчанию большинство наборов данных в Windows записывают обновленные данные на сервер базы данных автоматически, после их пересылки (например, когда пользователь перемещается на другую запись таблицы). С другой стороны, клиентские наборы данных всегда кэшируют все обновления данных в памяти. Для того чтобы успешно разрешить эту проблему, прочитайте разд. "Обновление данных в приложениях dbExpress", который представлен далее в этой главе.
Перенос приложений баз данных в Linux
Перенос готового приложения базы данных на драйверы dbExpress позволит вам создать межплатформенное приложение, которое будет работать как под управлением Windows, так и под Linux. Из-за того, что dbExpress использует другую технологию, вам придется произвести некоторые изменения в приложении. Трудность переноса приложения из Windows в Linux зависит от типа используемой в приложении технологии. Наиболее трудными для переноса являются те приложения, которые применяют специфичные для Windows технологии, такие как ADO. Наиболее простыми для переноса являются приложения, использующие технологию Delphi для работы с базами данных.
Осуществите восемь следующих шагов для переноса приложения из Windows в Linux:
1. Рассмотрите, где располагается база данных. Технология dbExpress обеспечивает драйверы для работы с базами данных Oracle, Interbase, DB2 и MySQL. Следовательно, данные должны находиться на одном из этих SQL-серверов. Если вы использовали другие серверы баз данных, вам придется преобразовать данные к одному из поддерживаемых типов. Для этого, если у вас есть Delphi 5 версии Enterprise, вы можете воспользоваться утилитой Data Pump, которая поможет преобразовать формат локальных данных таких платформ, как Paradox, dBase и FoxPro в один из поддерживаемых. (Для подробной инструкции работы с утилитой смотрите файл помощи datapump.hlp в каталоге Program Files\Common Files\Borland\Shared\BDE в Windows).
2. Если у вас в приложении формы, содержащие интерфейс пользователя, не изолированы от модулей данных, которые включают в себя компоненты наборов данных и компоненты, обеспечивающие соединение с сервером базы данных, вы можете захотеть их изолировать, прежде чем продолжить перенос приложения из одной операционной системы в другую. В этом случае вам нужно изолировать часть приложения, содержащую модули данных от интерфейса пользователя. Затем формы интерфейса пользователя можно перенести в Linux так же, как и любые обычные формы.
Дальнейшие шаги подразумевают, что вы изолировали компоненты для работы с данными в отдельные модули данных.
3. Создайте новый модуль данных для хранения компонентов CLX, предназначенных для работы с данными.
4. Для каждого набора данных оригинального приложения добавьте отдельный набор данных dbExpress, компонент TDataSetProvider и компонент TClientDataSet. Дайте этим компонентам понятные имена. Установите свойство ProviderName компонента TClientDataSet аналогично имени компонента TdataSetProvider и свойство DataSet компонента TDataSetProvider в dbExpress. Смените свойство DataSet во всех компонентах для работы с данными, которые ссылались на оригинальный набор данных, так, чтобы они ссылались на клиентский набор данных.
5. Установите свойства нового набора данных в соответствии с оригинальным набором данных:
ствa StoredProcName или ProcedureName оригинального набора данных, а свойство Params компонента TSQLStoredProc равным значению свойства Params или Parameters оригинального набора данных.
в наборе данных BDE).
7. Для каждого набора данных dbExpress, которые созданы в четвертом шаге, установите их свойства SQLConnection в значение компонентов TSQLConnection, соответствующих нужной базе данных.
8. Для каждого компонента TSQLConnection определите информацию, необходимую для установки связи с базой данных. Для этого щелкните дважды на компоненте TSQLConnection, после чего появится редактор соединения (Connection Editor), и установите нужные значения параметров.
Обновление данных в приложениях dbExpress
Приложения dbExpress используют клиентские наборы данных для обеспечения функций редактирования данных. Когда вы размещаете отредактированные данные в клиентском наборе данных, изменения записываются в память и не передаются автоматически на сервер базы данных. Если оригинальное Windows-приложение также использовало кэширование данных в памяти, вам не потребуется вносить какие-либо изменения в приложение для Linux.
Если оригинальное приложение не кэшировало данные, вы можете сымити-ровать поведение набора данных Windows с помощью собственного кода, который будет обновлять данные на сервере всякий раз после их изменения. Для этого нужно написать обработчик события AfterPost клиентского набора данных, как показано в листинге 21.5.
Арифметические операции над двумя операндами
Таблица 3.1. Арифметические операции над двумя операндами| Знак операции | Операция | Типы операндов | Тип результата | Пример |
| + | Сложение | Integer, real | Integer, real | X+Y |
| - | Вычитание | Integer, real | Integer, real | X-Y |
| * | Умножение | Integer, real | Integer, real | X*Y |
| / | Деление | Integer, real | Real | X/10 |
| div | Целочисленное деление | Integer | Integer | X div Y |
| mod | Целочисленный остаток от деления | Integer | Integer | X mod Y |
Результатом операции mod будет остаток от целочисленного деления операндов. Таким образом, выражение X mod Y эквивалентно выражению X - (X div Y) *Y. Например, результатом выражения 4 div 2 будет 0, а результатом выражения 9 div 4 будет 1.
В табл. 3.2 приведены операции, осуществляемые над одним операндом.
Арифметические операции над одним операндом
Таблица 3.2. Арифметические операции над одним операндом| Знак операции | Операция | Тип операнда | Тип результата | Пример |
| + | Сохранение знака числа | Integer, real | Integer, real | +7 |
| - | Отрицание знака числа | Integer, real | Integer, real | -X |
Поразрядные арифметические операции
Таблица 3.3. Поразрядные арифметические операции| Знак операции | Операция | Типы операндов | Тип результата | Пример |
| not | Поразрядное отрицание | Integer | Integer | not X |
| and | Поразрядное умножение | Integer | Integer | X and Y |
| or | Поразрядное сложение | Integer | Integer | X or Y |
| xor | Поразрядное исключающее ИЛИ | Integer | Integer | X xor Y |
| shl | Поразрядный сдвиг числа влево | Integer | Integer | X shl 2 |
| shr | Поразрядный сдвиг числа вправо | Integer | Integer | X shr 1 |
Приведем примеры использования побитовых арифметических
Таблица 3.4 (окончание)| Знак операции | Операция | Бит1 | Бит 2 | Результирующий бит | ||
| 1 | 0 | 0 | ||||
| 1 | 1 | 1 | ||||
| or | Поразрядное сложение | 0 | 0 | 0 | ||
| 0 | 1 | 1 | ||||
| 1 | 0 | 1 | ||||
| 1 | 1 | 1 | ||||
| хоr | Поразрядное исключающее ИЛИ | 0 | 0 | 0 | ||
| 0 | 1 | 1 | ||||
| 1 | 0 | 1 | ||||
| 1 | 1 | 0 | ||||
Результаты выполнения поразрядных арифметических операций
Таблица 3.4. Результаты выполнения поразрядных арифметических операций| Знак операции | Операция | Бит1 | Бит 2 | Результирующий бит |
| not | Поразрядное отрицание | 0 | 1 | |
| 1 | 0 | |||
| and | Поразрядное умножение | 0 | 0 | 0 |
| 0 | 1 | 0 |
Логические операции языка Object Pascal
Таблица 3.5. Логические операции языка Object Pascal| Знак операции | Операция | Типы операндов | Тип результата | Пример |
| not | Отрицание | Boolean | Boolean | not (С in MySet) |
Как видно из примеров табл.
Таблица 3.5 (окончание)| Знак операции | Операция | Типы операндов | Тип результата | Пример |
| and | Конъюнкция (логическое И) | Boolean | Boolean | A and В |
| or | Дизъюнкция (логическое ИЛИ) | Boolean | Boolean | A or В |
| xor | Исключающая дизъюнкция (исключающее ИЛИ) | Boolean | Boolean | A xor В |
Результаты выполнения логических операций
Таблица 3.6. Результаты выполнения логических операций| Знак операции | Операция | Операнд 1 | Операнд 2 | Результат |
| not | Отрицание | False | True | |
| True | False | |||
| and | Конъюнкция (логическое И) | False | False | False |
| False | True | False | ||
| True | False | False | ||
| True | True | True | ||
| or | Дизъюнкция (логическое ИЛИ) | False | False | False |
| False | True | True | ||
| True | False | True | ||
| True | True | True | ||
| xor | Исключающая дизъюнкция (исключающее ИЛИ) | False | False | False |
| False | True | True | ||
| True | False | True | ||
| True | True | False |
Рассмотрим теперь такой немаловажный вопрос: в каком порядке выполняются те или иные операции? Если в сложном выражении записаны несколько операций подряд, то последовательность их выполнения определяется старшинством. Для того чтобы был четкий порядок выполнения операции, в языке Object Pascal существует такое понятие, как приоритет.
Приоритет определяет старшинство операций и служит для установления порядка выполнения операций. Операции с более высоким уровнем приоритета выполняются раньше остальных.
По приоритету все операции делятся на четыре уровня:
и not;
Строковые выражения
Строковые выражения содержат строковые операции и функции. Для строк в Object Pascal определена одна операция — операция объединения строк (конкатенации строк). Знаком операции конкатенации является +. Операндами для этой операции могут быть строки, упакованные строки, а также символы. В то же время, если один из операндов имеет тип WideChar, другой операнд должен быть длинной строкой. Результат операции объединения строк — строка символов. Этот результат совместим со всеми строковыми типами языка. В то же время, если количество символов после операции объединения строк превысит 255, то результатом станут первые 255 символов, а оставшиеся будут просто отброшены.
Для строк определены также следующие функции:
Методы для работы с RTTI
Таблица 5.1. Методы для работы с RTTI| Название метода |
Тип возвращаемого результата |
Результат |
| Classlnfo |
Pointer |
Указатель на информацию о типе объекта |
| ClassName |
String |
Имя класса объекта |
| ClassParent |
Tclass |
Тип класса-предка объекта |
| ClassType |
Tclass |
Тип объекта |
| InheritsFrom |
Boolean |
Является ли объект потомком данного класса |
| InstanceSize |
Word |
Размер объекта как экземпляра класса в байтах |
Синтаксис использования оператора is:
Объект is Класс;
Данный оператор применяется для проверки того, принадлежит ли объект к указанному классу. В том случае, если объект принадлежит классу, возвращается значение True, в противном случае возвращается False.
Приведем пример использования оператора is.
if ActiveControl is TEdit then TEdit(ActiveControl).SelectAll;
В этом примере производится проверка, имеет ли активный компонент тип TEdit. И если это так, то в нем выделяется весь имеющийся текст.
Примечание
Для более глубокого понимания компонентов и их свойств обратитесь ко второй части книги.
Синтаксис использования оператора as:
Объект as Класс;
Данный оператор служит для приведения одного типа к другому.
Информация о типе времени выполнения используется в Kylix в основном для определения, с объектом какого типа сейчас работает приложение.
Назад
Средство ведения списка задач, подлежащих
Таблица 6.1 (окончание)| Возможность | Desktop Developer | Server Developer |
| Средство ведения списка задач, подлежащих исполнению (список То Do) | Есть | Есть |
| Расширенный менеджер проектов | Есть | Есть |
| Расширенный интегрированный отладчик | Есть | Есть |
| Средства многопроцессной отладки | Есть | Есть |
| Набор стандартных компонентов для быстрой разработки приложений | 130 | 165 |
| Поддержка фреймов для создания составных компонентов | Есть | Есть |
| Интерфейс драйверов баз данных dbExpress | Есть | Есть |
| Локальное ядро баз данных MyBase | Есть | Есть |
| Драйверы dbExpress для MySQL и InterBase | Есть | Есть |
| Драйверы dbExpress для Oracle и Db2 | Нет | Есть |
| Компоненты NetCLX для разработки Интернет-приложений | Нет | Есть |
| Компоненты связи через sockets | Нет | Есть |
| Набор компонентов на основе WebBroker | Нет | Есть |
| Поддержка приложений Apache CGI и DSO | Нет | Есть |
| Контейнеры типа WebModule | Нет | Есть |
| Компоненты WebDispatch | Нет | Есть |
| Мастер создания Web-приложений для сервера Apache | Нет | Есть |
| Набор компонентов компании Nevrona для разработки Интернет-приложений: Indylnternet protocol component suite | Есть | Есть |
Если вы знакомы со средой программирования Borland Delphi, то переход к программированию в Kylix будет достаточно легким, т. к. многое в Kylix напоминает Delphi.
Интегрированная среда Kylix является достаточно удобным средством эффективной и быстрой разработки приложений в Linux. Среда Kylix вобрала в себя много хорошего от своего предшественника — Delphi.
Интегрированная среда разработки Kylix состоит из четырех основных окон, которые отображаются при запуске среды:
Возможности Kylix
Таблица 6.1. Возможности Kylix| Возможность | Desktop Developer | Server Developer |
| Высокопроизводительный оптимизирующий компилятор в платформенный исполняемый код | Есть | Есть |
| Возможность создания разделяемых библиотек объектов (Shared Object libraries, .so) | Есть | Есть |
| Интегрированная среда разработки (Integrated Development Environment, IDE) | Есть | Есть |
| Возможность сохранения нескольких схем размещения визуальных элементов IDE | Есть | Есть |
| Встроенное средство Code Explorer | Есть | Есть |
| Модули данных для хранения невизуальных объектов, компонентов и других элементов | Есть | Есть |
Компоненты вкладки Standard
Таблица 8.1. Компоненты вкладки Standard| Название на английском языке | Название на русском языке | Краткое описание компонента |
| Frames | Фреймы | Фрейм — это похожий на форму компонент, который используется для размещения внутри него других компонентов. Может размещаться на формах или других фреймах. Для создания нового фрейма нужно выбрать пункт меню File/New Frame (Файл/Новый Фрейм) |
Создает так называемый контейнер, который
Таблица 8.1 (окончание)| Название на английском языке | Название на русском языке | Краткое описание компонента |
| GroupBox | Группа | Создает так называемый контейнер, который может содержать внутри себя компоненты. Эти компоненты объединяются в одну группу. Служит в основном для удобства работы с разными группами компонентов на одной форме |
| RadioGroup | Группа переключателей | Создает группу переключателей. Эти переключатели не зависят от других групп или одиночных переключателей |
| Panel | Панель | Используется для создания строк состояния или панелей инструментов. На панели могут размещаться другие компоненты |
| ActionList | Список действий | Позволяет вашему приложению централизованно реагировать на какие-либо действия пользователя. Например, копирование данных из поля для ввода |
Служит для создания главного меню
Таблица 8.1 (продолжение)| Название на английском языке | Название на русском языке | Краткое описание компонента |
| MainMenu | Главное меню | Служит для создания главного меню вашего приложения. Расположите этот компонент на форме и после двойного щелчка на нем добавьте новые пункты вашего меню |
| PopupMenu | Всплывающее меню | Служит для создания так называемого всплывающего меню — меню, которое отображается после щелчка правой кнопкой мыши в определенной области приложения |
| Label | Метка | Служит для простого отображения текстовой информации, которую пользователь не может редактировать во время работы приложения |
| Edit | Поле для ввода | Служит для отображения текстовой информации, которую пользователь может изменять. Удобно применять для ввода или редактирования какой-либо текстовой информации |
| Memo | Многострочное поле | Работает как и поле для ввода, только позволяет вводить (редактировать) несколько строк текста |
| Button | Кнопка | Обычная кнопка предназначена для выполнения какого-либо кода по нажатии на кнопку пользователем |
| CheckBox | Флажок | Представляет опцию, благодаря которой пользователь может изменять положение переключателя вкл./выкл. |
| RadioButton | Переключатель | Данный переключатель работает обычно в группе с другими. Если на форме располагается несколько таких переключателей, только один из них может принимать включенное положение |
| ListBox | Список | Предназначен для вывода нескольких строк текста. Пользователь может выбрать любую из этих строк простым нажатием на ней |
| ComboBox | Выпадающий список | Является как бы комбинацией списка и поля для ввода. Пользователь может ввести самостоятельно текст в поле либо выбрать нужный из предоставленного списка |
| ScrollBar | Полоса прокрутки | Предназначена для смены видимой области отображения формы. Нужна для просмотра большого количества информации, которая просто не помещается на экран |
Компоненты вкладки Indy Servers
Таблица 8.10. Компоненты вкладки Indy Servers| Название | Название на русском языке | Краткое описание компонента |
| IdTCPServer | TCP-сервер | Инкапсулирует полную функциональность TCP-сервера, включая поддержку сокетов, и может быть использован для создания заказных программных средств |
| IdUDPServer | UDP-сервер | Инкапсулирует полную функциональность UDP-сервера и может быть использован для создания заказных программных средств |
| IdChargenServer | Chargen-сервер | Обеспечивает создание Chargen-сервера |
| IdDayTimeServer | Сервер даты/времени | Обеспечивает поддержку протокола даты/времени (RFC 876) как сервер |
| IdDictServer | Dictionary-сервер | Обеспечивает поддержку протокола Dictionary Server, DICT (RFC 2229) |
| IdDiscardServer | Discard-сервер | Обеспечивает поддержку протокола Discard (RFC 863) как сервер |
позволяющий получить доступ клиентов через
Таблица 8.10 (окончание)| Название | Название на русском языке | Краткое описание компонента |
| IdTunneIMaster | TCP-сервер с поддержкой IP-туннелей | Позволяет создавать серверы, поддерживающие IP-туннели |
| IdTunnelSlave | Сервер доступа к туннельным соединениям | Сервер, позволяющий получить доступ клиентов через туннельное соединение |
| IdWhoIsServer | Whois-сервер | Поддерживает протокол Nickname или Whois (RFC 954) как сервер |
Обеспечивает поддержку протокола Finger User
Таблица 8.10 (продолжение)| Название | Название на русском языке | Краткое описание компонента |
| IdEchoServer | Эхо-сервер | Обеспечивает поддержку эхо-протокола (RFC 862) как сервер |
| IdFingerServer | Сервер указателя | Обеспечивает поддержку протокола Finger User Information (RFC 1288) как сервер |
| IdGopher Server | Gopher-сервер | Обеспечивает поддержку протокола Internet Gopher (RFC 1436) как сервер |
| IdHostNameServer | HostName-сервер | Обеспечивает разработку Internet HostName сервера (RFC 953) |
| IdHTTPServer | HTTP-сервер | Обеспечивает поддержку HTTP-протокола как сервер |
| IdMAP4Server | МАР4-сервер | Обеспечивает поддержку протокола Internet Message Access версии 4, IMAP4 (RFC 2060) |
| IdlRCServer | IRC-сервер | Позволяет создавать сервер, поддерживающий протокол Internet Relay Chat, IRC (RFC 1459) |
| IdMappedPortTCP | Сервер портов TCP | Позволяет создавать сервер с прослушиванием определенных портов и обеспечением связи с другими серверами |
| IdNNTPServer | NNTP-сервер | Обеспечивает поддержку протокола Network News Transfer (RFC 977) как сервер |
| IdQOTDServer | QOTD-сервер | Обеспечивает поддержку протокола Quote of the Day (RFC 865) как сервер |
| IdSimpleServer | Простой TCP-сервер | Простой TCP-сервер без поддержки потоков |
| IdTelnetServer | Telnet-сервер | Компонент поддерживает протокол Telnet как сервер |
| IdTimeServer | Time-сервер | Компонент поддерживает протокол Time (RFC 868) как сервер |
| IdTrivialFTPServer | TrivialFTP-сервер | Компонент поддерживает протокол Trivial File Transfer как сервер |
Компоненты вкладки Indy Misc
Таблица 8.11. Компоненты вкладки Indy Misc| Название | Название на русском языке | Краткое описание компонента |
| IdAntiFreeze | Разморозка | Позволяет подсистеме Indy осуществить вызов процедуры Application . ProcessMessag, которая обеспечивает дальнейшую работу системы, пока обрабатываются вызовы Indy |
| IdDateTimeStamp | Переводчик форматов даты/времени | Переводит дату/время в различные форматы, используемые в различных протоколах |
| IdLogDebug | Отладчик | Прерывает текущее соединение в случае ошибки с ведением log-файла |
На этом пока закончим обзор
Таблица 8.11 (окончание)| Название | Название на русском языке | Краткое описание компонента |
| IdCoderMD4 | Шифровальщик MD4 | Шифрует данные с использованием (формата шифрования MD4 |
| IdCoderMD5 | Шифровальщик MD5 | Шифрует данные с использованием, формата шифрования MD5 |
RFC 822 или RFC 1036)
Таблица 8.11 (продолжение)| Название | Название на русском языке | Краткое описание компонента |
| IdMessage | Интернет-сообщение | Инкапсулирует полное Интернет-сообщение ( RFC 822 или RFC 1036) для следующих протоколов: РОР3, SMTP и NNTP со встроенным расширением Multiple Mail Extensions, MME (RFC 2045, 2046, 2047, 2048 и 2049) |
| IdThreadMgrDefault | Менеджер потока | Действует по умолчанию в качестве менеджера потока в Indy для сервера типа TidTCPServer и его потомков |
| IdThreadMgrPool | Пудовый менеджер потока | Работает как менеджер потока, для потока типа TIdThread, использующего пул |
| IdVCard | Электронные бизнес-карты | Обеспечивает поддержку Virtual Cards (электронных бизнес-карт с помощью метода ReadFromTStrings |
| IdlMFDecoder | IMF-декодер | Декодирует двоичные данные в текстовый формат при помощи UU-кодировки |
| IdQuotedPrintableEncoder | ММЕ-кодер | Кодирует текст в формат ММЕ |
| IdQuotedPrintableDecoder | ММЕ-декодер | Декодирует формат ММЕ в текст |
| IdBase64Encoder | Ваsе64-кодер | Кодирует двоичные данные в текст, использующий кодировку Base64 |
| IdBase64Decoder | Base64-декодер | Декодирует текст в формате Base64 в двоичную форму |
| IdUUEncoder | UU-кодер | Кодирует двоичные данные в текст, использующий кодировку UUEncode |
| IdUUDecoder | UU-декодер | Декодирует текст формата UUEncode в двоичную форму |
| IdXXEncoder | ХХ-кодер | Кодирует двоичные данные в текст, использующий кодировку XX |
| IdXXDecoder | ХХ-декодер | Декодирует текст формата XX в двоичную форму |
| IdCoderMD2 | Шифровальщик MD2 | Шифрует данные с использованием формата шифрования MD2 |
в инспекторе объектов как множества.
Таблица 8.12 (окончание)| Тип свойства | Отображение свойств в окне инспектора объектов |
| Множество (Set) | Свойства типа "множество" отображаются в инспекторе объектов как множества. При помощи двойного щелчка мыши на значении свойства разработчик может расширить множество и установить каждому элементу множества булево значение (True, если данный элемент входит в множество) |
| Объект (Object) | Свойства такого типа часто имеют собственный редактор свойств. Свойства типа "объект" должны быть потомками класса Tpersistent |
| Массив (Array) | Свойства типа "массив" должны иметь собственный редактор свойств. Инспектор объектов Kylix не поддерживает редактирование свойств данного типа. Разработчик должен при регистрации компонента определить редактор свойств |
Рассмотрим свойства, которые имеют стандартные компоненты Kylix. Для начала — основные свойства, которые присущи компонентам — наследникам класса TControl. Кроме краткого описания свойства, мы будем приводить строку кода, описывающего данное свойство внутри класса TControl.
Это поможет вам понять, какой тип имеет данное свойство.
property Action: TBasicAction;
property ActionLink: TControlActionLink;
property Align: TAlign;
• alNone — компонент остается на том месте, где он был размещен во время разработки приложения. Данное значение присваивается свойству Align по умолчанию;
• alTop — компонент занимает всю верхнюю часть компонента-контейнера. Во время выполнения приложения ширина компонента зависит от ширины компонента-контейнера. Высота компонента остается неизменной, независимо от высоты контейнера;
• alBottom - аналогичен alTop, за исключением того, что компонент занимает всю нижнюю часть компонента-контейнера;
• alLeft — компонент занимает всю левую часть компонента-контейнера. Во время выполнения приложения высота компонента зависит от высоты компонента-контейнера. При изменении ширины компонента-контейнера ширина компонента остается неизменной;
• alRight — аналогичен alLeft, за исключением того, что компонент занимает всю правую часть компонента-контейнера;
• alClient — компонент занимает всю клиентскую часть компонента-контейнера. При изменении высоты и ширины компонента-контейнера изменяются высота и ширина компонента. Если в клиентской части компонента контейнерного типа уже имеются другие компоненты, то данный компонент занимает всю оставшуюся незанятой часть компонента-контейнера.
Примечание
Значения alTop и alBottom имеют больший приоритет по сравнению со значениями alLeft и alRight. Таким образом, если вы вывели на форму два компонента, присвоив свойству Align одного из них значение alTop, а другому — alRight, то первый компонент вытеснит верхнюю часть второго компонента (Рисунок 8.12).
property Anchors: TAnchors;
Это свойство имеет тип множества (TAnchors), которое может содержать такие элементы: • akTop — компонент привязан к верхнему краю родительского компонента;
• akLeft — компонент привязан к левому краю родительского компонента;
• akBottom — компонент привязан к нижнему краю родительского компонента;
• akRight — компонент привязан к правому краю родительского компонента.
Типы свойств компонентов Kylix
Таблица 8.12. Типы свойств компонентов Kylix| Тип свойства | Отображение свойств в окне инспектора объектов |
| Простой (Simple) | Числовые, символьные и строковые свойства отображаются соответственно как числа, символы и строки. Разработчик может редактировать значения данных свойств непосредственно в окне инспектора объектов |
| Перечисляемый (Enumerated) | Свойства перечисляемых типов (включая булевы) отображаются в инспекторе объектов как редактируемые строки. Разработчик может, кроме непосредственного ввода значения свойства, переключать допустимые значения свойства двойным щелчком кнопки мыши в поле значения свойства инспектора объектов либо выбрать допустимое значение из выпадающего списка |
Константы цвета в среде Kylix
Таблица 8.13. Константы цвета в среде Kylix| Константа | Цвет |
| clNone | Бесцветный (белый) |
| clBlack | Черный |
| clMaroon | Темно-бордовый |
| clGreen | Зеленый |
| clOlive | Оливковый |
| clNavy | Темно-синий |
| clPurple | Пурпурный |
| clTeal | Морской |
| clGray | Серый |
| clSilver | Серебристый |
| clRed | Красный |
| clLime | Лимонный |
| clBlue | Синий |
| clYellow | Желтый |
| clFuchsia | Сиреневый |
| сlAqua | Голубой |
| clLtGray | Светло-серый |
| clDkGray | Темно-серый |
| clWhite | Белый |
| clBackground | Базовый цвет фона |
| clNormalBackground | Цвет фона для включенных неактивных компонентов |
| dBase | Базовый цвет фона для текстовых компонентов |
| clNormalBase | Цвет фона для включенных неактивных текстовых компонентов |
| clDisabledBase | Цвет фона для отключенных текстовых компонентов |
Базовый цвет для среднеосвещенных областей
Таблица 8.13 (окончание)| Константа | Цвет |
| clActiveLight | Цвет светлых областей в 3D-эффектах для активных компонентов |
| clMidlight | Базовый цвет для среднеосвещенных областей в 3D-эффектах |
| clNormalMidlight | Цвет среднеосвещенных областей в 3D-эффектах для включенных неактивных компонентов |
| clDisabledMidlight | Цвет среднеосвещенных областей в 3D-эффектах для отключенных компонентов |
| clActiveMidlight | Цвет среднеосвещенных областей в 3D-эффектах для активных компонентов |
| clMid | Базовый цвет для темных областей в 3D-эффектах |
| clNormalMid | Цвет темных областей в 3D-эффектах для включенных неактивных компонентов |
| clDisabledMid | Цвет темных областей в 3D-эффектах для отключенных компонентов |
| clActiveMid | Цвет темных областей в 3D-эффектах для активных компонентов |
| clDark | Базовый цвет для очень темных областей в 3D-эффектах |
| clNormalDark | Цвет очень темных областей в 3D-эффектах для включенных неактивных компонентов |
| clDisabledDark | Цвет очень темных областей в 3D-эффектах для отключенных компонентов |
| clActiveDark | Цвет очень темных областей в 3D-эффектах для активных компонентов |
| clShadow | Базовый цвет тени в 3D-эффектах |
| clNormalShadow | Цвет тени в 3D-эффектах для включенных неактивных компонентов |
| ClDisabledShadow | Цвет тени в 3D-эффектах для отключенных компонентов |
| clActiveShadow | Цвет тени в 3D-эффектах для активных компонентов |
for i := 0 to ComponentCount - 1 do
if (Components[ i ].Name <> 'Button1') then
(Components[ i ] as TControl).Left: = (Components[ i ] as TControl).Left + 10;
property Constraints: TSizeConstraints;Примечание
He устанавливайте данное свойство, если вы используете свойства Align или Anchors, т. к. это может привести к конфликту свойств и неправильной работе приложения.
property ControlState: TControlState;
Цвет фона для активных текстовых
Таблица 8.13 (продолжение)| Константа | Цвет |
| clActiveBase | Цвет фона для активных текстовых компонентов |
| clScrollBar | Цвет полос прокрутки |
| clActiveCaption | Цвет фона полосы заголовка активного окна |
| clInactiveCaption | Цвет фона полосы заголовка неактивного окна |
| clMenu | Цвет фона меню |
| clWindow | Цвет фона окна |
| clWindowFrame | Цвет рамки окна |
| clMenuText | Цвет текста меню |
| clWindowText | Цвет текста окна |
| clCaptionText | Цвет текста заголовка в активном окне |
| clActiveBorder | Цвет бордюра активного окна |
| clInactiveBorder | Цвет бордюра неактивного окна |
| clAppWorkSpace | Цвет рабочей области приложения |
| clHighlight | Базовый цвет фона для выбранного или подсвеченного компонента |
| clNormalHighlight | Цвет фона для включенных неактивных подсвеченных компонентов |
| clDisabledHighlight | Цвет фона для отключенных подсвеченных компонентов |
| clActiveHighlight | Цвет фона для активных подсвеченных компонентов |
| clHighlightedText | Базовый цвет букв подсвеченного текста |
| clNormalHighlightedText | Цвет букв включенных неактивных подсвеченных компонентов |
| clDisabledHighlightedText | Цвет букв отключенных подсвеченных компонентов |
| clActiveHighlightedText | Цвет букв отключенных подсвеченных компонентов |
| clBtnFace | Цвет поверхности кнопки |
| clBtnShadow | Цвет тени, отбрасываемой кнопкой |
| clGrayText | Цвет текста недоступных элементов окна |
| clBtnText | Цвет текста кнопки |
| clInactiveCaptionText | Цвет заголовка в неактивном окне |
Таблица 8.13 (продолжение)
| Константа | Цвет |
| clBtnHighlight | Цвет выделенной кнопки |
| cl3DDkShadow | Цвет темных теней трехмерных элементов окна |
| cl3DLight | Светлый цвет на краях трехмерных элементов окна |
| clInfoText | Цвет текста советов (всплывающих подсказок) |
| clInfoBk | Цвет фона советов (всплывающих подсказок) — обычно светло-коричневый |
| clHighlightText | Подсвеченный текст |
| clForeground | Базовый цвет линий или текста |
| clNormalForeground | Цвет линий или текста для включенных неактивных компонентов |
| clDisabledForeground | Цвет линий или текста для отключенных компонентов |
| clActiveForeground | Цвет линий или текста для активных компонентов |
| clText | Базовый цвет букв |
| clNormalText | Цвет букв для включенных неактивных текстовых компонентов |
| clDisabledText | Цвет букв для отключенных текстовых компонентов |
| clActiveText | Цвет букв для активных текстовых компонентов |
| clButton | Базовый цвет фона кнопок |
| clNormalButton | Цвет фона включенных неактивных кнопок |
| clDisabledButton | Цвет фона отключенных кнопок |
| clActiveButton | Цвет фона активных кнопок |
| clButtonText | Базовый цвет букв кнопок |
| clNormalButtonText | Цвет букв включенных неактивных кнопок |
| clDisabledButtonText | Цвет букв отключенных кнопок |
| clActiveButtonText | Цвет букв активных кнопок |
| clBrightText | Базовый контрастный цвет букв |
| clNormalBrightText | Контрастный цвет букв включенных неактивных компонентов |
| clDisabledBrightText | Контрастный цвет букв отключенных компонентов |
| clActiveBrightText | Контрастный цвет букв активных компонентов, |
| clLight | Базовый цвет для светлых областей в 3D-эффектах |
| clNormalLight | Цвет светлых областей в 3D-эффектах для включенных неактивных компонентов |
| clDisabledLight | Цвет светлых областей в 3D-эффектах для отключенных компонентов |
Флаги значения свойства ControlState
Таблица 8.14. Флаги значения свойства ControlState| Флаг | Значение |
| csLButtonDown | Левая кнопка мыши нажата |
| csClicked | То же, что и csLButtonDown, но устанавливается только в случае, если в свойстве ControlStyle также установлен флаг csClickEvents |
| csPalette | Палитра изменена, и элемент управления не закончил регулировку этой палитры |
Элемент управления считывает свое состояние
Таблица 8.14 (окончание)| Флаг | Значение |
| csReadingState | Элемент управления считывает свое состояние из потока |
| csAlignmentNeeded | Элемент управления нуждается в перестроении |
| csFocusing | Приложение обрабатывает сообщения, предназначенные для передами фокуса элементу управления. Данный флаг не гарантирует, что элемент управления получит фокус, но предотвращает рекурсивные вызовы |
| csCfeating | Элемент управления и (или), его владелец начинают создаваться. Данный флаг сбрасывается после завершения процесса создания |
| csPaintCopy | Элемент управления начинает копирование (собственное) |
| csCustomPaint | Элемент управления обрабатывает выбранные сообщения о закрашивании |
| csDestroyingHandle | Окно элемента управления находится в процессе уничтожения |
| csDocking | Элемент управления начинает устанавливаться |
| csRecreating | Основное окно Qt начинает создаваться |
| esWidgetPainting | Основное окно Qt в процессе перерисовки |
property ControlStyle: TControlStyle;
Флаги значения свойства ControlStyle
Таблица 8.15. Флаги значения свойства ControlStyle| Флаг | Значение |
| CsAcceptsControls | Элемент управления получает своего предка от одного из компонентов, созданных во время разработки приложения |
| CsCaptureMouse | Элемент управления перехватывает событие нажатия кнопки мыши |
| CsDesignlnteractive | Элемент управления преобразует щелчки правой кнопкой мыши во время разработки приложения в щелчки левой Кнопкой мыши |
Элемент управления имеет вид трехмерной
Таблица 8.15 (окончание)| Флаг , | Значение |
| CsClickEvents | Элемент управления может принимать и обрабатывать щелчки мыши |
| CsFramed | Элемент управления имеет вид трехмерной рамки |
| CsSetCaption | Значение свойства Caption элемента управления должно соответствовать значению свойства Name этого же элемента управления, если оно не было явно установлено в какое-то другое значение |
| СsOpaque | Элемент управления полностью занимает клиентскую прямоугольную область |
| CsDoubleClick | Элемент управления может принимать и обрабатывать двойные щелчки мыши. Иными словами, преобразовывать двойные щелчки в одинарные |
| CsFixedWidth | Ширина элемента управления не может быть изменена |
| CsFixedHeight | Длина элемента управления не может быть изменена |
| CsNoDesignVisible | Элемент управления является невидимым при разработке приложения |
| CsReplicatable | Элемент управления может быть скопирован с помощью метода PaintTo |
| CsNoStdEvents | Стандартные события, такие как щелчки мыши, нажатие клавиш клавиатуры и др., игнорируются приложением. Установка данного флага позволяет приложению работать быстрее и применяется в тех случаях, когда обработки стандартных событий не требуется |
| CsDisplayDragImage | Элемент управления может содержать изображение из списка изображений |
| CsActionClients | Элемент управления привязан к объекту типа TBasicAction. Этот флаг устанавливается, если у элемента управления используется свойство Action, и сбрасывается в противном случае |
| CsMenuEvents | Элемент управления реагирует на команды системного меню |
property Cursor:TCursor;
type TCursor = -32768 .. 32768;
Kylix имеет встроенные виды указателей. Кроме встроенных, разработчик может помещать в приложение собственные виды указателя мыши. В табл. 8.16 приводятся встроенные типы указателей мыши.
Указатели мыши
Таблица 8.16. Указатели мыши| Значение свойства Cursor | Числовое значение | Изображение указателя мыши |
| CrDefault | 0 | Указатель, принятый по умолчанию. Обычно это сrArrow |
| CrNone | -1 | Без изображения указателя |
| CrArrow | -2 | Стрелка |
| CrCross | -3 | Крест |
| CrIBeam | -4 | Указатель в виде курсора для ввода текста |
| CrSize | -22 | Указатель изменения размера окна |
| CrSizeNESW | -6 | Указатель изменения размера окна в правом верхнем углу или в левом нижнем |
| CrSizeNS | -7 | Указатель изменения размера окна вверху или внизу (по вертикали) |
| CrSizeNWSE | -8 | Указатель изменения размера окна в левом верхнем углу или в правом нижнем |
| CrSizeWE | -9 | Указатель изменения размера окна слева или справа (по горизонтали) |
| CrUpArrow | -10 | Стрелка вверх |
| CrHourGlass | -11 | Песочные часы |
| CrDrag | -12 | Перетаскивание компонента |
| CrNoDrop | -13 | Указатель, показывающий невозможность переноса компонента в данную область |
| CrHSplit | -14 | Горизонтальный сплиттер |
| CrVSplit | -15 | Вертикальный сплиттер |
| CrMultiDrag | -16 | Перетаскивание нескольких компонентов |
| CrSQLWait | -17 | Ожидание выполнения SQL-запроса |
| CrNo | -18 | Указатель, показывающий невозможность действия |
| CrAppStart | -19 | Ожидание старта приложения (стрелка с песочными часами) |
| CrHelp | -20 | Стрелка с вопросом |
| CrHandPoint | -21 | Указатель в форме руки |
property DragMode: TDragMode;
Данное свойство может принимать одно из двух значений: dmAutomatic или dmManual. В первом случае от разработчика не требуется обработки событий. Достаточно щелкнуть кнопкой мыши на компоненте и начать его перетаскивание. Во втором случае компонент не может начать процесс перетаскивания, пока приложение не вызовет метод BeginDrag.
property DragObject: TDragObject;
Оно предназначено только для чтения и используется в основном при создании собственных компонентов.
property Enabled: Boolean;
Недоступный компонент (Enabled = false) отображается серым цветом. Он игнорирует события клавиатуры, мыши и таймера. Данное свойство применяется для временного ограничения доступа пользователя к компонентам. Например, если вы хотите сделать временно недоступной кнопку, нужно в свойстве Enabled кнопки установить значение false:
Button1.Enabled := false;
property Font: TFont;
property Height: Integer;
property HelpContext: THelpContext;
property HelpFile: String;
Данное свойство содержит имя файла, который будет использоваться приложением в качестве файла контекстно-зависимой справки.
property HelpKeyword: String;
property Hint: String;
Данное свойство обычно состоит из двух частей, разделяемых символом " |". Например,
Button1.Hint := "Открыть|Выбор и открытие файла рисунка";
В данном случае при наведении указателя мыши на кнопку Button1 будет выдана всплывающая подсказка "Открыть", вторая часть подсказки будет выведена в специальную область, отведенную для таких подсказок, например на панель состояния. Разработчик может пользоваться только первой частью подсказки, без использования символа "|". Кроме того, для отображения всплывающих подсказок нужно дополнительно установить свойство ShowHint в true (см. далее).
Данное свойство описано следующим образом:
property Left: Integer;
property MouseCapture: Boolean;
Если элемент управления захвачен мышью — возвращается True, иначе —False.
property Name: TComponentName;
Имя задается в процессе разработки программы и не должно изменяться во время работы программы. Kylix по умолчанию самостоятельно дает имена новым компонентам, например: Button1, Button2, Label1 и т. п. Рекомендуется изменять эти имена на более осмысленные.
property Parent: TWidgetControl;Примечание
Важно различать два похожих свойства. Свойство Parent определяет родительский компонент, т. е. тот компонент, на котором располагается данный компонент. Свойство Owner определяет владельца компонента. Владелец — это компонент, который передается в качестве параметра в конструктор данного компонента и который владеет им. Например, форма является владельцем всех расположенных на ней компонентов и одновременно — родителем.
property ParentColor: Boolean;
property ParentFont: Boolean;
property ParentShowHint: Boolean;
Данное свойство используется для одновременного разрешения или запрещения показа всплывающих подсказок в пределах некоторой формы или компонента контейнерного типа.
property PopupMenu: TPopupMenu;
property ScalingFlags: TScalingFlags;
Флаги TScalingFlagФлаг
Таблица 8.17. Флаги TScalingFlag| Флаг | Значение |
| sfLeft | Левая сторона элемента управления не может масштабироваться |
| sfTop | Верх элемента управления не может масштабироваться |
| sf Width | Ширина элемента управления не может масштабироваться |
| sfHeight | Высота элемента управления не может масштабироваться |
| sfFont | Шрифт элемента управления не может масштабироваться |
property ShowHint: Boolean;
property Text: TCaption;
Это свойство применяется в компонентах типа TEdit и в компонентах-списках.
property Top: Integer;
property Visible: Boolean;
property Width: Integer;
property Bitmap: TBitmap;
property Brush: TBrush;
property ChildHandle: QwidgetH; library;
property ControlCount: Integer;
Это свойство применяется только для чтения. Значение, хранящееся в данном свойстве, всегда на единицу больше, чем самый последний индекс дочернего элемента (см. свойство Controls ниже), т. к. первый индекс всегда равен нулю.
property Controls[Index: Integer]: TControl;Примечаниe
He путайте свойство Controls со свойством Components. Свойство Controls содержит список всех дочерних окон от данного, а свойство Components — список всех компонентов, владельцем которых этот компонент является.
property Handle: QWidgetH read GetHandle; library;
Данное свойство применяется только для чтения
property InputKeys: TInputKeys;
Таблицa 8.18. Значения типа TInputKeys
| Значение | Описание |
| ikAll | Ввод любых символов клавиатуры |
| ikArrows | Клавиши со стрелками (<влево>, <вправо>, <вверх>, <вниз>) |
| ikChars | Любые нефункциональные клавиши без |
| ikReturns | Клавиша ввода ( |
| ikTabs | Клавиша табуляции (<Таb>) и комбинация клавиш обратной табуляции ( |
| ikEdit | Клавиши редактирования ( |
| ikNav | Клавиши навигации по тексту (<вверх>, <вниз>, <влево>, <вправо>, |
| ikEsc | Клавиша |
property Masked: Boolean;
Принимает значение True, если окно имеет непрямоугольную форму.
property Palette: TWidgetPalette;
property ParentWidget: QWidgetH;
property Style: TWidgetStyle;
property TabOrder: TTabOrder;
Нумерация осуществляется, начиная с нуля. Если задать свойству TabOrder компонента значение -1, этот компонент не сможет получить фокус при помощи клавиши <Таb>. Предположим, что на форме расположены три кнопки: Button1, Button2 и Button3. Для того чтобы фокус между этими кнопками передавался следующим образом: сначала активна кнопка Button2, затем — Button1 и потом уже Button3, нужно установить свойство TabOrder для кнопки Button1 равным 1, для Button2 — 0, а для Button3 — 2.
property TabStop: Boolean;
Методы
Методы — это процедуры или функции, принадлежащие объекту. Методы определяют поведение объекта. Для вызова метода объекта нужно указать объект, с которым ассоциирован данный метод, затем, через точку, — название метода. Например:
Button1.Click
Вызывается метод нажатием (Click) кнопки (Button1).
Для создания метода его нужно сначала объявить внутри описания класса или компонента, содержащего данный метод. Например:
type TMyComponent = class(TObject)
. . .
procedure DoSomething; . . .
end;
Здесь, внутри описания нового компонента, мы объявляем метод DoSomething с помощью служебного слова procedure. После того как мы объявили новый метод, необходимо создать тело данного метода. Эта процедура может находиться где угодно внутри модуля, в котором был описан компонент. Например:
procedure TMyComponent.DoSomething; begin
// Здесь размещаем команды и операторы, которые должны выполняться
// при вызове метода DoSomething на выполнение end;
Заметим, что при создании процедуры DoSomething мы должны указывать его полное имя вместе с указанием имени компонента или класса
(procedure TMyComponent.DoSomething;).
Рассмотрим основные методы среды Kylix.
Duplicates установлено в dupError.
Коды клавиш
Таблица 8.19. Коды клавиш| Символическое имя клавиши | Название клавиши | Символическое имя клавиши | Название клавиши |
| Key_Escape | Key_Period | <.> | |
| Key_ Tab | Key_ Slash | > | |
| Key_ Backtab, Key_ BackTab | Key_0 | <0> | |
| Key_Backspace, Key_BackSpace | Key_1 | <1> | |
| Key_Return | Key_2 | <2> | |
| Key_Enter | Key_3 | <3> | |
| Key_Insert | Key_4 | <4> | |
| Key_Delete | Key_5 | <5> | |
| Key_ Pause | Key_6 | <6> | |
| Key_Print | Key_7 | <7> | |
| Key_SysReq | Key_8 | <8> |
Параметр Shift является множеством, которое
Таблица 8.19 (окончание)| Символическое имя клавиши | Название клавиши | Символическое имя клавиши | Название клавиши |
| Key_Exclam | | Кеy_К | |
| Key_NumberSign | <#> | Key_L | |
| Key_Dollar | <$> | Кеy_М | <М> |
| Key _Percent | <%> | Key_N | |
| Key_Ampersand | <&> | Кеy_O | <0> |
| Key_Apostrophe | <'> | Кеy_Р | <Р> |
| Key_Asterisk | <*> | Key_Q | |
| Key_ Plus | <+> | Key_R | |
| Кеy_Соmmа | <,> | ... | |
| Key_Minus | <-> | Key_Z |
if ( (Key = ord ('L') ) and (ssShift in Shift) and (ssCtrl in Shift) )
then ShowMessage ('Нажата комбинация клавиш
В вышеприведенном примере мы использовали функцию ord ( ), которая позволяет по символу клавиши получить код клавиши (в нашем случае, код клавиши
Символическое имя
Таблица 8.19 (продолжение)| Символическое имя клавиши | Название клавиши | Символическое имя клавиши | Название клавиши |
| Кeу_ Ноmе | Кеу_9 | <9> | |
| Key_ End | Key_Colon | <:> | |
| Key_Left | <стрелка влево> | Key_Semicolon | <;> |
| Key_Up | <стрелка вверх> | Key_Less | <меньше> |
| Key_Right | <стрелка вправо> | Key_Equal | <=> |
| Key_ Down | <стрелка вниз> | Key_Greater | <6ольше> |
| Key_PageUp | Key_Question | > | |
| Key_ PageDown | Key_At | <@> | |
| Key_Shift | Key_BracketLeft | <[> | |
| Key_Control | Key_BackSlash | <\> | |
| Key_Alt | Key_BracketRight | <]> | |
| Key _CapsLock | Key_AnsiiCircum | <^> | |
| Key _NumLock | Key_Underscore | < > | |
| Key_ScrollLock | Key_BraceLeft | <{> | |
| Key_F1 | Key_Bar | <|> | |
| Key_F2 | Key_BraceRight | <}> | |
| Key_F3 | Key_AsciiTilde | <~> | |
| Key_F4 | Key_paragraph | <параграф> | |
| Key_F5 | Key_unknown | Неизвестная клавиша | |
| Key_F6 | Key_A | <А> | |
| Key_F7 | Key_B | <В> | |
| Key_F8 | Key_C | <С> | |
| Key_F9 | Key_D | ||
| Key_F10 | Key_F | ||
| Key_F11 | Key_G | ||
| Key_F12 | Key_I | ||
| Key_Space | <пробел> | Key_J |
Компоненты вкладки Additional
Таблица 8.2. Компоненты вкладки Additional| Название | Название на русском языке | Краткое описание компонента |
| BitBtn | Кнопка с рисунком | Кнопка, которая, помимо текста, может отображать рисунок |
| SpeedButton | Кнопка быстрого доступа | Такие кнопки обычно располагаются на панели инструментов. Они не могут содержать текста, а содержат только рисунки |
| MaskEdit | Поле для ввода по шаблону | Компонент похож на поле для ввода, только позволяет вводить информацию по определенным правилам, например паспортные данные, почтовый индекс, номер телефона и др. |
Название на английском
Таблица 8.2 (окончание)| Название на английском языке | Название на русском языке | Краткое описание компонента |
| StringGrid |
Компоненты вкладки Common Controls
Таблица 8.3. Компоненты вкладки Common Controls| Название | Название на русском языке | Краткое описание компонента |
| TabControl | Вкладки | Предназначен для размещения нескольких переключаемых страниц, содержащих различные элементы. Примером применения вкладок может служить палитра компонентов Kylix |
| PageControl | Страницы | Используется для создания многостраничных диалоговых окон, таких как, например, окно настройки проекта (Project Options) Kylix |
| ImageList | Список рисунков | Создает объединение рисунков, имеющих одинаковый размер, каждому из которых сопоставлен собственный индекс |
| TrackBar | Бегунок | Панель, предназначенная для визуального изменения какой-либо переменной величины. Бегунок может быть как горизонтальным, так и вертикальным |
| ProgressBar | Индикатор хода выполнения | Создает прямоугольную панель, которая заполняется слева направо для индикации хода выполнения какой-либо задачи. Часто применяется для отображения хода установки (инсталляции) какой-либо программы на жесткий диск |
| TreeView | Дерево | Отображает список в виде дерева |
| ListView | Список | Отображает список |
| HeaderControl | Заголовок | Отображает заголовок над столбцами, содержащими текст или числовые значения |
| StatusBar | Строка состояния | Создает панель, предназначенную для вывода служебной информации |
| ToolBar | Панель инструментов | Создает элемент, позволяющий размещать на себе кнопки и другие элементы, автоматически подбирая их размер и расположение |
Отображает содержимое текстового файла или
Таблица 8.3 (окончание)| Название | Название на русском языке | Краткое описание компонента |
| TextViewer | Просмотрщик текстов | Отображает содержимое текстового файла или простую HTML-страничку, которую можно прокручивать (скроллировать) |
| TextBrowser | Обозреватель текстов | Отображает содержимое текстового файла или простую HTML-страничку. Пользователь может прокручивать (скроллировать) текст или щелкать на размещенных в тексте ссылках для просмотра других страниц и рисунков |
| SpinEdit | Поле со стрелками | Отображает поле редактирования, в которое пользователь может ввести однострочное числовое значение или текст и использовать кнопки "стрелка вверх" и "стрелка вниз" для увеличения или уменьшения текущего значения поля |
| IconView | Список иконок | Отображает список или данные в виде строк и столбцов маленьких или больших иконок |
Компоненты вкладки Dialogs
Таблица 8.4. Компоненты вкладки Dialogs| Название | Название на русском языке | Краткое описание компонента |
| OpenDialog | Диалог открытия файла | Отображает стандартное диалоговое окно, позволяющее открыть любой файл по его имени |
Отображает стандартное диалоговое окно, позволяющее
Таблица 8.4 (окончание)| Название | Название на русском языке | Краткое описание компонента |
| SaveDialog | Диалог сохранения файла | Отображает стандартное диалоговое окно, позволяющее сохранить данные в виде файла с заданием его имени |
| FontDialog | Диалог выбора шрифта | Отображает стандартное диалоговое окно, позволяющее выбрать нужный шрифт и задать его стилевые особенности (размер, начертание и т. д.) |
| ColorDialog | Диалог выбора цвета | Отображает стандартное диалоговое окно, позволяющее выбрать необходимый цвет |
| FindDialog | Диалог поиска текста | Отображает стандартное диалоговое окно, позволяющее набрать фрагмент текста (строку) для поиска и осуществить этот поиск |
| ReplaceDialog | Диалог поиска и замены | Отображает стандартное диалоговое окно, позволяющее произвести поиск введенной строки текста и замену этой строки на необходимую, которая также должна быть введена |
Пятая вкладка называется Data Access и показана Рисунок 8.5.
Компоненты вкладки Data Access
Таблица 8.5. Компоненты вкладки Data Access| Название | Название на русском языке | Краткое описание компонента |
| DataSource | Источник данных | Невизуальный компонент, который служит "каналом" для передачи данных между набором данных и компонентами, отображающими данные, такими как DBGrid |
Невизуальный компонент, представляющий собой набор
Таблица 8.5 (окончание)| Название | Название на русском языке | Краткое описание компонента |
| ClientDataSet | Клиентский набор данных | Невизуальный компонент, представляющий собой набор данных, содержащий данные в оперативной памяти. Он может быть использован при создании локальных баз данных |
| DataSet Provider | Поставщик данных | Невизуальный компонент, который формирует пакеты данных для отправки клиентам |
Компоненты вкладки dbExpress
Таблица 8.6. Компоненты вкладки dbExpress| Название | Название на русском языке | Краткое описание компонента |
| SQLConnection | SQL-соединение | Компонент для обеспечения связи с сервером базы данных dbExpress |
| SQLDataSet | Набор данных SQL | Представляет собой набор данных, работающий с базами данных dbExpress |
| SQLQuery | SQL-запрос | Компонент, позволяющий создавать и выполнять SQL-запросы для работы с таблицами баз данных dbExpress |
| SQLStoredProc | Хранимая SQL-процедура | Хранимая на сервере dbExpress процедура, выполняемая с помощью соответствующего вызова |
| SQLTable | SQL-таблица |
и ClientDataSet, этот компонент сохраняет
Таблица 8.6 (окончание)| Название | Название на русском языке | Краткое описание компонента |
| SQLClientDataSet | Набор данных SQL-клиента | Как и ClientDataSet, этот компонент сохраняет в оперативной памяти данные и любые изменения, сделанные приложением в физические таблицы |
Компоненты вкладки Data Controls
Таблица 8.7. Компоненты вкладки Data Controls| Название | Название на русском языке | Краткое описание компонента |
| DBGrid | Сетка | Содержащий данные компонент, предназначенный для отображения и редактирования данных в табличном виде, похожем на лист электронной таблицы |
| DBNavigator | Навигационный интерфейс | Содержащий данные компонент, имеющий кнопки для перемещения по записям набора данных, вставки, редактирования и просмотра, а также сохранения новых или измененных данных в физической таблице |
| DBText | Надпись | Содержащий данные компонент, метка, которая отображает значение какого-либо поля текущей записи набора данных |
| DBEdit | Поле ввода | Содержащий данные компонент, предназначенный для отображения или редактирования значения какого-либо поля текущей записи набора данных |
Содержащий данные компонент, предназначенный для
Таблица 8.7 (окончание)| Название | Название на русском языке | Краткое описание компонента |
| DBMemo | Мемо-поле | Содержащий данные компонент, предназначенный для отображения или редактирования BLOB-текста текущей записи набора данных |
| DBImage | Графический образ | Содержащий данные компонент, предназначенный для отображения, копирования или вставки растровой картинки в нее или в текущую запись набора данных |
| DBListBox | Список | Содержащий данные компонент, применяемый для отображения и прокрутки списка значений из столбца таблицы |
| DBGomboBox | Комбинированный список | Содержащий данные компонент, предназначенный для отображения или редактирования прокручиваемого списка значений из столбца таблицы |
| DBCheckBox | Независимый переключатель | Содержащий данные компонент, который применяется для отображения или редактирования поля логического типа текущей записи набора данных |
| DBRadioGroup | Группа зависимых переключателей | Содержащий данные компонент, представляющий собой группу зависимых переключателей, предназначенных для отображения или установки значений столбца |
| DBLookupListBox | Простой список | Его значения формируются по полю другого набора данных |
| DBLookupComboBox | Комбинированный список | Его значения формируются по полю другого набора данных |

Компоненты вкладки Internet
Таблица 8.8. Компоненты вкладки Internet| Название | Название на русском языке | Краткое описание компонента |
| WebDispatcher | Диспетчер Web | Конвертирует обычный модуль данных в Web-модуль и позволяет приложению Web-серверу отвечать на запросы клиентов |
| Page Producer | Составитель страниц | Конвертирует HTML (Hypertext Transfer Protocol)-шаблоны в строки HTML-команд, которые могут обрабатываться приложением-клиентом, например Web-обозревателем |
| DataSetTableProducer | Составитель таблиц набора данных | Монтирует последовательность HTML-команд для отображения записей набора данных в виде таблицы |
| DataSetPageProduCer | Составитель страниц набора данных | Конвертирует HTML-шаблоны, содержащие поля набора данных, в строки HTML-команд, которые могут обрабатываться приложением-клиентом, таким как Web-обозреватель |
| SQLQueryTableProducer | Составитель таблиц из объектов типа TSQLQuery | Монтирует последовательность HTML-команд для отображения записей из объектов типа TSQLQuery в виде таблицы |
| TcpClient | TCP-клиент | Добавляет на форму или модуль данных объект типа TTCPClient для "превращения" приложения в приложение-клиент TCP/IP (Transmission Control Protocol/Internet Protocol). TCP-клиент устанавливает желаемое соединение с TCP/IP-сбрвером, обслуживает текущее соединение и завершает соединение |
| TcpServer | TCP-сервер | Добавляет на форму или модуль данных объект типа TTCPServer для "превращения" приложения в приложение-сервер TCP/IP. TCP-сервер ожидает запросы на TCP/IP-соединение от других компьютеров сети, и если такой запрос получен — устанавливает соединение |
Добавляет на форму или модуль
Таблица 8.8 (окончание)| Название | Название на русском языке | Краткое описание компонента |
| UdpSocket | UDP-сокет | Добавляет на форму или модуль данных объект типа TUDPSocket для "превращения" приложения в UDP/IP (User Datagram Protocol/ Internet Protocol)-клиент или сервер |
Первая из этих трех вкладок носит имя Indy Clients (Рисунок 8.9).
Компоненты вкладки Indy Clients
Таблица 8.9. Компоненты вкладки Indy Clients| Название | Название на русском языке | Краткое описание компонента |
| IdTCPClient | TCP-клиент | Инкапсулирует полную функциональность TCP-клиента, включая поддержку сокетов, и может быть использован для создания заказных программных средств |
| IdUDPClient | UDP-клиент | Инкапсулирует полную функциональность UDP-клиента и может быть использован для создания заказных программных средств |
| IdDayTime | Дата/время | Обеспечивает поддержку протокола даты/времени (RFC 876) как клиент |
| IdDNSResolver | Разрешитель DNS | Запрашивает DNS (Domain Name Server) для различных типов записей доменных имен |
Компонент поддерживает протокол Trivial File
Таблица 8.9 (окончание)| Название | Название на русском языке | Краткое описание компонента |
| IdTrivialFTP | TrivialFTP-клиент | Компонент поддерживает протокол Trivial File Transfer как клиент |
| IdWhois | Whois-клиент | Поддерживает протокол Nickname или Whois (RFC 954) как клиент |
Обеспечивает поддержку протокола Finger User
Таблица 8.9 (продолжение)| Название | Название на русском языке | Краткое описание компонента |
| IdEcho | Эхо | Обеспечивает поддержку эхо-протокола (RFC 862) |
| IdFinger | Указатель | Обеспечивает поддержку протокола Finger User Information (RFC 1288) как клиент |
| IdFTP | FTP-клиент | Обеспечивает поддержку протокола передачи файлов File Transfer Protocol (RFC 959) как клиент |
| IdGopher | Gopher-клиент | Обеспечивает поддержку протокола Internet Gopher (RFC 1436) как клиент |
| IdHTTP | HTTP-клиент | Обеспечивает поддержку HTTP-протокола, в том числе модификации HTTP 1.0 (RFC 1945) и HTTP 1.1 (RFC 2616) как Web-обозреватель |
| IdlcmpClient | ICМР-клиент | Данный компонент предназначен для отправки пакетов Internet Control Message на другие компьютеры сети |
| IdPOP3 | РОР3-клиент | Данный компонент обеспечивает поддержку протокола Post Office версии 3 (RFC 1939) для приема электронной почты как клиент |
| IdNNTP | NNTP-клиент | Обеспечивает поддержку протокола Network News Transfer (RFC 977) как клиент |
| IdQOTD | QOTD-клиент | Обеспечивает поддержку протокола Quote of the Day (RFC 865) как клиент |
| IdRawClient | Raw-клиент | Представляет собой потомок класса TidRawBase, который обеспечивает способность клиента использовать соединение Raw сокет |
| IdSMTP | SMTP-клиент | Компонент поддерживает протокол Simple Mail Transfer (RFC 821, 1869 и 2554) как клиент |
| IdSNTP | SNTP-клиент | Компонент поддерживает протокол Simple Network Time (RFC 2030) как клиент |
| IdTelnet | Telnet-клиент | Компонент поддерживает протокол Telnet как клиент |
| IdTime | Time-клиент | Компонент поддерживает протокол Time (RFC 868) как клиент |
Коды ошибок ввода/вывода
Таблица 9.1. Коды ошибок ввода/вывода| Linux | Windows | ||
| Код ошибки | Описание | Код ошибки | Описание |
| 2 | Нет файла или каталога | 2 | Файл не найден |
| 3 | Путь к файлу не найден | ||
| 5 | Ошибка ввода/вывода | 5 | Доступ запрещен |
| 13 | Доступ запрещен | ||
| 20 | Не является каталогом | ||
| 21 | Является каталогом | ||
| 32 | Ошибка совместного использования файла | ||
| Ошибки, не зависящие от операционной системы | |||
| Код ошибки | Описание | ||
| 100 | Достигнут конец файла | ||
| 101 | Диск полон | ||
| 102 | Файловая переменная не назначена | ||
| 103 | Файл не открыт | ||
| 104 | Файл не открыт для ввода | ||
| 105 | Файл не открыт для вывода | ||
| 106 | Ошибка ввода по формату | ||
| 107 | Файл уже открыт | ||
Примечание
Не путайте классы исключений EInvalidOp и EInvalidOperation!
базы данных dbExpress
Таблица базы данных dbExpressможет содержать разнотипные
Таблица может содержать разнотипные данные. Например, пусть таблица состоит из четырех полей: Number, Year, Name и Surname. Эти поля будут обозначать: порядковый номер записи, год рождения, имя и фамилию людей, занесенных в нашу таблицу. Таким образом, первое и второе поле будутчисловыми, а третье и четвертое — символьными. Заполняя данными эти поля, мы будем заносить записи в таблицу базы данных.
В таблицах могут использоваться ключи и индексы.
Ключ — это одно или несколько полей, содержащих уникальные для каждой записи данные.
Ключевое поле — это поле, которое определяет ключ.
Таким образом, по известным данным ключевого поля можно найти единственную запись в таблице, содержащую эти данные.
Ключи можно поделить нa простые и составные:
Обычно ключевые поля в большинстве баз данных автоматически индексируются.
Среда Kylix поддерживает таблицы баз данных InterBase, Oracle, DB2 и MySQL. Если вы хотите использовать таблицы других типов, вам придется написать собственный драйвер для работы с ними либо преобразовать эти таблицы в поддерживаемые средой Kylix.
Назад Вперед
Различные дистрибутивы Linux иногда размещают
Таблица П1 (окончание)| Каталоги |
Содержание |
| /var |
Log-файлы, сообщения |
| /proc |
Виртуальная файловая система и отчет системы |
| /tmp |
Временные файлы |
Различные дистрибутивы Linux иногда размещают файлы в других каталогах. Программы-утилиты могут располагаться в каталоге /bin в дистрибутиве Red Hat Linux и в /usr/local/bin в дистрибутиве Debian Linux.
Вы можете получить дополнительную информацию об организации файловой системы в Linux, обратившись по ссылке www.pathname.com.
Назад
П1 Основные каталоги Linux
Таблица П1. Основные каталоги Linux| Каталоги |
Содержание |
| / |
Корневой, верхний, каталог файловой системы Linux |
| /root |
Корневой (домашний) каталог для суперпользователя (root) |
| /bin |
Команды, утилиты |
| /sbin |
Системные утилиты |
| /dev |
Устройства, которые изображены как файлы |
| /lib |
Библиотеки |
| /home/username |
Файлы, принадлежащие пользователю, вошедшему в систему под именем |
| /opt |
Дополнительный каталог |
| /boot |
Ядро, которое запускается при загрузке системы |
| /etc |
Файлы конфигурации |
| /usr |
Приложения, программы. Обычно включает каталоги типа /usr/spool, /usr/man, /usr/include, /usr/iocal |
| /mnt |
Другие медиа-устройства, смонтированные в системе, такие как проигрыватель компакт-дисков (CD-ROM) или флоппи-дисковод (FD-Drive) |
со строками
Таблица со строкамиТаблица
Таблица/
баз данных
Таблицы баз данныхВ реляционной базе данных, как уже отмечалось выше, для хранения данных используются взаимосвязанные таблицы. Эти таблицы обычно находятся в одном каталоге на диске. Этот каталог представляет собой базу данных, а файлы — таблицы. Таблицы баз данных очень похожи на электронные таблицы. Каждая таблица обычно состоит из нескольких файлов. Эти файлы содержат данные, индексы и др. Имя файла, содержащего данные, является именем таблицы. Остальные файлы таблицы имеют такое же имя, отличаясь только расширениями.
Рассмотрим структуру таблицы (Рисунок 15.3).
Типы данных
Типы данныхЭта глава представляет обзор типов данных, которые имеются в языке Object Pascal. Мы рассмотрим как простые типы данных, так и структурные, вариантные и процедурные типы данных. Кроме того, кратко остановимся на указателях.
Object Pascal представляет собой строго типизированный язык, который требует особого внимания при объявлении и использовании переменных, процедур и функций.
Тип данных определяет то множество значений, которые может принимать данная переменная или другой элемент программы. В зависимости от типа данных, с ними можно выполнять определенные действия. Например, над вещественными переменными можно производить любые арифметические операции, а со строковыми переменными такие операции недопустимы.
Мы разделим все типы данных языка Object Pascal на пять групп:
Вперед
Типы графических объектов
Типы графических объектовCLX Kylix предоставляет программисту несколько графических объектов, которые имеют собственные методы для рисования на канве, а также для загрузки и сохранения изображений в графические файлы. В табл. 13.1 приведены основные типы графических объектов CLX.
Указатели процедурные и вариантные типы данных
Указатели, процедурные и вариантные типы данныхКроме рассмотренных выше простых и структурных типов данных, в языке Object Pascal имеется еще несколько типов данных, не относящихся ни к тем, ни к другим. Рассмотрим их.
Указатели
Указатель — это переменная, в которой хранится адрес памяти, указывающий на начало размещения некоторых данных в памяти.
Указатели применяют для определения адреса в памяти конкретного объекта, например какой-либо переменной.
Переменные типа "указатель" содержат и изменяют свои значения в процессе выполнения программы.
Указатели бывают типизированными и нетипизированными.
Типизированный указатель — это указатель, который ссылается на данные определенного типа и указан при объявлении указателя или типа указателя.
Для объявления типа указателя используется специальный значок ^, который располагается перед типом адресуемых данных.
Приведем пример объявления типизированного указателя:
var
X, Y: Integer ; / / X и Y переменные типа Integer
Р: ^Integer ; / / Р - указатель типа Integer Нетипизированный указатель всегда имеет тип Pointer и ссылается на данные любого типа.
Пример объявления нетипизированного указателя:
var
Р: Pointer; / / Р - нетипизированный указатель типа Pointer Рассмотрим пример использования указателей и поясним на этом примере операции, допустимые над указателями (листинг 2.2)
Установка пакетов компонентов
Установка пакетов компонентовДля того чтобы установить собственные пакеты или пакеты, созданные другими разработчиками, вам необходимо выполнить следующие шаги:
1. В случае, когда вы устанавливаете новый пакет, скопируйте файлы пакета в каталог библиотеки Kylix. Убедитесь, что скопировали все необходимые файлы пакета (имеющие расширения so, dcp, dcu).
2. В главном меню Kylix выберите команду Component/Install Packages либо воспользуйтесь вкладкой Packages диалогового окна свойств проекта, вызываемого командой главного меню Kylix Project/Options (Рисунок 20.3)
3. В вызванном диалоговом окне вы можете увидеть список всех доступных пакетов. Для инсталляции любого пакета, имеющегося в списке, установите флажок напротив наименования пакета. Для удаления пакета из проекта уберите флажок напротив наименования пакета. Для просмотра компонентов, входящих в пакет, щелкните мышкой на имени пакета и нажмите кнопку Components в окне настройки проекта (см. Рисунок 20.1). На Рисунок 20 3 показан список компонентов, входящих в состав пакета Borland Database Components.
4. Для добавления нового пакета в список нажмите кнопку Add и в открывшемся окне выберите файл пакета.
5. Чтобы удалить пакет из списка, выберите пакет и нажмите кнопку Remove (см. Рисунок 20.1).
Компоненты пакета устанавливаются на вкладке палитры компонентов Kylix.
Установка свойств поля ID в окне Object Inspector
Рисунок 18.5. Установка свойств поля ID в окне Object Inspector
Установка свойств поля Name в окне Object Inspector
Рисунок 18.6. Установка свойств поля Name в окне Object Inspector
В Kylix
в KylixИз этой главы вы узнаете, как с помощью Kylix можно создавать приложения, использующие графику. Вы научитесь работать с объектом канвы или холста (Canvas), рисовать различные фигуры, строить графики и диаграммы. В конце этой главы мы создадим простую игровую графическую программу.
Kylix предоставляет программисту несколько способов работы с графикой. Для добавления графического элемента в ваше приложение вы можете вставить предварительно созданную картинку во время разработки приложения, создать картинку во время разработки приложения средствами Kylix или нарисовать ее во время работы приложения.
Общий обзор программирования графики в Kylix
Графические компоненты CLX инкапсулируют возможности Qt, которые позволяют достаточно легко добавлять графику в Linux-приложения.
Для рисования в Kylix (так же, как и в Delphi) используется канва объекта, на котором будет производиться рисование.
Канва (холст) — это свойство, имеющееся у некоторых объектов, входящих в CLX Kylix, которое позволяет рисовать на поверхности объекта, как на холсте.
Примечание
Далее по тексту мы будем использовать слово канва вместо слова холст, т. к. это слово более полно описывает поверхность для рисования.
Главное преимущество канвы объекта в том, что она наиболее эффективно использует ресурсы, и вы можете применять одни и те же методы для вывода графики на экран, принтер или графический образ. Канва объекта доступна программисту только во время работы приложения, таким образом, для обращения к канве нужно использовать команды языка Object Patscal.
Способ отображения графики в вашем приложении зависит от типа объекта CLX, канва которого используется для рисования. Если вы напрямую выводите рисунок на канву объекта управления, изображение будет выведено немедленно.
В то же время, если вы рисуете на канве объекта, находящегося вне экрана, например на канве объекта графического образа TBitmap, изображение не будет отображаться, пока не будет выполнено копирование из графического образа на канву элемента управления.
Примечание
Использование объекта TBitmap в консольных приложениях приведет к исключительной ситуации с выдачей сообщения "Имя проекта: невозможно соединиться с Х-сервером".
Применяя графику в своих приложениях, вы будете довольно часто использовать два основных понятия: черчение и рисование.
Черчение — это создание с помощью команд языка Object Pascal особых одиночных графических элементов, например линий и геометрических фигур.
Рисование — это создание готового (полного) графического образа на канве объекта.
Таким образом, рисование включает в себя черчение. В качестве примера можно рассмотреть прорисовку окна редактирования TEdit, который рисует сам себя, начертив сначала прямоугольник, а затем — текст внутри прямоугольника.
Вперед
Виртуальные методы
Виртуальные методыВиртуальные методы, в отличие от статических, поддерживают перегрузку, поэтому вызов таких методов для среды Kylix намного сложнее (заранее неизвестен адрес конкретного вызываемого метода). Для того чтобы решить эту проблему, Kylix строит таблицу виртуальных методов (Virtual Method Table), благодаря которой компилятор может определить адрес метода во время выполнения программы. Такая таблица содержит виртуальные методы не только самого класса или компонента, но и его предков. Естественно, хранение такой таблицы увеличивает расходы памяти, но вызов виртуальных методов выполняется быстрее, чем вызов динамических методов.
Описание виртуального метода выглядит следующим образом:
type TComponent = class
procedure MyProcedure; virtual; end;
В данном случае метод MyProcedure — виртуальный.
Назад Вперед
Вкладка Additional Эта вкладка содержит
Рисунок 8.2. Вкладка Additional Эта вкладка содержит компоненты (слева направо), перечисленные в табл. 8.2.Вкладка Commands
Рисунок 6.3. Вкладка CommandsВы можете запретить или разрешить показывать подсказки (Show tooltips) при наведении курсора на любую кнопку панели инструментов. Кроме того, имеется возможность разрешить или запретить показывать во всплывающих подсказках комбинации "горячих клавиш", выполняющих ту же функцию, что и кнопки панели инструментов.
Вкладка Common Controls
Рисунок 8.3. Вкладка Common ControlsДанная вкладка содержит 14 компонентов, которые указаны в табл. 8.3.
Вкладка Data Access
Рисунок 8.5. Вкладка Data AccessНа этой вкладке расположены всего три компонента, с помощью которых программа получает возможность обращаться к данным, записанным в таблицы баз данных. Табл. 8.5 кратко описывает эти компоненты.
Вкладка Data Controls
Рисунок 8.7. Вкладка Data ControlsОна содержит компоненты, позволяющие управлять данными таблиц баз данных. Эти компоненты перечислены в табл. 8.7.
Назад
Вкладка Data Controls
Данная вкладка содержит компоненты, предназначенные для отображения записей из наборов данных. Мы не будем рассматривать свойства каждого компонента этой вкладки. Мы лишь отметим два главных свойства этих компонентов:
Назад
Вкладка dbExpress
Вкладка dbExpressДанная вкладка содержит семь компонентов. Рассмотрим эти компоненты и их основные свойства.
Компонент TSQLConnetion — предназначен для обеспечения связи с сервером базы данных. В Delphi аналогом данного компонента является компонент TDatabase. Табл. 16.4 содержит перечень основных свойств данного компонента.
Рисунок 8.6. Вкладка dbExpress
Вкладка содержит компоненты доступа к базам данных dbExpress. Все эти компоненты описаны в табл. 8.6.
Вкладка Dialogs
Рисунок 8.4. Вкладка DialogsДанная вкладка содержит компоненты, предназначенные для создания диалоговых окон загрузки, сохранения файлов и т. д. Все эти компоненты перечислены в табл. 8.4.
Вкладка Events
Рисунок 6.7. Вкладка EventsДля того чтобы привязать к какому-либо событию процедуру-обработчик (event handler), достаточно сделать двойной щелчок кнопкой мыши в правой части вкладки событий напротив выбранного события. При этом активизируется окно редактора кода.
При выборе любого события справа от него появляется выпадающий список, содержащий все доступные обработчики событий. Разработчик может выбрать любую из программ-обработчиков. Эта функция полезна, когда разработчик связывает одну процедуру-обработчик с несколькими событиями.
Редактор кода — это полноценный текстовый редактор, который включает в себя дополнительные функции:
и многое другое.
Когда разработчик начинает новый проект, Kylix добавляет новую страницу (модуль) в редакторе кода для главной формы. По умолчанию ей присваивается имя Unit1 .pas (см. Рисунок 4.2).
Если в проекте присутствует несколько форм, то для каждой формы в редактор кода добавляется новый модуль (Unit2, Unit3 и т. д.). Разработчик может сам добавлять новые модули (Unit) при помощи пункта меню главного окна Kylix File/New/Unit (Файл/Новый/Модуль). При этом важно помнить, что для каждой формы Kylix автоматически создает модуль, т. е. форма обязательно связана с каким-либо модулем проекта. Если модуль был создан разработчиком, то он является независимым и не связан ни с какой формой проекта. В такой модуль удобно выносить подпрограммы, используемые разными модулями проекта либо разными проектами. Редактор кода состоит из двух частей: окна просмотра и редактирования кода (Code Browser) и окна проводника (Code Explorer).
Окно просмотра и редактирования кода отображает весь программный код, связанный с текущим модулем. Это окно позволяет мгновенно проверять синтаксис вводимых команд, а также выводить подсказки. Настроить окно просмотра и редактирования кода можно с помощью пункта главного меню Kylix Tools/Editor Options (Средства/Настройки редактора). После выполнения этой команды появляется окно свойств редактора (Editor Properties) (Рисунок 6.8). Оно содержит пять вкладок: General, Display, Key Mappings, Color, Code Insight.
Вкладка Indy Clients
Рисунок 8.9. Вкладка Indy ClientsВсе компоненты, расположенные на данной вкладке, кратко описаны в приведенной ниже табл. 8.9.
Вкладка Indy MiscКомпоненты этой вкладки
Рисунок 8.11. Вкладка Indy MiscКомпоненты этой вкладки описываются в табл. 8.11.Вкладка Indy Servers
Рисунок 8.10. Вкладка Indy ServersКомпоненты, расположенные на этой вкладке, перечислены в табл. 8.10.
Вкладка Internet
Рисунок 8.8. Вкладка InternetВсе компоненты вкладки Internet кратко описаны в табл. 8.8.
Вкладка Options
Рисунок 6.4. Вкладка OptionsПалитра компонентов сразу после установки Kylix содержит девятнадцать вкладок, на которых расположены компоненты в виде значков. Каждая вкладка объединяет компоненты по назначению. Палитру компонентов можно настраивать по своему усмотрению с помощью окна Palette Properties. Открыть это окно можно при помощи контекстного меню, вызываемого щелчком правой кнопки на палитре компонентов или с помощью пункта меню главного окна Kylix Component/Configure Palette (Компонент/ Конфигурация палитры). Палитра компонентов состоит из следующих вкладок:
Разработчик размещает на форме необходимые компоненты из палитры компонентов простым перетаскиванием. С помощью мыши можно изменять размеры формы, а также ее положение на экране. Разрабатываемое приложение может содержать неограниченное число форм.
Компоненты, расположенные на вкладках панели компонентов, делятся на:
Примечание
Визуальные компоненты могут быть не видны на форме, если они перекрыты другими компонентами или свойство видимости компонента (Visible) имеет значение False.
Невизуальными называются компоненты, которые отображаются на форме во время создания приложения в виде небольших значков и не отображаются на форме во время выполнения приложения.
Для настройки свойств, методов и событий компонентов используется Инспектор объектов (Object Inspector) (Рисунок 6.5).
Инспектор объектов предназначен для выполнения трех основных функций:
Вкладка Standart
Рисунок 8.1. Вкладка StandartНа этой вкладке расположены стандартные компоненты, такие как кнопки, фреймы, меню и т. д.
Рассмотрим по порядку (слева направо) компоненты, расположенные на этой вкладке (табл. 8.1).
Введение в создание компонентов
Введение в создание компонентовДанная глава посвящена творческому процессу создания собственных компонентов. Мы рассмотрим различные способы создания новых компонентов, а именно — как создавать невизуальные и визуальные компоненты.
Основы создания компонентов
Итак, мы приступаем к процессу создания собственного визуального или невизуального компонента. Для создания собственного компонента важно иметь представление о библиотеке визуальных компонентов Kylix, об иерархии компонентов. Все это вам уже знакомо.
Для чего же нужны новые компоненты? Зачем их создавать? Решение о создании новых компонентов может быть принято по ряду причин, среди которых:
Создание компонентов по сложности практически не отличается от создания приложений. Конечно, все зависит от сложности компонента. Но если вы уже решились на создание компонента, рекомендации будут следующими:
Вперед
Выбор предка компонента
Выбор предка компонентаИтак, вы уже знаете основные классы, имеющиеся в CLX Kylix. Ранее мы рассмотрели базовые классы, которые могут являться предками вашего компонента (см. главу 7). Эти классы перечислены в табл. 19.1.
Выражения и операторы
Выражения и операторыВ этой главе мы рассмотрим такие конструкции языка Object Pascal, как выражения и операторы. Вы узнаете об арифметических, логических и строковых выражениях языка Object Pascal. Кроме того, мы расскажем о простых и структурированных операторах, операторах условия, выбора и цикла.
Выражения
Выражения представляют собой конструкцию языка, которая содержит данные, операции и имеется строгий порядок выполнения операций.
В общем случае, в состав выражения входят:
Знаки операций — это знаки, определяющие конкретные действия, которые должны быть произведены над операндами. Операции могут производиться над одним операндом и над несколькими операндами. Если операция производится над одним операндом, то знак операции ставится перед операндом, например -х. Если операция производится над двумя или несколькими операндами, знак операции ставится между операндами, например х*12.
Скобки — круглые скобки, которые служат для определения порядка выполнения операций, например, (х+у) /2.
Вперед
Вывод сообщений
Вывод сообщенийДиректива компилятора $MESSAGE позволяет вашему приложению выводить подсказки сообщения и ошибки таким образом, как это делает компилятор:
{$MESSAGE HINT|WARN | ERROR | FATAL ' строка текста'}
Тип сообщения выбирается вами из перечисленных выше. Если тип не указан, компилятор по умолчанию будет выводить подсказку (HINT). Строка текста — это текст сообщения. Она должна быть заключена в апострофы. Например:
{$MESSAGE 'Подсказка'} // выводит подсказку
{$Message Hint 'Подсказка 2'} // тоже выводит подсказку
{$Message Warn 'Внимание!'} // выводит предупреждение
{$Message Error 'Не поддерживается'} // выводит ошибку и компиляция
// продолжается
{$Message Fatal 'Фатальная ошибка'} // выводит ошибку и прерывает
// процесс компиляции Назад Вперед
Загрузка и сохранение графических файлов
Загрузка и сохранение графических файловГрафические образы, которые используются в приложении, иногда требуется сохранить для дальнейшего использования. Компонент Image позволяет достаточно просто и эффективно загружать графику из файла и сохранять в файл.
Компоненты CLX, которые можно использовать для загрузки, сохранения и других действий с графикой, поддерживают несколько графических форматов: bmp, png, xpms, ico и др.
Загрузка графического образа из файла
Если ваше приложение позволяет изменять готовые изображения или создавать новые, необходимо обеспечить возможность загрузки графики из файла. Для этого можно воспользоваться специальным методом LoadFromFile,который имеется у всех компонентов CLX, способных работать с графикой.
Нижеприведенный пример (листинг 13.19) вызывает диалоговое окно открытия файла и получает из него имя файла, содержащего графический образ. Затем происходит загрузка этого образа в компонент Image1.
Замещенные методы
Замещенные методыЗамещение методов предполагает передачу и изменение методов от компонента (класса) предка компоненту (классу) наследнику. Как мы уже отметили, только виртуальные или динамические методы могут быть замещенными. Рассмотрим пример:
type TComponentChild = class (TComponentParent) procedure MyProcVirtual; override; procedure MyProcDynamic; override; end;
Применение служебного слова override после названия метода позволяет заместить оригинал метода компонента предка методом компонента наследника. При этом замещение происходит непосредственно в таблице виртуальных методов (или таблице динамических методов). При использовании служебных слов virtual или dynamic вместо override произойдет создание нового метода вместо замещения старого.
Замещение методов не работает со статическими методами — при замещении статического метода новым произойдет простая замена метода родителя в потомке.
Назад Вперед
Защита ресурсов
Защита ресурсов
Программирование: Языки - Технологии - Разработка
- Программирование
- Технологии программирования
- Разработка программ
- Работа с данными
- Методы программирования
- IDE интерфейс
- Графический интерфейс
- Программирование интерфейсов
- Отладка программ
- Тестирование программ
- Программирование на Delphi
- Программирование в ActionScript
- Assembler
- Basic
- Pascal
- Perl
- VBA
- VRML
- XML
- Ada
- Lisp
- Python
- UML
- Форт
- Языки программирования