Иллюстрированный самоучитель по Kylix

Общий обзор языка

Введение
Для операционной системы 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 входят следующие символы:

  • набор символов ASCII, включающий буквы латинского алфавита от а до z и от А до z и пробел, а также цифры от о до 9;
  • специальные символы: # $ & ; ' ( ) * + , - . / : ; & lt; = > @ [ ] ^ { } ;
  • дополнительные специальные символы, которые являются комбинациями специальных символов:
    • (* и *) — ремарка, пояснение. Является альтернативой символам фигурных скобок { и };

    • ( . и . ) — применяется для индексов массива, работы со строками и в других случаях. Данные символы можно использовать вместо квадратных скобок [ и ];

    • .. — применяется для определения диапазона значений;

    • / / — ремарка, пояснение. Символы, находящиеся справа от данной комбинации символов, игнорируются компилятором и считаются пояснением;

    • : = — символ присваивания;

    • <= — меньше или равно;

    • >= - больше или равно;

    • <> — не равно;

    Примечание

    Символы ! , ", % , ?, \, _, ~ не являются специальными символами языка Object Pascal.

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

    Все слова условно делятся на три большие группы:
  • зарезервированные слова (reserved words);
  • директивы (directives);
  • идентификаторы (identifiers).
  • Зарезервированные слова — это слова, входящие непосредственно в язык 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), так и создаваемые программистом.

    Идентификаторы должны создаваться по следующим правилам:
  • длина идентификатора не должна превышать 255 символов;
  • идентификатор может содержать в себе буквы, цифры и знак подчеркивания ( _ );
  • идентификатор всегда должен начинаться с буквы или символа подчеркивания, но он не может содержать внутри себя пробелы;
  • идентификатор может состоять из строчных или прописных букв, а также из комбинации тех и других. Компилятор не чувствителен к регистру букв, поэтому приведенные далее идентификаторы рассматриваются им как одинаковые: MyLabel, MYLABEL, mylabel
  • между каждыми двумя идентификаторами обязательно должен присутствовать хотя бы один разделитель.
  • Назад Вперед

    Архитектура баз данных

    Архитектура баз данных

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

    На рис, 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 как версия VCL

    Kylix использует библиотеку компонентов 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).

    Назад Вперед

    Директивы компилятора

    Директивы компилятора

    Директивы компилятора — это указания компилятору на выполнение каких-либо действий. Для записи директив компилятора используют символы:

    {$ директива} либо( * директива *)

    Все директивы компилятора делятся на:
  • глобальные;
  • локальные.
  • Глобальные директивы компилятора действуют на весь компилируемый файл.

    Локальные директивы действуют от места их появления до появления отменяющей директивы.

    Имеется три вида директив компилятора:

  • ключевые директивы;
  • директивы параметров;
  • директивы условной компиляции.
  • Первые два вида директив могут быть установлены по умолчанию. Для того чтобы настроить эти установки, вы можете воспользоваться вкладкой Compiler (Компилятор) диалогового окна Project Options (Настройки проекта), вызываемого из главного меню Куliх Project/Options (Проект/Настройки).

    Назад

    Для чего используются пакеты

    Для чего используются пакеты

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

    Для того чтобы приложение использовало пакеты, необходимо установить флажок Build with runtime package в диалоговом окне Project Options на странице Packages. Для открытия этого диалогового окна используйте пункт главного меню Kylix Project/Options. При такой компиляции приложения оно значительно сократится в размерах (примерно в 8—10 раз), но вам придется при распространении приложения передавать и все применяемые им пакеты.

    Рассмотрим, когда нужно использовать пакеты, а когда — стандартные библиотеки разделяемых объектов Linux:

  • если вы хотите внедрить самостоятельно созданные компоненты в среду Kylix— создавайте пакеты. Помните, что пакеты Kylix поддерживаются только приложениями, созданными в Kylix или Borland Delphi 6;
  • если же вы хотите использовать созданную вами библиотеку различными приложениями, созданными в разных средах программирования, вам необходимо создать библиотеку разделяемых объектов (so).
  • С файлами пакетов связаны следующие расширения (табл. 20.1):



    Другие методы работы с графикой в Ку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 для буфера обмена удалит все содержимое буфера.

  • Метод Click служит для вызова обработчика события OnClick данного компонента. Применяется для имитации нажатия левой кнопки мыши над объектом. Например, для вызова обработчика события OnClick кнопки Button1 можно проделать следующее;
    Button1.Click;
  • Метод ClientToScreen применяется для преобразования координат клиентской области компонента в координаты экрана. Началом координат клиентской области является левый верхний угол клиентской области компонента, Началом координат экрана является левый верхний угол экрана. Для обратного преобразования координат можно использовать метод ScreenToClient.
  • Метод ContainsControl определяет, каким наследником (прямым или косвенным) является данный компонент по отношению к какому-либо оконному компоненту. Если этот компонент прямой наследник, то метод возвращает true, иначе — false.
  • Метод ControlAtPos предназначен для оконных компонентов. Он применяется для того, чтобы определить, какой дочерний компонент находится в позиции с координатами, задаваемыми параметром Pos. В случае, если в заданной позиции нет ни одного дочернего компонента, данный метод возвращает в качестве результата значение nil. Второй параметр AllowDisabied определяет, нужно ли учитывать при вызове метода те компоненты, которые отключены (свойство Disabled = true).
  • Метод CopyRect применяется для копирования прямоугольной части изображения с одной канвы на другую. Копирование осуществляется в том режиме, который определен свойством CopyMode.
  • Метод Delete применяется по отношению к таким компонентам, как TList, TStringList, TStrings и TMenuItem. Данный метод вызывается при необходимости удаления какого-либо элемента из списка. В качестве параметра этого метода передается число, определяющее индекс удаляемого элемента. Нумерация элементов начинается с нуля. При удалении пункта меню, содержащего Подменю, удаляется и этот пункт, и его подменю.
    Примечание

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

  • Метод Destroy применяется для вызова деструктора объекта. То есть вызов данного метода уничтожает данный объект и освобождает занимаемую память.
    Примечание

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

  • Метод DisableAlign применяется для временного запрета выравнивания дочерних компонентов оконного компонента. Обратное действие можно получить, воспользовавшись методом EnableAlign.
  • Метод Dormant используется для создания битовой матрицы в оперативной памяти для освобождения дескриптора матрицы. Использование данного метода позволяет сократить расходы ресурсов графической подсистемы Linux, которые используются приложением. Приведем пример (листинг 8.1).


  • Функции языка 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 находится справа от меню), и содержат кнопки для вызова некоторых команд меню главного окна. Панели подразделяются по функциональному назначению:

  • стандартная панель (Standard) содержит кнопки для работы с файлами проекта и позволяет создавать, сохранять и удалять файлы проекта;
  • панель просмотра (View) служит для работы с формами и текстом программ;
  • панель отладки (Debug) — для запуска и отладки приложения;
  • панель пользователя (Custom) предназначена для размещения кнопок, необходимых разработчику;
  • панель рабочий стол (Desktop) — позволяет сохранять и восстанавливать сведения о том, какие окна среды разработки открыты и где именно они расположены на экране. Такие сведения называются конфигурацией рабочего стола Kylix. Среда Kylix позволяет создавать и сохранять несколько конфигураций рабочего стола. Кроме того, можно выделить конфигурацию, которая будет автоматически загружаться в режиме отладки (debug desktop) и выгружаться при выходе из него. Для вышеперечисленных целей можно использовать кнопки: Save current desktop и Set debug desktop.
  • Вы можете сами указывать кнопки, которые будут располагаться на тех или иных панелях при помощи диалогового окна Настройки (Customize) (Рисунок 6.2). Это окно можно вызвать из контекстного меню, щелкнув правой кнопкой в области панели управления, либо воспользоваться пунктом меню Kylix View/Toolbars/Customize (Просмотр/Панели управления/Настройка).

    Главное окно Kylix

    Графический интерфейс пользователя

    Графический интерфейс пользователя.

    И регенерация исключений

    и регенерация исключений

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



    Иерархия классов CLX

    Иерархия классов CLX

    Как уже говорилось ранее, библиотека классов CLX содержит наиболее применяемые компоненты, из которых строится ваше приложение. Так как в языке Object Pascal объекты создаются путем наследования, библиотека классов CLX построена по иерархическому принципу. Рассмотрим иерархию компонентов CLX (Рисунок 7.1).

    Приведенный Рисунок 7.1 требует некоторых пояснений. Отметим, что данный рисунок показывает полную иерархию классов Kylix. Компоненты CLX являются лишь составной частью этой иерархии и начинаются с класса TComponent, который является базовым для всех компонентов CLX.

    Далее рассмотрим полную иерархию классов Kylix.

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

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


  • Информация о типе во времени выполнения

    Информация о типе во времени выполнения

    Информация о типе во время выполнения (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


    Из данной главы вы:

  • узнаете, что представляет собой среда Kylix;
  • изучите основные окна среды;
  • научитесь настраивать среду.
  • Возможности Kylix

    Средство для быстрой разработки приложений (Rapid Application Development, RAD) Borland Kylix было создано в 2001 году. Корпорация Borland предлагает два основных варианта Kylix:

  • Kylix Desktop Developer;
  • Kylix Server Developer.
  • Рассмотрим возможности среды и отличия в возможностях данных вариантов (табл. 6.1).



    Интерфейс 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 — цвет кисти;
  • Style — стиль кисти;
  • Bitmap — графический образ, который будет применяться для заполнения.
  • Значения этих свойств определяют способ, которым будут заполняться геометрические фигуры и области канвы. По умолчанию значения установлены следующим образом: цвет кисти — белый, стиль — сплошной, без графического образа для заполнения.

    Рассмотрим эти свойства более подробно.

    Цвет кисти

    Цвет кисти определяет, какой цвет будет использоваться для заполнения внутренних областей геометрических фигур и областей канвы. Для смены цвета кисти достаточно присвоить необходимое значение свойству 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 вы должны выполнять следующие требования:

  • при объявлении интерфейса явно объявляйте в качестве предка интерфейс Iunknown, т. к. только в этом случае вы сможете воспользоваться оператором as;
  • если вы используете оператор as для интерфейса, данный интерфейс должен иметь свой IID. Напомним, что для создания нового IID достаточно, находясь в редакторе кода, нажать комбинацию клавиш + ++.
  • Назад Вперед

    Использование пакетов в приложениях

    Использование пакетов в приложениях

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

    Примечание
    При разработке коммерческих приложений обратите внимание на то, чтобы пользователи получили правильную версию файлов пакетов (so).

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

    1. Загрузите или создайте новый проект в среде Kylix.

    2. В главном меню Kylix выберите Project/Options.

    3. В открывшемся диалоговом окне выберите вкладку Packages (Рисунок 20.1).

    4. Установите флажок Build with runtime package. Затем в открывшееся поле введите одно или несколько названий пакетов, которые вы хотите использовать в своем приложении. Вы можете воспользоваться также кнопкой Add для поиска необходимого пакета (Рисунок 20.2).


    Использование пера

    Использование пера

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

    Перо имеет четыре собственных свойства, которые вы можете изменять:
  • Color — цвет пера;
  • Width - ширина пера;
  • Style — стиль пера;
  • Mode — режим пера.
  • Значения данных свойств определяют способ, которым будут отображаться точки линий. По умолчанию установлен черный цвет пера и его ширина равна одному пикселу, стиль — сплошной, режим рисования поверх текущего изображения канвы.

    Рассмотрим последовательно использование этих четырех свойств.

    Цвет пера

    Вы можете устанавливать цвет пера по своему усмотрению с помощью свойства Color во время исполнения приложения. Для этого нужно лишь присвоить соответствующее значение цвета свойству Color пера Реn.

    В листинге 13.3 мы устанавливаем красный цвет пера (значение clRed) по нажатии кнопки Button1.



    Использование специальных директив

    Использование специальных директив

    Использование директивы компилятора $IFDEF является достаточно разумным путем для разделения кода Windows и Linux в вашем межплатформенном приложении. Тем не менее, использование директивы $IFDEF делает код приложения более трудным для понимания, поэтому старайтесь применять эту директиву как можно реже.

    Пользуясь директивой $IFDEF, следуйте нижеприведенным указаниям:

  • постарайтесь не применять директиву $IFDEF без крайней необходимости. Эта директива применяется в исходном файле только после компиляции;
  • не используйте директиву $IFDEF в файлах пакетов (dpk). Создателям компонентов нужно разработать два пакета для каждой из платформ без использования директивы $IFDEF;
  • применяйте директиву $IFDEF MSWINDOWS для проверки того, что приложение запущено в среде Windows. Используйте директиву $IFDEF WIN32 для определения различных Windows-платформ, например 32- и 64-битную версии Windows;
  • используйте директиву $IFDEF LINUX для проверки того, что приложение запущено в среде Linux;
  • избегайте в своих приложениях комбинации $IFNDEF/$ELSE. Пользуйтесь положительными тестами ($IFDEF/$ELSE) для лучшего понимания кода;
  • старайтесь использовать директивы $IFDEF MSWINDOWS и $IFDEF LINUX вместо комбинаций $IFDEF LINUX/$ELSE или $IFDEF MSWINDOWS/$ELSE.
  • Приведем пример неосторожного обращения с директивой $IFDEFF (листинг 21.4).



    Класс 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 включают в себя специальные возможности, которые называются завершение класса. Данные возможности позволяют упростить работу программиста по созданию нового класса. Упрощение происходит благодаря автоматическому генерированию скелета кода для членов класса, который вы определяете.

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

  • В интегрированной среде разработчика Kylix начните новый проект и выполните команду меню Kylix File/New Unit (Файл/Новый модуль). Таким образом вы создадите новый модуль проекта, в котором будет объявлен новый класс.
  • Добавьте в секцию интерфейса нового модуля (interface) секцию uses и type.
  • В секции type напишите объявление нового класса. Здесь вам необходимо объявить все внутренние переменные класса, свойства, методы и события класса.
  • Например,

    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) и нажмите комбинацию клавиш + ++ или щелкните правой кнопкой мыши и в выпадающем меню выберите пункт Complete Class at Cursor (Завершить класс в пределах курсора). Kylix завершит объявление каждого незавершенного свойства и создаст необходимые пустые методы в секции реализации (implementation). Если же ваша версия Kylix не поддерживает завершение классов, вам придется делать все самостоятельно.

    В приведенном ниже примере, если у вас есть завершение класса, 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 определяют наивысшую степень доступности.

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

    Рассмотрим все четыре ключевых слова более подробно.

  • Private (частные) — определяет элементы класса, которые не видны вне модуля, в котором был объявлен класс, содержащий эти элементы. Другими словами, частные методы не могут быть вызваны из других модулей, а частные поля или свойства не могут быть считаны или изменены из других модулей.
  • Protected (защищенные) — определяет элементы класса, которые видны только внутри модуля, где определен класс, содержащий эти элементы, а также внутри других модулей, где присутствуют классы-потомки данного класса.
  • Public (общедоступные) — определяет элементы класса, которые видны в любом месте программы и из любых модулей, в которых виден сам класс.
  • Published (опубликованные) — определяет элементы класса, имеющие ту же видимость, что и public-элементы. Единственное отличие заключается в том, что опубликованные элементы порождают информацию о типе времени выполнения (RTTI). Благодаря данной информации. Kylix может осуществить проверку принадлежности элементов объекта к тому или иному классу. Kylix использует RTTI для доступа к значениям свойств при сохранении и загрузке файлов форм, чтобы иметь возможность отобразить свойства в инспекторе объектов и ассоциировать конкретные методы с конкретными свойствами. Все методы классов могут быть опубликованы, за исключением перегруженных (overload) методов, имеющих одинаковые имена.
  • Перегруженными называются методы, которые имеют одинаковые имена, но используют в качестве параметров данные различных типов. В процессе вызова такого метода компилятор решает сам, какой из методов вызвать в зависимости от аргументов, передаваемых при вызове метода.

    В Kylix имеется понятие абстрактного класса.

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

    Все объекты в Kylix созданы из абстрактного класса TObject. Класс TObject — предок многих простых классов. Этот класс объединяет в себе основные функции, которые свойственны всем объектам Kylix. 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).

    Компонент Clients в окне модуля данных

    Компоненты для работы с базами данных

    Компоненты для работы с базами данных

    В этой главе мы рассмотрим основные компоненты, предназначенные для работы с базами данных. Компоненты расположены на вкладках Data Access, dbExpress и Data Controls.

    Вкладка Date Access

    На этой вкладке расположено всего три компонента, которые мы и рассмотрим.

    Компонент TDataSource - обеспечивает интерфейс между набором данных и компонентом, отображающим данные. В табл. 16.1 приведены его основные свойства и их описания.



    Консольные приложения

    Консольные приложения

    Консольные приложения — это 32-разрядные приложения, которые могут работать без загруженного графического интерфейса Linux.

    Для создания нового консольного приложения выберите пункт главного меню Kylix File/New и в появившемся диалоговом окне выберите пиктограмму Console Application (Рисунок 10.5).


    Координация потоков

    Координация потоков

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

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

  • Хранение локальных переменных в стеке потока. Так как любой поток приложения получает свой стек, он будет иметь собственные локальные переменные.
  • Сохранение локальных переменных в объекте потомка класса Tthread.
  • Хранение локальных переменных на уровне операционной системы с использованием в описании локальных переменных слова threadvar.
  • Первый способ является самым простым, очевидным и самым эффективным. Доступ к локальным переменным, расположенным в стеке потока, самый быстрый.

    Рассмотрим два других способа хранения локальных переменных потока. Второй способ проще и эффективнее чем третий (листинг 14.8).



    Координаты точек задаваемых при вызове метода Arc

    Рисунок 8.13. Координаты точек, задаваемых при вызове метода Arc

  • Метод Arc предназначен для рисования дуги окружности или эллипса. В качестве параметров метода передаются координаты четырех точек. Первые две точки (X1, Y1) и (X2, Y2) определяют прямоугольник, описывающий эллипс. Следующая точка (X3, Y3) определяет начальную точку
    дуги, которая находится на пересечении прямой, проходящей через центр окружности или эллипса и точки (X3, Y3). Точка (X4, Y4) определяет конечную точку дуги, которая находится на пересечении прямой, проходящей через центр окружности или дуги и точки (Х4, Y4). Дуга рисуется против часовой стрелки, от начальной до конечной точки (Рисунок 8.13).
    Для Рисунок 8.13 можно привести такой пример вызова метода Arc:
    Image1,Canvas.Arc (0,0, 200,100, 200,10, 0,0);
  • Метод Assign применяется для копирования данных одного объекта в другой. Настоящий метод имеет отличие от простого присваивания: объект1 : = объект2, которое заключается в том, что при присваивании указатель на объект-назначение начинает указывать на объект-источник, а метод Assign создает новую копию объекта. После применения метода Assign получается два объекта с одинаковыми данными. Если объекты разного типа, то при вызове D.Assign(S) тип D должен "знать", как скопировать в него тип S (тип S может ничего не знать о преобразовании типов). Если метод Assign не может осуществить преобразование типов, он вызывает защищенный метод AssignTo, объявленный в классе TPersistent и перегруженный в классах, производных от него. Вызов имеет вид S.AssignTo(D). Если и метод AssignTo не может осуществить преобразование или если он не перегружен, вызывается AssignTo класса TPersistent и генерируется исключение. Метод Assign можно применять в разных ситуациях." Хорошей иллюстрацией применения данного метода может служить копирование изображения из буфера обмена в графический компонент TImage:
    Image1.Picture.Assign (Clipboard);
    и, наоборот, из компонента в буфер обмена
    Clipboard.Assign (Image1.Picture);
  • Метод BeginDrag вызывается, когда начинается процесс перетаскивания компонента. Данный метод применяется только в том случае, если свойство DragMode компонента имеет значение dmManual. В случае, когда свойство имеет значение dmAutomatic, перетаскивание компонента осуществляется автоматически. Вызов данного метода обычно вставляют в обработчик события OnMouseDown. Параметр Immediate метода BeginDrag показывает, сразу ли после нажатия кнопки мыши указатель курсора сменит вид на тот, который определен в свойстве DragCursor, и сразу ли начнется процесс перетаскивания. В случае, если параметр Immediate имеет значение false, перетаскивание начинается только после того, как пользователь щелкнет на компоненте и сместит указатель мыши на расстояние и пять пикселов. Это удобно для того, чтобы обрабатывать щелчок на компоненте, не начиная его немедленного перетаскивания.
  • Метод BringToFront применяется для переноса компонента наверх в так называемой Z-последовательности, Z-последовательность определяет порядок компонентов в свойстве Controls родительского оконного компонента (см. разд "Иерархия визуальных компонентов" данной главы). Тот компонент, который расположен в Z-последовательности выше других, в случае частичного или полного перекрытия компонентов будет виден. Таким образом, вызов метода BringToFront позволит переместить "наверх" компонент, скрытый под другими компонентами. Данный метод можно применять как к неоконным, так и к оконным компонентам. Однако все неоконные компоненты располагаются в Z-последовательности ниже оконных, поэтому в случае, если неоконный компонент перекрыт оконным, например кнопка перекрыта компонентом типа TMеmо, вызов метода BringToFront для кнопки ничего не даст.
  • Метод BrushCopy вызывается для копирования части изображения битовой матрицы на область вывода (канву) и замены указанного цвета в изображении на значение, установленное для кисти канвы.
  • Метод CanFocus применяется для определения, может ли данный компонент получать фокус. Данный метод возвращает значение true, если у компонента и всех его родителей свойства Visible и Enabled имеют значения true.
  • Метод ChangeScale применяется для изменения масштаба компонента и всех его дочерних элементов При вызове настоящего метода масштабируются такие свойства компонента, как Tор, Left, Width, Height. Данный метод имеет два параметра, определяющих множитель и делитель масштаба: M и D. Приведем пример использования этого метода. Допустим, мы хотим увеличить размер формы Form1 в два раза, для этого зададим множитель масштаба, равный двум, а делитель - равный единице:
    Form1.ChangeScale (2,1);
    При выполнении данной строки размеры формы Form1 увеличатся в два раза.
    Для уменьшения размеров, например в три раза, нужно задать значение M, равное eдинице, а значение D — равное трем:
    Form1.ChangeScale (1,3);
  • Метод Chord применяется для рисования замкнутой фигуры, границами которой являются дуга окружности или эллипса и хорда. Параметры данного метода аналогичны параметрам метода Arc. Результатом работы настоящего метода могут стать фигуры, изображенные на Рисунок 8.14.
  • Метод ClassName применяется для определения имени типа компонента.
  • Метод Clear предназначен для удаления всех элементов, входящих в данный список, или для удаления всего текста, входящего в рассматриваемый компонент. Примеры:
    ListBox1.Clear;
    Memo1. Clear;
  • Координаты точек задаваемых при вызове метода Arc


    Кроссплатформенные Интернетприложения

    Кроссплатформенные Интернет-приложения

    Интернет-приложения — это приложения типа клиент-сервер, которые используют стандартные Интернет-протоколы для обеспечения связи между клиентом и сервером. Так как ваши приложения используют стандартные Интернет-протоколы, вы можете легко сделать ваше приложение межплатформенным. Например, программа — сервер Интернет-приложения соединяется с клиентом при помощи специального программного обеспечения, называемого 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.Описание базового интерфейса IUnknown

    type
    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 поддерживает три метода, которые наследуются всеми интерфейсами:

  • QueryInterface( ) — используется для создания запроса, поддерживается ли данный интерфейс, и если поддерживается, то метод возвращает указатель на него. Предположим, что имеется некоторый объект Object, который поддерживает несколько интерфейсов: Interface1, Interface2 и др. Для получения указателя на интерфейс Interface2 объекта Object вам нужно вызвать метод Interface2. QueryInterface( ) .
  • _AddRef ( ) — используется, когда получен указатель на данный интерфейс, и вы хотите использовать этот указатель. Метод _AddRef ( ) обязательно должен заканчиваться вызовом метода _Release ( ).
  • _Release ( ) — используется для завершения работы с интерфейсом.
  • Назад Вперед

    Определение класса TInterfacedObject

    Листинг 10.4. Определение класса TInterfacedObject

    type
    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. Использование ключевого слова implements

    unit 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

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

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

    Соединение-сервер прослушивает запросы сокетов на установление соединения. В случае, если сокет-клиент запрашивает от сокета-сервера соединение, сокет-сервер отсылает клиенту свое полное описание.

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

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

  • систему, под которой запущен данный сокет;
  • тип интерфейсов, которые понимает данный сокет;
  • номер порта, используемый сокетом для соединения.
  • Компоненты для создания сокетов располагаются на вкладке Internet палитры компонентов Kylix. Это компоненты TCPClient и TCPServer.

    Компонент 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.Код обработки события OnPaint

    procedure 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.Обработчик события OnMouseup

    procedure 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.Обработчик события OnMouseMove

    procedure 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.Создание объекта Bitmap

    procedure 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.Прямая работа с Bitmap

    procedure 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.Код обработки события OnClick

    procedure 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. Объект TThred

    TThread = 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. В автоматически сгенерированном файле, модуля вы можете:
  • инициализировать поток;
  • заполнить метод Execute объекта потока, разместив там функции и процедуры;
  • написать код гарантированного разрушения потока (например, строку FreeOnTerminate: =True;).
  • Назад Вперед

    Проверка прекращения работы потока

    Листинг 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-объектам в консольных приложениях вы должны использовать другие методы, такие как критические секции

    В некоторых случаях вы можете обходиться без метода синхронизации, например, если:

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

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

  • объекты для работы с графикой являются потокобезопасными. Это такие классы, как TFont, TPen, TBrush, TBitmap, TDrawing и TIcon;
  • вместо объектов списков (List), которые не являются потокобезопасными, вы можете использовать потокобезопасный потомок объекта TList — TThreadList.
  • Назад Вперед

    Объявление локальных переменных в потоке класса TThread

    Листинг 14.8.Объявление локальных переменных в потоке класса TThread

    type
    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.Модуль Ffactlin

    unit 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, а записи — в тэге ROW DATA. После создания новой таблицы базы данных тэг ROWDATA будет пустым.

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

    Теперь давайте запустим наше приложение, вставим в таблицу новую запись, закроем приложение и посмотрим, как изменился xml-файл.

    Мы видим, что изменился тэг PARAMS:



    Кроме того, тэг ROWDATA тоже изменился:



    ="e?AI?" />



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

    Если вам не нужно, чтобы этот журнал велся, в режиме выполнения программы установите свойство 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;Рассмотрим методы нового класса:

  • функция GetAttributes добавляет к унаследованному множеству атрибуты paDialog (при этом появляется кнопка в окне инспектора объектов) и paReadOnly (который применяется для того, чтобы редактирование данного свойства было возможно только через диалог);

  • функция GetValue заменяет символы перевода каретки (#10) и переход на новую строку (#13) на символ больше (>
    ).
  • Наконец, процедура Edit применяется для вызова диалога ввода строк всплывающей подсказки.

    Для регистрации нового редактора нужно в интерфейсной части модуля поместить Объявление Процедуры Register. После чего В части Implementation модуля написать саму процедуру регистрации (листинг 19.11).

    Процедура регистрации нового редактора свойствprocedure Register; begin

    Листинг 19.11. Процедура регистрации нового редактора свойствprocedure Register; begin

    RegisterPropertyEditor (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;

    Процедура регистрации нового редактора свойствprocedure Register; begin Процедура регистрации нового редактора свойствprocedure Register; begin Процедура регистрации нового редактора свойствprocedure Register; begin

    Метод диспетчеризации события TControl = class (TComponent) private

    Листинг 19.12. Метод диспетчеризации события TControl = class (TComponent) private

    FOnClick: 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; interface

    uses
    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

    Создание свойствамножества unit QMyButton;

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

    Листинг 19.5. Создание потомка TPersistenttype

    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 write FProperty1;
    property Property2: Char read FProperty2 write FProperty2; end;В качестве предка нового класса может выступать не только класс TPersistent, но и любой его потомок. В вышеприведенном листинге мы создаем новый класс TMyObject, в котором присутствуют два простых свойства — Property1 и Property2. Кроме того, в новый объект включена процедура Assign. Данная процедура необходима для обеспечения правильного доступа к свойству нашего будущего компонента TMyButton. Ниже приведен листинг 19.6, в котором мы добавляем в компонент TMyButton новое свойство-объект.

    Добавление свойстваобъекта в компонент TMyButtontype

    Листинг 19.6. Добавление свойства-объекта в компонент TMyButtontype

    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;Как вы можете видеть, мы добавляем в код нового компонента конструктор и деструктор объекта.

    Теперь осталось дописать конструктор и деструктор для компонента 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.Пример компонента TWeek

    unit 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).

    Пример компонента TWeek

    Определение базового

    Листинг 19.9. Определение базового класса TPropertyEditorTPropertyEditor = class(TBasePropertyEditor, IProperty) private

    FDesigner: 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;
    Методы данного класса, приведенные ниже, можно переопределять для изменения поведения редактора свойств.

  • Метод Activate вызывается, когда данное свойство выбирается в окне инспектора объектов.
  • Метод AllEqual вызывается при выборе на форме более одного компонента.
  • Метод Edit вызывается нажатием кнопки или двойным щелчком мыши на свойстве. Данный метод может вызвать диалоговое окно для редактирования свойства, например, как это происходит при редактировании свойства Font.
  • Метод Get Attributes возвращает множество значений типа TProperyAttributes, определяющих, каким образом свойство будет отображаться в окне инспектора объектов.
  • Метод GetComponent предназначен для определения компонента по его номеру (параметр Index) в случае, если на форме выбрано несколько компонентов одновременно.
  • Метод GetEditLimit возвращает максимальное число символов в строке, которые пользователь может ввести при редактировании свойства.
  • Метод GetName предназначен для получения имени свойства. Данный метод целесообразно изменять только в том случае, когда имя свойства отличается от имени, отображаемого в окне инспектора объектов.
  • Метод GetPropType применяется для определения указателя на информацию о типе редактируемого свойства.
  • Метод GetValue возвращает значение свойства в виде строки.
  • Метод Initialize вызывается при создании (инициализации) редактора свойств.
  • Метод SetValue применяется для установки значения свойства.
  • В большинстве случаев при создании нового редактора свойств нет необходимости использовать в качестве класса-предка базовый класс TPropertyEditor. Часто разработчик просто переделывает уже существующий для данного свойства редактор, переопределяй некоторые его методы.

    Рассмотрим в качестве примера переработанное свойство 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; Переменная вариантного типа может принимать два дополнительных значения:

  • Unassigned — не определено;
  • Null — значение неизвестного типа или значение потеряно.
  • Назад

    Использование директивы $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.Код для среды Windows

    while 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 имеет достаточно большое количество функций для работы с числовыми данными. Эти функции можно также использовать в арифметических выражениях. Среди прочих наиболее часто используются следующие функции:

  • Abs (x) — абсолютное значение х. Вызов данной функции позволяет отбросить знак минус у числа, если он есть;
  • Cos (х) — косинус угла х. Угол задается в радианах;
  • Ехр (х) — возведение числа е в степень х;
  • Ln(x) — натуральный логарифм числа х;
  • Odd(x) — проверяет число х на четность. Если оно четное, то возвращает значение True, иначе — False;
  • Sin (х) — синус угла х. Угол задается в радианах;
  • Sqr (х) — возведение числа х в квадрат;
  • Sqrt (х) — извлечение квадратного корня из числа х.
  • Аргументами данных функций могут быть не только числа, но и переменные, константы, выражения.

    Приведем пример вычисления выражения, в котором присутствуют арифметические функции:

    a:=sqr( (152+b) /2*cos (3.14+b) +sqrt (23)) ;

    Логические выражения

    Логические выражения это выражения, в которых содержатся:

  • логические константы True и False;
  • логические переменные и константы типа Boolean;
  • операции отношения;
  • логические операции;
  • скобки.
  • В результате выполнения логической операции получается логическое значение True или False. Логические операции, доступные в языке Object Pascal, представлены в табл. 3.5.



    Пример работы с оператором with

    Листинг 3.3 Пример работы с оператором with

    type 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. Пример использования оператора case

    case 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. Описание процедуры NumString

    procedure 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;
  • Метод Draw применяется для рисования изображения, хранящегося в объекте, который определен параметром Graphic, в координаты, задаваемые параметрами X и Y. Изображение может быть либо битовой матрицей, либо пиктограммой, либо метафайлом. Например:
    Image1.Canvas.Draw (10, 10, Image2.Picture.Bitmap);

    Таким образом, в координаты (10,10) канвы картинки Image1 будет занесен рисунок из канвы картинки Image2.
  • Метод DrawFocusRect применяется для рисования прямоугольника с помощью булевой операции XOR. То есть повторное рисование такого же прямоугольника на том же месте удалит этот прямоугольник. Пример:
    Image1.Canvas.DrawFocusRect (Rect (0,0,30,30);
  • Метод Ellipse применяется для рисования окружности или эллипса. Параметры — точки (X1, Y1) и (X2, Y2), определяющие прямоугольник, в который вписан эллипс.
  • Метод Error вызывается при необходимости генерации исключения при работе с объектом типа TList. Вызов данного метода дает лучший результат по сравнению с командой Raise. Примером вызова этого метода может служить следующая строка:
    List.Error ('Ошибка в элементе %u списка List', I);

    Выполнение данной строки вызовет сообщение об ошибке в какой-либо строке списка.
  • Метод Exchange предназначен для обмена местами двух элементов списка. Позиции этих двух элементов задаются параметрами Index1 и Index2.Примечаниe
    Не применяйте метод Exchange для отсортированных списков— это может нарушить упорядоченность списков.

  • Метод Expand применяется для увеличения емкости списка типа TList. Вызов данного метода приводит к выделению дополнительной памяти для быстрого добавления новых элементов списка. В случае, если при вызове данного метода список не заполнен, его емкость не изменяется, иначе — увеличивается.
  • Метод FillRect применяется для заполнения указанного прямоугольника канвы цветом, определенным значением свойства Brush. Например, приведенный ниже код заполняет всю область канвы компонента Image1 фоновым цветом, определенным свойством Brush:
    with Image1.Canvas do
    FillRect (Rect (0, 0, Width, Height) );
  • Метод FindNextControl применяется для определения следующего за указанным в параметре CurControl дочернего оконного компонента, соответствующего последовательности табуляции. Если в качестве параметра выступает не дочерний элемент данного оконного компонента, то метод возвращает первый в последовательности табуляции компонент. Второй параметр GoForward определяет направление поиска компонента. Если данный параметр имеет значение true, то ищется следующий компонент, иначе — предыдущий. Следующий параметр CheckTabStop — определяет,
    будут ли при поиске учитываться компоненты, в которых свойство TabStop установлено в false. Если значение данного параметра равно true, то такие компоненты не учитываются, иначе — учитываются. Последний параметр CheckParent применяется для того, чтобы указывать, учитывать ли при поиске только те компоненты, которые являются прямыми потомками данного оконного компонента. Если данный параметр равен false, то просматриваются все компоненты, иначе — только прямые потомки.
  • Метод First возвращает первый элемент списка типа TList.
  • Метод FloodFill применяется для закрашивания замкнутой области канвы произвольной формы каким-либо цветом. В качестве параметров данного метода выступают: начальная точка закрашивания, цвет и стиль заполнения. Начальная точка закрашивания (X, Y) должна находиться внутри закрашиваемой области. Два других параметра применяются для задания границы этой области. Параметр color применяется для указания цвета, который является границей закрашивания. Параметр FillStyle может иметь два значения. Если он равен fsSurface, то происходит закрашивание именно той области, которая окрашена цветом color, а на других цветах закрашивание не происходит. Если же параметр FillStyle имеет значение fsBorder, то заполняется область, в которой могут присутствовать любые цвета, кроме color, который является цветом границы закрашивания.
  • Метод Focused применяется для определения, является ли в настоящий момент времени данный оконный компонент активным. Данный метод возвращает значение true, если фокус принадлежит данному оконному компоненту, иначе — false.
  • Метод FrameRect применяется для рисования на канве прямоугольной рамки. Данный метод использует установки текущей кисти (Brush). Толщина рамки равна одному пикселу. Внутренняя часть рамки не заполняется никаким цветом. В качестве примера приведем код, который рисует на канве компонента Image1 красную прямоугольную рамку:
    with Image1.Canvas do begin Brush.Color := clRed; FrameRect ( Rect (10,10,150,100) );

    end;
  • Метод Free применяется для вызова деструктора объекта. Данный метод проверяет, не была ли уже ранее высвобождена память, предназначенная для данного объекта, после чего вызывает метод Destroy.
  • Метод GetTabOrderList предназначен для построения списка типа TList дочерних оконных компонентов, расположенных в последовательности табуляции. Свойство TabStop во внимание не принимается. В список входят как прямые, так и косвенные потомки данного оконного компонента.
  • Метод HandleAllocated предназначен для проверки наличия дескриптора окна у данного компонента. В случае, если дескриптор, окна есть, метод возвращает значение true. Данный метод удобно применять, если нет необходимости создавать дескриптор окна компоненту, у которого его нет. Непосредственная проверка свойства Handle компонента приводит к созданию дескриптора окна.
  • Метод HandleNeeded применяется для создания дескриптора окна для компонента, у которого его не было. При работе настоящий метод вызывает сначала метод CreateHandle у родительского компонента, а затем создает дескриптор для данного компонента.
  • Метод Hide применяется для того, чтобы сделать компонент невидимым. Вызов данного метода эквивалентен команде
    Component.Visible := false;
    Если данный компонент является оконным и содержит в себе другие компоненты, то эти компоненты также становятся невидимыми.Примечание
    Обратите внимание на тот факт, что хотя компонент является невидимым, все его свойства и методы являются доступными.

  • Метод IndexOf применяется для определения индекса первого вхождения в компонент типа TList данного элемента. Если такого элемента в списке нет, метод возвращает значение —1.
  • Метод Insert предназначен для вставки нового элемента списка в заданную позицию. Единственный параметр данного метода Index показывает, в какую именно позицию будет вставлен новый элемент списка. При вставке нового элемента все последующие элементы сдвигаются (их индексы увеличиваются на единицу). В случае, если происходит попытка вставить новый элемент в отсортированный список, генерируется исключение EListError. Тогда лучше использовать метод Add.
  • Метод Invalidate используется для полной перерисовки компонента. Применяется, когда с компонентом произошли какие-либо визуальные изменения.
  • Метод Last возвращает значение, равное последнему указателю списка типа Tlist и значению Count -1.
  • Метод LineTo применяется для рисования на канве объекта прямой линии. Начало линии совпадает с текущим значением координат пера (PenPos) и заканчивается в точке с координатами (X, Y), за исключением самой точки, которые передаются в качестве параметров метода.
  • Метод LoadFromClipboardFormat применяется для загрузки изображения в графический компонент из буфера обмена.
  • Метод LoadFromFile предназначен для загрузки изображения в графический компонент из файла, задаваемого параметром FileName. Если данный графический файл по каким-либо причинам не может быть загружен (несоответствие типов, незарегистрированный графический формат файла), то генерируется исключение EInvalidGraphic.
  • Метод LoadFromStream позволяет загружать графическое изображение из потока, задаваемого параметром Stream. Данный метод может использоваться при загрузке, например, графических полей в наборе данных из объекта типа TBlobStream.
  • Метод Lock применяется для блокировки канвы компонента и запрета рисования на ней из других потоков многопоточного приложения. Обратный результат достигается при помощи метода unlock. При многократном вызове метода Lock будет увеличиваться свойство LockCount, в котором фиксируется количество блокировок. Канва будет недоступной из других потоков, пока не снимется последняя блокировка. Если вы не хотите использовать многократную блокировку, можно воспользоваться методом TryLock. После блокирования канвы общая производительность приложения может существенно снизиться.
  • Метод Mask применяется для преобразования цветного изображения в черно-белую маску. В результате замены цвет TransparentColor переходит в белый, а все остальные цвета — в черный.
  • Метод Move предназначен для перемещения элемента списка, находящегося в позиции, задаваемой параметром CurIndex, в позицию, задаваемую параметром NewIndex.
  • Метод MoveToприменяется для изменения текущей позиции пера (PenPos) в заданную параметрами (X, Y). При перемещении пера на канве ничего не рисуется. Данный метод аналогичен прямой установке координат пера в свойстве PenPos.
  • Метод OpenBit предназначен для возврата индекса первого элемента массива типа TBits, имеющего значение false.
  • Метод Pack предназначен для удаления из списка типа TList всех элементов, значение которых равно nil. После удаления происходит переиндексация всех элементов списка.
  • Метод Pie рисует замкнутый сегмент окружности или эллипса. Параметры данного метода аналогичны параметрам метода Arc. В результате выполнения данного метода может получиться рисунок, похожий на Рисунок 8.15.
  • Метод Polygon рисует на канве многоугольник по заданному множеству точек, определенных массивом Points, причем первая точка соединяется с последней, после чего многоугольник закрашивается цветом, определенным свойством кисти Brush.
    Например:
    Image1.Canvas.Polygon ( [ Point (10, 10), Point (30,10),
    Point (130, 30), Point (240, 120) ] );

    Вышеприведенный код рисует на канве компонента Image1 закрашенный четырехугольник, координаты которого заданы непосредственно.
  • Освобождение ресурсов графической подсистемы

    Обработка события OnDragOver

    Листинг 8.2.Обработка события OnDragOver

    procedure 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. Код обработки OnDragOver

    procedure TForm1.ListBox2DragDrop(Sender, Source: TObject; X, Y: Integer);

    begin
    ListBox2. Items .Add (ListBox1. Items[ListBox1. ItemIndex]);
    end;
    Таким образом, мы добавляем выбранную строку компонента ListBox1 в компонент ListBox2.

    Все! Можно запускать приложение при помощи клавиши
    . Попробуйте перетащить любую строку из первого списка, во второй.

  • Событие OnEndDrag — последнее из событий, которые предназначены для обработки переноса одного компонента на другой. Оно наступает при любом окончании процесса переноса, как успешного, так и неудачного (когда компонент отпущен над формой или компонентом, неспособными его принять). Данное событие наступает в перетаскиваемом компоненте. Это событие может применяться для реакции приложения на перетаскивание (например, "выполнено успешно" или "неудача"). В обработчике этого события параметр Sender — это сам объект перетаскивания, а параметр Target принимает значение компонента-приемника (при успешном перетаскивании) или значение nil — при неудачном переносе. Приведем пример (листинг 8.4).


  • Oбработчик события OnEndDrag

    Листинг 8.4.Oбработчик события OnEndDrag

    procedure 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.

  • Событие OnEnter наступает, когда компонент получает фокус. Данное событие не наступает при переключении между разными формами приложения или между различными приложениями. При переключении между компонентами контейнерного типа (т. е. между компонентами, которые могут размещать на себе другие компоненты, например панели) событие OnEnter наступает сначала для компонента контейнерного типа, а затем — для содержащегося в нем компонента.
  • Oбработчик события OnEndDrag

    Синтаксис конструкции 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.Вызов метода HandleException

    try { операторы } except
    Application,HandleException(Self);
    end;
    Теперь рассмотрим конструкцию, предназначенную для защиты ресурсов приложения.

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



    Конструкция try finally

    Листинг 9.7.Конструкция try...finally

    try
    {операторы, способные создать исключительную ситуацию}; 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.pas

    unit 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.pas

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

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

  • статические;
  • виртуальные (virtual);
  • динамические (dynamic);
  • перегруженные (override);
  • методы обработки сообщений (message);
  • абстрактные (abstract).
  • После заголовка метода в описании класса через точку с запятой указывается один из вышеперечисленных идентификаторов (virtual, ..., abstract).

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

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

    Назад Вперед

    Модуль данных

    Рисунок 18.10. Модуль данных

    Модули

    Модули

    Кроме рассмотренных выше программ и подпрограмм, язык Object Pascal позволяет создавать так называемые модули.

    Модуль (unit) — предназначен для записи в него различных элементов, таких как подпрограммы, переменные, константы и др.

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


    Наиболее успешные сделки совершаются в направлении тренда



    Наиболее успешные сделки совершаются в направлении тренда

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

    Написание переносимого кода

    Написание переносимого кода

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

  • сократите вызов специфичных функций API Win32 или Linux или откажитесь от него совсем, используйте вместо этого методы CLX;
  • устраните конструкции PostMessage и SendMessage внутри приложения;
  • используйте объект TMemIniFile вместо TregIniFile;
  • обращайте внимание на регистр символов при наименовании файлов или каталогов;
  • откажитесь от кода ассемблера TASM (ассемблер GNU не поддерживает синтаксис TASM);
  • попробуйте написать код, использующий платформонезависимые библиотеки и константы, находящиеся в модулях System, SysUtils и других модулях, одинаковых для обеих платформ.
  • Приведем пример, который позволяет использовать многобайтные символы для обеих платформ (Windows и Linux). Среда Windows традиционно сопоставляет только два байта каждому многобайтному символу. В Linux многобайтная кодировка символов может содержать намного больше байтов на один символ (до шести байтов в кодировке UTF-8). Обе платформы могут использовать одинаковую кодировку с помощью функции StrNextChar, находящейся в модуле SysUtils. В листинге 21.2 приведен код для среды Windows.



    Непереносимые возможности

    Непереносимые возможности

    При создании объекта 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. Обозначения окна проводника

    Для перехода из окна проводника в окно просмотра и редактирования кода и наоборот можно использовать комбинацию клавиш ++. В окне проводника можно использовать пошаговый поиск. Чтобы найти любой класс, свойство, метод, переменную или программу (процедуру или функцию), достаточно набрать на клавиатуре необходимое имя. Между окном проводника и окном просмотра и редактирования кода существует прямая связь. При выборе объекта в окне проводника курсор в окне просмотра и редактора кода сместится на раздел реализации (Implementation) для данного объекта. И наоборот, при перемещении в окне просмотра и редактирования кода будут подсвечиваться соответствующие объекты в окне проводника.

    Для добавления (переименования) объекта в окне проводника достаточно щелкнуть правой кнопкой мыши в соответствующем узле окна проводника и выбрать в контекстном меню 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.

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

  • остерегайтесь создавать слишком много потоков — это может привести к большой загруженности операционной системы и процессора;
  • используйте синхронизацию в случае, когда несколько потоков пытаются получить доступ к одному ресурсу;
  • большинство методов, которые обращаются к объектам CLX и изменяют содержимое формы, должны вызываться из главного CLX-потока или использовать объект синхронизации.
  • Определение объекта TThread находится в модуле Classes и имеет вид, приведенный в листинге 14.1.



    Окно Environment Options

    Рисунок 6.10. Окно Environment Options

    Окно Environment Options

    Окно настройки

    Рисунок 6.2. Окно настройки

    В окне настройки имеются три вкладки: Toolbars, Commands и Options.

    Вкладка Toolbars (см. Рисунок 6.2) позволяет показывать или скрывать вкладки панели инструментов.

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

    Вкладка Commands — это очень удобное средство добавления практически любых команд на панель инструментов для быстрого доступа.

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

    Окно настройки

    Окно New Items

    Рисунок 18.1. Окно New Items

    Окно New Items

    Окно появляющееся при обработке события OnKeyDown

    Рисунок 8.21. Окно, появляющееся при обработке события OnKeyDown

  • Событие OnKeyPress наступает при нажатии пользователем символьной клавиши. Данное событие имеет параметр Key, который содержит символ нажатой, клавиши и имеет тип Сhar. При этом различаются символы верхнего и нижнего регистров, а также раскладка клавиатуры.
    Примечание
    С помощью данного события невозможно обработать нажатие функциональных клавиш и клавиш , или . Таким образом, когда вы нажмете комбинацию клавиш +, в параметр Key события OnKeyPress поступит значение "В" — клавиша только поменяет регистр символа. При нажатии комбинации клавиш <Аlt>>+<любая символьная клавиша> событие OnKeyPress не наступает. При нажатой комбинации клавиш <СtrlМ>+<любая символьная клавиша> событие OnKeyPress наступает, но в параметр Key ничего не передается.

  • Событие ОnKеyUр наступает при отпускании пользователем любой ранее нажатой клавиши. Данное событие позволяет обрабатывать все клавиши, как и событие OnKeyDown. По своим параметрам и поведению событие OnKeyUp равносильно событию OnKeyDown.
  • Событие OnMouseDown наступает при нажатии пользователем любой кнопки мыши в тот момент, когда указатель мыши находится над компонентом. Данное событие имеет параметры Button, Shift, X и Y. Параметр Button определяет, какая кнопка мыши нажата:
  • mbLeft — левая кнопка;
  • mbMiddle — средняя кнопка;
  • mbRight — правая кнопка.
  • Параметр Shift равносилен параметру Shift для событий, связанных с обработкой клавиатуры. Таким образом, можно обрабатывать нажатие любой кнопки мыши одновременно с клавишами , или .
    Параметры X и Y содержат координаты указателя мыши в области компонента.
  • Событие OnMouseUp наступает, когда пользователь отпускает любую кнопку мыши над компонентом. По своим функциям и параметрам данное событие аналогично событию OnMouseDown.
  • Событие OnMouseMove наступает при перемещении указателя мыши над компонентом. Данное событие возникает независимо от того, нажаты какие-либо кнопки мыши или нет.
    Примечание
    При нажатой левой кнопке мыши данное событие не возникает. Эта особенность почему-то не документирована.

    Данное событие имеет следующие параметры: Shift, X и Y, аналогичные вышеописанным.
  • Событие OnPaint наступает, когда приложение получает сообщение о необходимости перерисовки испорченного изображения. Изображение может испортиться от перекрытия окон одного или нескольких приложений. В обработчике данного события программист должен разместить процедуру, выполняющую перерисовку изображения. Например, если на форме был размещен рисунок, хранящийся в компоненте BitMap, можно для перерисовки изображения использовать следующий обработчик события OnPaint:
    Canvas.Draw (0, 0, BitMap );
  • Событие OnProgress наступает при прохождении медленных процессов, связанных с изменением графического изображения. Данное событие позволяет строить индикаторы хода выполнения процесса. Событие OnProgress имеет следующие параметры: Stage, PercentDone, RedrawNow,R и Msg. Параметр Stage предназначен для указания стадии прогресса (начало, продолжение, окончание) и может принимать значения psStarting (начало), psRunning (продолжение), psEnding (окончание). Параметр PercentDone показывает, какая часть процесса выполнена. Параметр RedrawNow показывает, может ли в настоящий момент изображение успешно отобразиться на экране. Параметр R служит для указания области изображения, которая изменена и требует перерисовки. Наконец, параметр Msg служит для отображения сообщений о ходе процесса. Этот параметр имеет строковый тип. Параметр Msg может быть пустым.
  • Окно появляющееся при обработке события OnKeyDown Окно появляющееся при обработке события OnKeyDown

    Окно сообщения об исключении

    Рисунок 9.2. Окно сообщения об исключении

    Примечание
    С объектами исключений нужно работать очень осторожно. Ни в коем случае самостоятельно не уничтожайте объекты исключения — это может привести к ошибке работы программы. После завершения обработки исключения Kylix самостоятельно позаботится об его уничтожении.

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

  • Exception — базовый класс исключений. Все другие классы исключений являются прямыми или косвенными потомками данного класса.
  • EAbort — потомок класса Exception. Данный класс исключения не отображает диалогового окна ошибки при возникновении исключения. Простейшим способом генерации данного исключения является вызов метода Abort.
  • EAbstarctError — потомок класса Exception. Генерируется при попытке вызова абстрактного метода.
  • EAccessViolation — потомок класса EExternal. Генерируется при неверной работе с памятью.
  • EAssertionFailed — потомок класса Exception. Класс исключения, генерируемый в случае ошибки при проверке истинности с помощью процедуры Assert. Данное исключение возникает, только если включена директива компилятора Kylix $ASSERTION ON.
  • EBcdException — потомок класса Exception. Базовый класс при работе со значениями типа BCD (Binary code decimal). Генерируется обычно в случае ошибки при попытке преобразования типа Variant или String в BCD.
  • EBcdOverflowException — потомок класса EBcdException. Генерируется при невозможности преобразования типа Variant в BCD с требуемым количеством символов после запятой.
  • EBitsError — потомок класса Exception. Генерируется при ошибке доступа к массиву булевых значений.
  • EClassNotFound — потомок класса EFilerError. Генерируется при невозможности найти определенный компонент при чтении из потока.
  • EComponentError — потомок класса Exception. Возникает при ошибке регистрации или переименования компонента.
  • EConvertError — потомок класса Exception. Генерируется при ошибке преобразования строк или объектов.
  • EDatabaseError — потомок класса Exception. Базовый класс для всех ошибок при работе с базами данных.
  • EDateTimeError — потомок класса ECommonCalendarError. Возникает при неправильном вводе даты или времени пользователем в компонент TdateTimePicker.
  • EDbcClient — потомок класса EDatabaseError. Генерируется в случае ошибки при работе с набором данных клиента базы данных.
  • EDBEditError — потомок класса Exception. Возникает в случае попытки помещения данных в поле, которые не являются совместимыми с заданной маской поля.
  • EDivByZero — потомок класса EIntError. Возникает при ошибке целочисленного деления на ноль. При делении на ноль чисел с плавающей запятой возникает другое исключение EZeroDivide (см. ниже).
  • EDSWriter — потомок класса Exception. Ошибка при попытке создания пакета данных из набора данных.
  • EExternal — потомок класса Exception. Базовый класс для всех ошибок, происходящих вне приложения во время его выполнения.
  • EExternalException — потомок класса EExternal. Исключение с нераспознаваемым кодом.
  • EFCreateError — потомок класса EStreamError. Неудачная попытка создания нового файла. Например, неправильное имя файла или если файл с таким именем уже существует.
  • EFilerError — потомок класса EStreamError. Попытка повторной регистрации класса.
  • EFOpenError — потомок класса EStreamError. Невозможно открыть требуемый файл. Файл не найден или не существует заданного пути к файлу.
  • EHandleComponentException — потомок класса Exception. Невозможно получить дескриптор окна.
  • EHeapException — потомок класса Exception. Класс исключения для ошибок, связанных с кучами распределения памяти.
  • EIdAcceptWaitCannotBeModifiedWhileServerlsActive — потомок класса EIdTCPServerError.Возникает, когда свойство TIdTCPServer.AcceptWait изменяет свое значение при активном TCP-сервере.
  • EIdAlreadyConnected — потомок класса EIdException. Попытка создать соединение с компонентом Indy, когда оно уже существует.
  • EIdCanNotChangeTarget — потомок класса EIdException. Попытка установки свойства TIdLogDebug. Target в то время, когда свойство TIdLogDebug.Active имеет значение true.
  • EldCanNotCreateMessagePart — потомок класса EldMessageException. Ошибка вызова конструктора класса TIdMessagePart.
  • EIdClosedSocket — потомок класса EIdException. Попытка записи в закрытый ТСР-сокет.
  • EIdConnClosedGracefully — потомок класса EIdSilentException. Возникает в случае успешного закрытия соединения.
  • EIdCorruptServicesFile — потомок класса EIdException. Поврежден один из файлов SERVICES. Данные файлы располагаются на диске в разных местах, в зависимости от операционной системы:
  • BSDUnix — /etc/;
  • Windows 9x, Millenium — папка Windows;
  • Windows NT — папка Windows/System32.
  • EIdCouldNotBindSocked — потомок класса EIdSockedHandleError. Ошибка привязки дескриптора сокета.
  • EIdDnsResolverError — потомок класса EIdException. Ошибка класса TIdDnsResolver.
  • EIdTunnelConnectToMasterFailed — пототмок класса EIdTunnelException. Данное исключение генерируется автоматически при ошибке туннельного соединения.
  • EIdException — потомок класса Exception. Базовый класс исключений для Indy-компонентов. Компоненты Indy не используют стандартные исключения.
  • EIdFailedToRetreiveTimeZoneInfo — потомок класса EIdException. Данные о временной зоне не могут быть получены текущим пользователем системы.
  • EIdFTPFileAlreadyExists — потомок класса EidException. Файл не может быть перезаписан с помощью запроса FTP Get.
  • EIdHTTPCannotSwitchSessionStateWhenActive — потомок класса EIdHTTPServerError. Невозможно изменить состояние активного HTTP-сервера.
  • EIdHTTPErrorParsingCommand — потомок класса EIdHTTPServerError. Неизвестная HTTP-команда.
  • EIdHTTPHeaderAlreadyWritten — потомок класса EIdHTTPServerError.Заголовок HTTP-документа уже существует.
  • EIdHTTPServerError — потомок класса EIdException. Базовый класс для всех HTTP-исключений в Indy.
  • EIdHTTPUnsopportedAuthorisationScheme — потомок класса EIdHTTPServerError. Неподдерживаемый формат имени пользователя и пароля для идентификации на HTTP-сервере.
  • EIdIcmpException — потомок класса EIdException. Исключение для всех ICMP-компонентов.
  • EIdInterceptPropInvalid — потомок класса EIdTCPConnectionError.Попытка использования возможностей, не поддерживаемых текущим классом TIdConnectionIntercept, который ассоциирован со свойством
    Intercept.
  • EIdInterceptPropIsNil — потомок класса EIdTCPConnectionError. Попытка установки InterceptEnabled в true в то время, когда Intercept имеет значение Nil.
  • EIdInvalidServiceName — потомок класса EIdException. Неправильное имя сервиса.
  • EIdInvalidSocked — потомок класса EIdException. Неожиданное закрытие соединения.
  • EIdLoginException — потомок класса EIdTelnetServerException. Ошибка при соединении с Telnet-сервером.
  • EIdMaxLoginAttempt — потомок класса EIdLoginException. Исчерпан лимит подключений к Telnet-серверу. Максимальное число подключений указывается в свойстве TIdTelnetServer.LoginAttempts.
  • EIdMessageException — потомок класса EIdException. Базовый класс для исключений Indy, которые отображают сообщения об ошибке.
  • EIdMoreThanOneTIdAntiFreeze — потомок класса EIdException. Попытка создания более одного компонента TIdAntiFreeze в вашем приложении. Приложению не требуется больше одного такого компонента.
  • EIdNNTPConnectionRefused — потомок класса EIdProtocolReplyError. Отказ соединения с NNTP-сервером.
  • EIdNNTPException — потомок класса EIdException. Базовый класс всех NNTP-исключений.
  • EIdNNTPNoOnNewGroupsList — потомок класса EIdNNTPException. Ошибка поиска в новом списке Newsgroups.
  • EIdNNTPNoOnNewNewsList — потомок класса EIdNNTPException. Ошибка поиска в новом списке сообщений NNTP.
  • EIdNNTPNoOnNewsgroupList — потомок класса EIdNNTPException. Ошибка поиска в новом списке Newsgroups.
  • EIdNNTPStringListNotInitialized — потомок класса EIdNNTPException. Неудачный поиск сообщения,
  • EIdNoBindingsSpecified — потомок класса EIdUDPServerException. Попытка UDP-сервера инициализировать дескриптор сокета, но номер порта при этом не был задан.
  • EIdNoDataToRead — потомок класса EIdTCPConnectionError. Попытка записи с помощью вызова метода WriteStream пустого потока Tstream.
  • EIdNoExecuteSpecified — потомок класса EIdTCPConnectionError. Heудачное выполнение процесса, имеющего равный приоритет с вашим приложением.
  • EIdNoOnAuthentication — потомок класса EIdTelnetServerException. У компонента TIdTelnetserver не определен обработчик события OnAuthentication.
  • EIdNotAHBytessent — потомок класса EIdSocketHandleError. Передача данных не завершена. Были отправлены не все байты.
  • EIdNotEnoughDataInBuffer — потомок класса EIdTCPConnectionError.Не достаточно байтов во внутреннем буфере компонента TIdTCPConnection.
  • EIdObjectTypeNotSupported — потомок класса EIdTCPConnectionError. Не поддерживаемый тип объекта TStream или TStrings.
  • EIdOpenSSLError — потомок класса EIdException. Класс-предок для всех классов исключений Open SSL.
  • EIdOpenSSLLoadError — потомок класса EIdOpenSSLError. Базовый класс ошибок загрузки библиотеки Open SSL.
  • EIdOSSLAcceptError — потомок класса EIdOpenSSLError. Новое SSL-соединение не доступно.
  • EIdOSSLConnectError — потомок класса EIdOpenSSLError. Ошибка SSL-соединения.
  • EIdOSSLCouldNotLoadSSLLibrary — потомок класса EIdOpenSSLLoadError. Невозможно загрузить библиотеку Open SSL.
  • EIdOSSLCreatingContextError — потомок класса EIdOpenSSLError.Ошибка преобразования содержания SSL после смены режима.
  • EIdOSSLDataBindingError — потомок класса EIdOpenSSLError. Невозможна привязка SSL-сокета.
  • EIdOSSLGetMethodError — потомок класса EIdOpenSSLError. Компонент TIdSSLContext содержит значение неверного режима.
  • EIdOSSLLoadingCertError — потомок класса EIdOpenSSLLoadError.Файл-сертификат не может быть загружен после смены значения свойства Mode у компонента TIdSSLContext.
  • EIdOSSLLoadingKeyError — потомок класса EIdOpenSSLLoadError. Ключевой файл-сертификат не может быть загружен после смены значения свойства Mode у компонента TIdSSLContext.
  • EIdOSSLLoadingRootCertError — потомок класса EIdOpenSSLLoadError.Корневой файл-сертификат не может быть загружен после смены значения свойства Mode у компонента TIdSSLContext.
  • EIdOSSLModeNotSet — потомок класса EIdOpenSSLError. He назначен режим контекста SSL.
  • EIdOSSLSettingCipherError — потомок класса EIdOpenSSLError. Ошибка установки схемы шифрования SSL контекста после смены режима.
  • EIdPackageSizeTooBig — потомок класса EIdSocketHandleError. Неправильный размер пакета.
  • EIdProtocolReplyError — потомок класса EIdException. Ошибка протокола.
  • EIdResponceError — потомок класса EIdException. Ошибка ожидаемого ответа.
  • EIdSetSizeExceeded — потомок класса EIdException. Количество вызовов FD SET превысило максимум, поддерживаемый операционной системой.
  • EIdsilentException — потомок класса EIdException. Молчаливое исключение. Похоже на Eabort.
  • EIdSockedError — потомок класса EIdException. Ошибка сокета.
  • EIdSockedHandleError — потомок класса EIdException. Базовый класс для всех ошибок дескрипторов сокетов.
  • EIdSocksAutnError — потомок класса EIdsocksError. Ошибка идентификации пользователя на Socks-прокси.
  • EIdSocksAuthMetnodError — потомок класса EIdSocksError. Неправильный или неподдерживаемый метод идентификации пользователя на Socks-прокси.
  • EIdSocksError — потомок класса EIdException. Базовый класс исключений Socks при использовании метода TIdTCPClientConnect.
  • EIdSocksRequestFailed — потомок класса EIdSocksError. Socks-прокси отклонил или не распознал запрос от TCP-клиента.
  • EIdSocksRequestIdentFailed — потомок класса EIdSocksError. Идентификатор пользователя, полученный от TCP-клиента, не совпадает с идентификатором, представленным программой Ident Daemon, запущенной на компьютере пользователя.
  • EIdSocksRequestServerFailed — потомок класса EIdSocksError. Socks-прокси не может создать соединения, запрашиваемого TCP-клиентом.
  • EIdSocksServerAddressError — потомок класса EdSocksError. Socks-прокси не поддерживает тип адресации, который получен от TCP-клиента.
  • EIdSocksServerCoimandError — потомок класса EldSocksError. Socks-прокси не поддерживает команду, которая получена от TCP-клиента.
  • EIdSocksServerConnectionRefusedError — потомок класса EIdSocksError.Соединение, запрашиваемое TCP-сервером, было отклонено Socks-прокси.
  • EIdSocksServerGeneralError — потомок класса EIdSocksError. Socks-прокси сообщает об ошибке.
  • EIdSocksServerHostUnreachableError — потомок класса EIdSocksError.Хост, запрашиваемый TCP-клиентом, недоступен.
  • EIdSocksServerNetUnreachableError — потомок класса EIdSocksError.Сеть недоступна.
  • EIdSocksServerPermissionError — потомок класса EIdSocksError. Запрашиваемое соединение не поддерживается набором правил.
  • EIdSocksServerRespondError — потомок класса EIdSocksError. Socks-прокси не отвечает на запросы TCP-клиента.
  • EIdSocksServerTTLExpiredError — потомок класса EIdSocksError. Хост не может быть доступным, т. к. превышен TTL.
  • EIdSocksUnknownError — потомок класса EdSocksError. Неизвестная ошибка.
  • EIdStackCanNotLoadWinsock — потомок класса EldException. Невозможно получить данные из сокета.
  • EIdstackError — потомок класса EIdException. Базовый класс для ошибок стека протокола Indy.
  • EIdStackInitializationFailed — потомок класса EIdStackError. Ошибка инициализации стека протокола.
  • EIdStackSetSizeExceeded — потомок класса EIdStackError. Превышено максимально возможное число дескрипторов сокетов.
  • EIdTableNotFound — потомок класса EIdException. Неверное преобразование символов с использованием кодовой таблицы.
  • EIdTCPConnectionError — потомок класса EIdException. Базовый класс ошибок TCP-соединений.
  • EIdTCPServerError — потомок класса EIdException. Базовый класс ошибок TCP-сервера.
  • EIdTelnetClientConnectError —потомок класса EIdTelnetError. Ошибка соединения с Telnet-сервером.
  • EIdTelnetError — потомок класса EIdException. Базовый класс ошибок Indy Telnet.
  • EIdTelnetServerException — потомок класса EIdException. Базовый класс ошибок Telnet-сервера.
  • EIdTelnetServerOnDataAvailabielsNil — потомок класса EIdTelnetError. Неверная попытка выполнения метода TIdTelnet.DoOnDataAvailable.
  • EIdTextInvalidCount — потомок класса EIdMessageException. Ошибка при создании текстового сообщения.
  • EIdTFTPAccessViolation — потомок класса EIdTFTPException. Доступ к FTP запрещен.
  • EIdTFTPAllocationExceeded — потомок класса EIdTFTPException. Превышение распределений.
  • EIdTFTPException — потомок класса EIdException. Базовый класс для исключений Trivial FTP.
  • EIdTFTPFileAlreadyExists — потомок класса EIdTFTPException. Попытка создания уже существующего файла.
  • EIdTFTPFileNotFound — потомок класса EIdTFTPException. Файл не найден.
  • EIdTFTPIllegalOperation — потомок класса EIdTFTPException. Неправильная FTP-операция.
  • EIdTFTPNoSuchUser — потомок класса EIdTFTPException. Ошибка проверки имени пользователя и пароля.
  • EIdTFTPOptionNegotiationFailed — потомок класса EIdTFTPException. Неверный выбор согласования FTP.
  • EIdTFTPUnknownTransferID — потомок класса EIdTFTPException. Нeизвестный идентификатор передачи данных.
  • EIdThreadClassNotSpecified — является потомком класса EIdThreadMgrError. Попытка создания нового потока без указания имени класса.
  • EIdThreadMgrError — потомок класса EIdException. Базовый класс для ошибок Indy Thread Manager.
  • EIdTunnelConnectToMasterFailed — потомок класса EIdTunnelException. Невозможно соединение подчиненного и главного туннелей.
  • EIdTunnelCRCFailed — потомок класса EIdTunnelException. Неверное вычисление CRC.
  • EIdTunnelCustomMessageInterpretationFailure — потомок класса EIdTunnelException. Подчиненный поток получил сообщение неизвестного типа.
  • EIdTunnelDontAllowConnections — потомок класса EIdTunnelException.Подчиненный поток не может установить соединение.
  • EIdTunnelException — потомок класса EIdException. Базовый класс для ошибок Indy Tunnel.
  • EIdTunnelInterpretationOfMessageFailed — является потомком класса EIdTunnelException. Ошибка интерпретации сообщения от подчиненного потока.
  • EIdTunnelMessageHandlingFailed — является потомком класса EIdTunnelException. Подчиненным потоком получено неправильное сообщение.
  • EIdTunnelMessageTypeRecognitionError — является потомком класса EIdTunnelException. Неизвестный тип сообщения.
  • EIdTunnelTransformError — потомок класса EIdTunnelException. Ошибка преобразования данных при туннельном соединении.
  • EIdTunnelTransformErrorBeforeSend — является потомком класса EIdTunnelException. Ошибка преобразования данных до их отправки.
  • EIdUDPException — потомок класса EIdException. Базовый класс для ошибок Indy UDP.
  • EIdUDPReceiveErrorZeroBytes — потомок класса EIdUDPException. Данные не были получены при установленном соединении.
  • EIdUDPServerException — потомок класса EIdUDPException. Базовый класс для ошибок Indy UDP-сервер.
  • EIniFileException — потомок класса Exception. Ошибка при работе с INI-файлами.
  • EInOutError — потомок класса Exception. Ошибка ввода/вывода. Коды ошибок ввода/вывода представлены в табл. 9.1.


  • Окно сообщения

    Рисунок 9.1. Окно сообщения

    Примечание
    Знание имен классов исключений необходимо при обработке исключительных ситуаций. Мы рассмотрим их далее в этой главе.

    В листинге 9.4 приведен пример использования временного имени объекта исключения в своих целях.

    Окно свойств редактора

    Рисунок 6.8. Окно свойств редактора

    С помощью окна свойств редактора можно настроить практически все параметры отображения текстов программ в окне просмотра и редактирования кода, а также проверки синтаксиса.

    Окно проводника служит для упрощения навигации между модулями проекта. Окно проводника можно закрыть, щелкнув левой кнопкой мыши в верхнем правом углу данного окна. С помощью пункта главного меню Kylix View/Code Explorer (Просмотр/Окно проводника) можно снова активизировать это окно.

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

    В окне проводника для обозначения всего вышеперечисленного используются следующие значки (Рисунок 6.9):

    Окно свойств редактора

    Событие OnExit является противоположным по

    Рисунок 8.19. Окно, выдаваемое при неудачном перетаскивании строки из ListBox1 в ListBox2

  • Событие OnExit является противоположным по отношению к ОnEnter. Событие наступает в момент, когда компонент теряет фокус, т. е. когда фокус переходит к другому компоненту. Это событие также не наступает при переключении между разными формами или приложениями. В отличие от события OnEnter, событие OnExit наступает сначала для компонента, содержащегося в компоненте-контейнере, а затем — для самого компонента контейнерного типа.
  • Приведем пример, иллюстрирующий события OnEnter и OnExit. Расположим на форме кнопку Button1и группу переключателей RadioGroup1 (Рисунок 8.20). Добавим в группу переключателей несколько строк (путем редактирования свойства Items).

    Событие OnExit является противоположным по

    выдаваемое при успешном перетаскивании

    Рисунок 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 можно использовать шаблоны. Символы шаблонов:

  • % — замещает любое количество символов, в том числе и нулевое;
  • _ — замещает один символ.
  • Пример 17.8. Проверка частичного совпадения по шаблону

    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. Кроме того, мы рассмотрим средства для работы с базами данных, предоставляемые средой программирования.

    Основные понятия

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

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

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

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

  • Иерархические — построенные в виде иерархического дерева. Все данные в базе данных такого типа делятся на главные и подчиненные. Таким образом, данные, которые находятся на самом высоком уровне иерархии, являются главными. В свою очередь данные, находящиеся на более низких ступенях иерархии, называются подчиненными. Этот тип баз данных практически не применяется в настоящее время из-за того, что работает только с данными, которые иерархически упорядочены.
  • Сетевые — построены таким образом, что данные расположены произвольно. То есть любые данные могут быть и главными и подчиненными. В такой базе данных достаточно сложно организовать поиск нужных данных.
  • Реляционные — организованы в виде одной или нескольких прямоугольных таблиц, в которые занесены данные.
  • Все эти типы данных представлены на Рисунок 15.1.


    Основы языка SQL

    Основы языка SQL

    В этой главе мы рассмотрим команды языка структурированных запросов SQL (Structured Query Language). Вы узнаете, что такое запрос и как с ним работать.

    Основные сведения о языке SQL

    Язык SQL существует в нескольких стандартах. Наиболее поддерживаемыми и распространенными являются стандарты SQL-89 и SQL-92. Последний стандарт также называют стандартом ANSI. Из-за наличия множества стандартов языка существует множество его диалектов. Мы рассмотрим только основные команды SQL для простых операций с таблицами баз данных.

    В языке SQL нет многих типов команд, которые присущи большинству языков программирования. Так, в нем нет операторов цикла, перехода и т. д.

    SQL-запрос — это команда на языке SQL.

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

    Все SQL-запросы можно условно разделить на два вида:

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

    Операторы определения данных — предназначены для создания, удаления и изменения структуры данных. Основные из них перечислены в табл. 17.1.



    Отличия CLX от VCL

    Отличия CLX от VCL

    Хотя многое в CLX и VCL выполнено одинаково, они имеют некоторые отличия. Рассмотрим их.

  • Визуальная среда Linux выглядит несколько иначе, чем Windows. Внешний вид диалоговых окон может достаточно сильно отличаться, в зависимости от того, каким менеджером окон вы пользуетесь в Linux (например, KDE или Gnome).
  • В Linux вы можете использовать свойство TApplioation.Style для задания внешнего вида приложения (начертания графических элементов).Можно оставить стиль таким, каким он установлен в Linux, но все же рекомендуется использовать свойство Style.
  • Весь код для работы с вариантным типом данных (variant), который находился в модуле system, в CLX содержится в двух новых модулях:
  • Variants.pas;
  • VarUtils.pas.
  • Таким образом, если вы хотите использовать в своем приложении вариантные переменные, не забудьте добавить в раздел uses модуль Variants.

  • Среда Linux не использует для хранения информации о текущей конфигурации системы системный реестр. Вместо него вы можете применять текстовые файлы конфигураций и переменные среды для получения такого же эффекта, как при работе с системным реестром Windows. Системные конфигурационные файлы в Linux часто находятся в каталоге /etc, например /etc/hosts. Кроме того, можно сохранять информацию в файлах инициализации ini как и в Windows. Есть лишь одно отличие: вам нужно использовать для работы с файлами инициализации объект TMemIniFile вместо TregIniFile, применяемого в Windows.
  • Нажатие клавиши не имитирует событие щелчка кнопки мыши, как это происходит в Delphi.
  • Компонент TColorDialog не имеет свойства TColorDialog.Options. Таким образом, вы не можете настроить работу и функциональность диалога выбора. Кроме того, TColorDialog не всегда является модальным (модальным называется окно, которое не позволяет пользователю работать с другими окнами, пока не будет закрыто).
  • Во время выполнения приложения комбинированные списки (TComboBox) работают по-разному в Kylix и Delphi. В Kylix вы можете добавить строку в список, введя нужный текст строки и нажав на клавишу для ввода комбинированного списка. Эту опцию можно отключить, установив свойство InsertMode в ciNone. Также в Kylix можно добавить пустой (не содержащий строку) элемент списка в комбинированный список. Если вы нажмете и будете удерживать клавишу <Ї> на клавиатуре управления курсором при активном комбинированном списке, то список не остановится на последней строке как в Delphi, а будет прокручиваться опять сверху вниз.
  • Компонент TCustomEdit нe поддерживает Undo, ClearUndo и CanUndo. Но пользователь приложения может отменить редактирование в поле для ввода TEdit во время работы приложения, нажав правую кнопку мыши над полем для ввода и выбрав в выпадающем меню пункт Undo.
  • Значение кода клавиши при использовании событий OnKeyDown или OnKeyUp в Windows равно 13. В Linux для этой же клавиши код имеет значение 4100.
  • Назад Вперед

    Пакеты компонентов

    Пакеты компонентов

    Пакеты — это специальные динамически присоединяемые компоненты (аналоги файлов so — разделяемых объектов, Shared Objects). По своему использованию пакеты делятся на:

  • пакеты, загружаемые во время работы приложения (runtime packages), мы их будем далее называть пакетами времени выполнения. Они содержат в себе код, компоненты и используются приложением во время выполнения. Если ваше приложение ссылается на отсутствующий пакет — оно не будет работать;
  • пакеты, используемые во время разработки приложения (design-time packages), будем их называть пакетами разработки. Пакеты разработки содержат в себе компоненты, редакторы свойств, мастера и другие элементы, предназначенные для работы в среде Kylix;
  • пакеты, которые могут работать как во время разработки приложения, так и во время работы приложения;
  • пакеты, не являющиеся ни пакетами времени выполнения, ни пакетами разработки. Данный вид пакетов предназначен для использования их другими пакетами. На них не могут ссылаться ни приложение, ни сама среда Kylix.
  • Для того чтобы пакеты можно было отличить от других динамически присоединяемых библиотек, имеющих расширение so, для пакетов используется следующее правило наименования: bpl<имя пакета>.sо. Первые три буквы обозначают пакет библиотеки Kylix (Borland Package Library).

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

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

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

    Вперед

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

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

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

    Описание основных компонентов Kylix

    Итак, как уже было сказано ранее, Kylix поставляется со стандартным набором компонентов, доступ к которым осуществляется при помощи палитры компонентов. Рассмотрим вкладки палитры компонентов.

    Вкладка Standard (Рисунок 8.1).

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

    Параметры и аргументы

    Параметры и аргументы

    Параметры — это элементы подпрограммы, которые используются при описании блока подпрограммы.

    Аргументы — это элементы, которые указываются при вызове подпрограмм. Они замещаются соответствующими параметрами подпрограммы.

    В качестве параметров могут выступать:

  • значения;
  • константы;
  • переменные.
  • Параметрами могут быть элементы абсолютно любого типа.

    Все параметры разделяются на группы, в зависимости от того, чем они являются:

  • параметры-значения;
  • параметры-константы;
  • параметры-переменные.
  • Параметры-значения — это параметры, перед которыми в заголовке подпрограммы не стоит слово var или const. За параметрами-значениями через двоеточие ставится их тип. Например:

    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 будет выглядеть наиболее похожим на переносимое из Windows приложение. Недостатком является низкая скорость выполнения приложения при эмуляции.
  • Если вы переносите приложение под Linux с целью запускать его только в данной среде, вы можете удалить все специфичные для Windows команды из приложения. Если же вам нужно запускать приложение в обеих средах, вам придется модифицировать код или использовать директиву компилятора $IFDEF для указания блоков кода, специфичных для одной из сред (Linux или Windows).

    Перечислим семь главных шагов, которые нужно выполнить для переноса приложения из 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 обеспечивает программисту три пути для доступа к информации, содержащейся в базах данных;

  • ActiveX Data Objects (ADO);
  • Borland Database Engine (BDE);
  • InterBase Express.
  • Эти три метода не применяются в Kylix. Вместо них вы можете использовать компоненты dbExpress, обеспечивающие новую межплатформенную технологию доступа к данным, которая будет доступна и в Windows при использовании Delphi 6.

    Прежде чем перенести приложения баз данных из 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 обеспечивает более простой и быстрый доступ к удаленным базам данных. В результате вы можете ожидать от своего приложения быстрой скорости доступа к данным;
  • dbExpress может обрабатывать запросы и хранимые процедуры, но не поддерживает концепцию открытых таблиц;
  • dbExpress возвращает только однонаправленные указатели;
  • dbExpress не содержит встроенную поддержку обновления данных, кроме способности выполнения запросов INSERT, DELETE и UPDATE;
  • dbExpress не делает кэширования метаданных;
  • dbExpress выполняет исключительно запросы пользователя, тем самым оптимизируя доступ к базе данных;
  • dbExpress непосредственно управляет буфером записей и блоками буферов записей. В BDE для этого необходимы клиенты, чтобы распределять память, используемую для помещения записей в буфер;
  • dbExpress не поддерживает локальные таблицы, которые основаны не на запросах SQL (то есть такие, как Paradox, dBase или FoxPro);
  • драйверы dbExpress позволяют работать с базами данных InterBase, Oracle, DB2 и MySQL. Если вы используете другой сервер баз данных, вам придется выбрать один из трех путей:
  • преобразовать данные в один из поддерживаемых форматов;
  • написать самостоятельно драйвер dbExpress для используемого сервера баз данных;
  • использовать драйвер стороннего производителя.
  • Отличия на уровне компонентов

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

    В табл. 21.7 приведен список наиболее важных компонентов для работы с базами данных, которые применяются в InterBase Express, BDE и ADO в среде Windows, и показано их соответствие компонентам dbExpress для использования в среде Linux и кроссплатформенньк приложениях.



    Пиктограмма Data Module окна New Items

    Рисунок 18.2. Пиктограмма Data Module окна New Items

    Пиктограмма 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-файла.

    Поля ID и Name

    Поля компонента Clients

    Рисунок 18.9. Поля компонента Clients

    Разместим в модуле данных компонент DataSource, установим его свойство Name в ds_Clients и свяжем его с компонентом Clients (свойство DataSet компонента ds_Clients установим равным Сlients). Затем установим свойство DataSource в ds__Clients. Окончательный вид модуля данных показан на Рисунок 18.10.

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

    Поля компонента Clients

    Поля

    Поля

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

    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

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

  • Свойство BoundsRect применяется для получения одновременно координат всех четырех вершин компонента. Данное свойство определяется так:
    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;

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

  • Свойство caption связывает с компонентом некоторую строку текста, поясняющую его назначение. Данная строка является обычно заголовком компонента (заголовком кнопки, метки, пункта меню и др.). Это свойство описывается следующим образом:
    property Caption: TCaption;
  • По умолчанию свойство устанавливается таким же, как имя компонента (свойство Name). Для пунктов меню и кнопок с помощью этого свойства можно задать кнопку быстрого вызова, для чего перед символом кнопки быстрого вызова ставится символ амперсанда (&). Например, для быстрого вызова меню Файл перед буквой "Ф" в свойстве Caption данного пункта меню можно поставить знак амперсанда: &Файл. При этом буква "Ф" в пункте меню станет подчеркнутой. Теперь для вызова данного пункта меню пользователю будет достаточно воспользоваться комбина-цией клавиш +<Ф>. Для того чтобы отобразить в заголовке символ &, вы можете использовать такую запись: &&.

  • Свойство ClientHeight предназначено для установки или чтения высоты клиентской области компонента. Это свойство описывается так:
    property ClientHeight: Integer;
    Оно применяется при изменении размеров компонента, которые содержат в себе другие компоненты. При таком изменении будет происходить изменение компонентов, содержащихся в компоненте-контейнере.
  • Свойство ClientOrigin предназначено для получения экранных координат (х и у) левого верхнего угла клиентской области компонента. Началом координат является верхний левый угол экрана. Возвращаемые координаты передаются в структуре типа TPoint. Данное свойство предназначено только для чтения. Оно описано следующим образом:
    property ClientOrigin: TPoint;
  • Свойство ClientRect возвращает координаты углов клиентской области компонента. Данное свойство также предназначено только для чтения. Координаты возвращаются в структуре типа TRect. Свойство описывается так:
    property ClientRect: TRect;
  • Вместо вызова данного свойства можно воспользоваться свойствами Rect,

    ClientWidth и ClientHeight (они описаны ниже):

    Rect (0, 0, ClientWidth, ClientHeight)

  • Свойство ClientWidth предназначено для установки или чтения горизонтального размера клиентской области компонента. Данное свойство описано следующим образом:
    property ClientWidth: Integer;
  • Свойство Сolor определяет цвет фона компонента. Значение данного свойства может быть или числом, определяющим интенсивность трех основных цветов (красного, зеленого и синего), или константой, определенной в Kylix (табл. 8.13).


  • Пример иллюстрирующий работу событий OnEnter и OnExit

    Рисунок 8.20. Пример, иллюстрирующий работу событий OnEnter и OnExit

    Запустим приложение. Фокус при запуске будет передан компоненту, который был размещен на форме первым (в нашем случае это кнопка Button1).

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

  • для кнопки Button1 наступит событие OnExit;
  • для группы переключателей RadioGroup1 наступит событие OnEnter;
  • для выбранного переключателя из группы наступит событие OnEnter.
  • Если после этого выбрать щелчком мыши кнопку Button1, то события произойдут в следующем порядке:

  • для активного переключателя группы наступит событие OnExit;
  • для группы переключателей наступит событие OnExit ;
  • для кнопки Button1 наступит событие OnEnter.
  • Событие OnKeyDown наступает, когда пользователь нажимает любую клавишу. Данное событие происходит для компонента, имеющего фокус в момент нажатия кнопки. С помощью данного события можно обрабатывать все клавиши, включая , и . В процедуру-обработчик передаются, кроме параметра Sender, такие параметры, как Key и Shift. Параметр Key определяет нажатую клавишу. В случае, если нажата не алфавитно-цифровая клавиша, в параметр передается виртуальный код клавиши. Приведем таблицу кодов клавиш (табл. 8.19).


  • Пример применения событий OnDragDrop и OnDragOver

    Рисунок 8.17. Пример применения событий OnDragDrop и OnDragOver

    Примеры создания приложений баз данных

    Примеры создания приложений баз данных

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

    Базы данных типа MyBase предоставляют программисту дополнительные возможности.

  • Сортировка данных по полям без создания дополнительных файлов индексов.
  • Ведение списка изменений и отката сделанных изменений. П Создание агрегатов на основе данных таблицы.
  • Совместное использование одних и тех же данных несколькими наборами данных.
  • Совместимость с Delphi 5 и Delphi 6.
  • Для иллюстрации всего вышесказанного создадим приложение просмотра и редактирования заказов.

    Начнем с создания заготовки приложения. В главном меню Kylix выберем пункт File/New Application (Рисунок 18.1).

    При этом среда создаст проект с пустой формой Form1. Добавим модуль данных. Для этого выберем в главном меню Kylix пункт File/New и в открывшемся диалоговом окне выберем пиктограмму Data Module (Рисунок 18.2).

    Теперь в модуль данных поместим компонент ClientDataSet с вкладки DataAccess. Установим свойство Name данного компонента в компонент Clients. Этот набор данных будет хранить информацию о заказчиках (Рисунок 18.3).

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

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

    Проблемы переноса приложений

    Проблемы переноса приложений

    Kylix предоставляет возможность разработки так называемых кроссплат-форменных (межплатформенных) 32-разрядных приложений, которые могут работать как в среде Linux, так и в Windows, Для этого вы можете выбрать один из двух вариантов:

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

    Большинство приложений, разработанных для работы в среде 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 самостоятельно создает процедуру регистрации компонента в модуле-заготовке. Создателю компонента в данном случае ничего не нужно делать, кроме следующих шагов:

  • выбрать пункт меню Component/Install Components;
  • нажать кнопку Add;
  • указать имя подключаемого модуля (естественно, предварительно нужно сохранить модуль компонента).
  • После компиляции на выбранной вкладке палитры компонентов появится новый компонент.

    Если же вы создаете компонент без использования эксперта компонентов, вам придется самостоятельно дописывать процедуру регистрации компонента. В разделе 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

  • Метод PolyLine рисует да канве незамкнутый многоугольник, т. е. кусочно-линейную кривую. Основное отличие этого метода от метода Polygon заключается в том, что PolyLine не соединяет первую и последнюю точки массива Points.
  • Метод Rectangle предназначен для рисования на канве прямоугольника. В качестве параметров метода передаются координаты двух точек: верхнего левого и правого нижнего углов прямоугольника. Прямоугольник рисуется текущим пером Реn и закрашивается цветом, определенным в свойстве Brush.
    Примечание

    Для рисования прямоугольника без рамки используйте метод FillRect. Для рисования прямоугольника со скругленными углами используйте метод RoundRect. Чтобы нарисовать незакрашенный прямоугольник, используйте метод FrameRect.

  • Метод Refresh служит для немедленной перерисовки изображения компонента. Данный метод вызывает метод Repaint.
  • Метод Remove предназначен для удаления элемента со значением, равным параметру Item из списка типа TList. Данный метод удобно применять, когда неизвестен индекс удаляемого элемента, а известно лишь его значение. В противном случае можно применять метод Delete.
  • Метод Repaint применяется для перерисовки изображения компонента. Данный метод можно применять вместо метода Refresh. Метод Repaint вызывает сначала метод Invalidate, а затем — Update.
  • Метод RoundRect применяется для рисования прямоугольника со скругленными углами. Прямоугольник закрашивается цветом, установленным в свойстве Brush. Два параметра (X1, Y1) и (Х2, Y2) задают координаты углов прямоугольника (как в методе Rectangle). Два других параметра X3 и Y3 задают эллипс с шириной X3 и высотой Y3. Углы прямоугольника скругляются с помощью данного эллипса.
  • Метод SaveToClipboardFormat применяется для создания копии изображения и передачи его в буфер обмена. Однако записать изображение в буфер обмена можно гораздо проще: воспользовавшись методом Assign.
  • Метод SaveToFile сохраняет графическое изображение в файл, задаваемый параметром FileName.
  • Метод SaveToStream сохраняет графическое изображение в поток, задаваемый параметром Stream.
  • Метод ScreenToClient служит для преобразования координат экранной области в координаты клиентской части данного компонента.
  • Метод ScrollBy предназначен для сдвига содержимого данного оконного компонента, включая все его дочерние компоненты. Два параметра DeltaX и DeltaY задают, соответственно, сдвиг по горизонтали и по вертикали. Положительные значения задают сдвиг вправо и вниз, отрицательные — влево и вверх. Например, нижеприведенный код сдвигает содержимое формы Form1 на 10 пикселов влево:
    Form1.ScrollBy (-10, 0);
  • Метод SelectFirst предназначен для передачи фокуса компоненту, находящемуся первым в последовательности табуляции. Например, код
    Form1.SelectFirst;
    выберет первый находящийся в последовательности табуляции компонент для формы Form1.
  • Метод SelectNext передает фокус следующему компоненту, расположенному в последовательности табуляции после указанного в параметре CurControl. Второй параметр GOForward определяет направление поиска компонента: если он равен true — то вперед, иначе — назад. Последний параметр CheckTabStop определяет, должен ли следующий компонент иметь значение true свойства TabStop.
  • Метод SendCancelMode предназначен для прекращения модального состояния данного компонента. Модальным состоянием называется такое состояние компонента, когда он ожидает от пользователя какого-либо действия, причем ни один другой компонент приложения не доступен. Вызов данного метода прекращает ожидание действия со стороны пользователя.
  • Метод SendToBack перемещает указанный компонент в самый конец Z-последовательности. Таким образом, компонент может стать невидимым из-за его перекрытия другими компонентами. Если данный компонент до вызова метода имел фокус, он его потеряет после выполнения метода.
  • Метод SetBounds предназначен для одновременного изменения четырех свойств компонента: Left, Toр, Width и Height. Параметры, соответственно, ALeft, ATop, AWidth и AHeight. Вызов данного метода позволяет сделать код приложения более компактным. Кроме того, перерисовка компонента произойдет здесь всего один раз, а не четыре, как если бы вы изменяли последовательно эти четыре свойства.
  • Метод SetChildOrder применяется для изменения позиции компонента, задаваемого параметром Child, в списке дочерних компонентов данного оконного компонента. Компоненту присваивается новый индекс, задаваемый параметром Order. Пример:
    Form1.SetChildOrder (Button1, 5);
    Таким образом, кнопка Button1 будет расположена в последовательности дочерних элементов формы Form1 на шестом месте (нумерация начинается с нуля).
  • Метод SetFocus предназначен для передачи фокуса данному компоненту. Например:
    Memo1. SetFocus ;
  • Метод SetZOrder предназначен для перемещения данного компонента в начало или конец Z-последовательности. Если параметр TopMost имеет значение true, то компонент перемещается в начало Z-последовательности, иначе — в конец.
  • Метод Show предназначен для того, чтобы сделать видимым невидимый компонент. То есть метод равносилен установке свойства Visible данного компонента в true.
  • Метод Sort предназначен для быстрой сортировки элементов списка типа TList.
  • Метод StretchDraw применяется для рисования графического изображения, содержащегося в компоненте, указанным параметром Graphic в прямоугольную область канвы, заданную параметром Rect, путем растягивания или сжимания изображения под размер данной области. Например, нижеприведенный код уменьшает изображение, находящееся в компоненте Image2 и имеющее размер больше чем 20x20 точек, до размера 20x20 точек и помещает его в компонент Image1:
    Image1,Canvas.StretchDraw ( Rect (0,0,19,19), Image2.Picture.Bitmap) ;
  • Метод TextExtent применяется для получения и длины, и ширины текста Text, который предполагается вывести на канву данного компонента, используя текущий шрифт. Возвращаемое методом значение имеет тип TSize.
  • Метод TextHeight возвращает значение, равное высоте текста Text, который предполагается вывести на канву с использованием текущего шрифта.
  • Метод TextOut предназначен для вывода строки текста, задаваемой параметром Text, на канву в позицию с координатами (X, Y). Например:
    Image1.Canvas.TextOut (10, 100, 'Мне нравится Kylix');
    выведет строку 'Mне нравится Kylix' на канву компонента Image1, начиная с координаты (10, 100).
  • Метод TextRect похож на метод TextOut за исключением того, что текст, выходящий за границы определенной прямоугольной области, урезается.
  • Метод TextWidth предназначен для определения в пикселах длины текста Text, который предполагается вывести на канву компонента текущим шрифтом.
  • Метод TryLock блокирует канву компонента, не позволяя другим потокам многопоточного приложения рисовать на ней. Данный метод возвращает значение true и устанавливает свойство LockCount в единицу, если канва не была ранее блокирована. Если канва была ранее блокирована, метод возвращает false и не увеличивает значение свойства LockCount.
  • Метод Unlock предназначен для разблокирования канвы компонента. Каждый вызов метода Unlock уменьшает значение свойства LockCount на единицу.
  • Метод Update предназначен для немедленной перерисовки компонента, без ожидания завершения каких-либо других процессов.
  • Поля
    Поле (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).

    Результат выполнения метода Pie

    Диалоговое окно New Items

    Рисунок 10.1. Диалоговое окно New Items

    Диалоговое окно New Items
    2. Щелкните на пиктограмме Application.

    3. Нажмите кнопку ОК.

    Для создания нового MDI-приложения выполните следующие шаги:

    1. Выберите в главном меню Kylix пункт File/New для вызова диалогового окна New Items.

    2. Выберите в диалоговом окне вкладку Projects и щелкните на пиктограмме MDI Application (Рисунок 10.2).

    3 Нажмите кнопку ОК.


    Вкладка Projects

    Рисунок 10.2. Вкладка Projects

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

  • fsMDIForm — для главной формы;
  • fsMDIChild — для дочерних форм.
  • При создании MDI-приложения Kylix делает большую часть работы за программиста. Если вы выполнили вышеперечисленные шаги для создания MDI-приложения, то можете видеть, что Kylix уже создал главную форму (Рисунок 10.3).


    Главная форма MDIприложения

    Рисунок 10.3. Главная форма MDI-приложения

    Главная форма MDIприложения
    Более того, данная форма имеет необходимые компоненты для работы со многими дочерними окнами, а также главное меню для работы с файлами и окнами. Кроме того, меню содержит пункт Edit для работы с текстом. Таким образом, Kylix уже сделал для нас простейший многооконный текстовый редактор. Естественно, вы можете самостоятельно расширить его функциональность либо удалить ненужные компоненты.


    Три расположенных рядом дочерних окна внутри главной формы

    Рисунок 10.4. Три расположенных рядом дочерних окна внутри главной формы

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

    Для поддержания всей этой функциональности Kylix создал специальный код, который размещен в модуле clxmain (листинг 10.6).



    Пиктограмма Console Application

    Рисунок 10.5. Пиктограмма Console Application

    Пиктограмма 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

    Обработка события OnMouseDown
    Еще один пример (листинг 13.26) устанавливает текущую позицию пера в координаты, в которых пользователь щелкнул мышью.



    Пример рисования линий

    Рисунок 13.8. Пример рисования линий

    Пример рисования линий
    Обработка события OnMouseMove

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

    Нижеприведенный пример (листинг 13.28) показывает, как можно использовать событие OnMouseMove для немедленного рисования линий (Рисунок 13.9).


    Обработка события OnMouseMove

    Рисунок 13.9. Обработка события OnMouseMove

    Обработка события OnMouseMove
    Назад Вперед

    Добавление объекта потока в проект с помощью диалогового окна New Items

    Рисунок 14.1. Добавление объекта потока в проект с помощью диалогового окна New Items

    Добавление объекта потока в проект с помощью диалогового окна 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. Схема приложения базы данных

    Схема приложения базы данных
    Рассмотрим все четыре части приложения баз данных:

  • интерфейс пользователя — предназначен для взаимодействия вашего приложения с пользователем. На схеме интерфейс пользователя отделен от всех других частей приложения. Отделение его от других частей имеет некоторые преимущества. Таким образом вы делаете свое приложение более гибким, т: к. изменения в данной части не повлекут за собой изменений в модуле данных, и наоборот. В дополнение к вышеописанному, изоляция части пользовательского интерфейса позволит вам использовать формы интерфейса пользователя в похожих приложениях;
  • источник данных — обеспечивает канал связи между пользовательским интерфейсом и набором данных. Многие компоненты, предназначенные для отображения данных, могут использовать один и тот же источник данных. В этом случае при перемещении по записям базы данных в каждом из таких компонентов синхронно будут отображаться одинаковые данные;
  • набор данных — это сердце вашего приложения базы данных. Этот компонент представляет набор записей из одной или нескольких таблиц базы данных;
  • соединение с данными — зависит от используемого набора данных.
  • Среда Kylix обеспечивает поддержку двух типов наборов данных:

  • клиентский набор данных — хранит данные в памяти, благодаря чему пе-ремещение по данным осуществляется просто и эффективно. Клиентский набор данных обеспечивает простой метод фильтрации записей и объединения данных. Так как данные кэшируются в памяти, этот набор данных может содержать ограниченное число записей. Имеется два типа клиентских наборов данных: общий клиентский набор данных и клиентский набор данных, использующий SQL. Первый обеспечивает доступ к данным, работая напрямую с файлами, расположенными на локальных дисках, соединяясь с другими наборами данных в одном и том же модуле данных или соединяясь с сервером баз данных. Второй может или использовать файлы, расположенные на локальных дисках, или соединяться с сервером базы данных;
  • однонаправленный набор данных — может читать данные, описанные в запросе SQL или возвращаемые хранимой на сервере процедурой. Этот вид набора данных не хранит данные в памяти и является менее гибким в использовании по сравнению с клиентским набором данных. Единственным направлением перемещения по записям в однонаправленном наборе данных является направление, указанное в SQL-запросе команды ORDER BY. Вы не можете использовать однонаправленный набор данных для обновления данных. Однако этот вид набора данных обеспечивает быстрый доступ к информации, хранящейся на сервере базы данных, и может предоставлять значительно больший объем информации по сравнению с клиентским набором данных.
  • В дополнение к вышеописанным наборам данных вы можете создать собственный набор данных. Для этого вам придется использовать класс TDataSet в качестве предка.

    Назад Вперед

    Структура таблицы базы данных

    Рисунок 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

    Результат обработки события 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);

    Записи

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

    Записи делятся на:
  • фиксированные;
  • вариантные.
  • Фиксированная запись — это запись, которая состоит из фиксированного числа полей. Для объявления фиксированной записи применяется следующая конструкция языка Object Pascal:

    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 начинается вариантная часть. В этой части:
  • признак (tag) является необязательной частью и представляет собой любую объявленную переменную типа ordinalType. Если вы не используете переменной, то можно ставить двоеточие сразу после слова case;
  • ordinalType — это порядковый тип;
  • каждый из вариантов значения переменной tag, представленный в списке constantList, должен быть единственным, без повторов;
  • каждое описание варианта (variant1 .. variantn) должно содержать обычное описание поля, например Fieidvar1: type1;.
  • Приведем пример использования вариантной записи. Предположим, что запись должна содержать данные о человеке. Назовем запись Person. Пусть она содержит имя (поле FirstName), фамилию (поле LastName), дату рождения (поле BirthDate) человека. Кроме того, если человек является гражданином России, в записи указывается место его рождения (поле BirthPlace). Если же человек — иностранец, то в записи о нем должны присутствовать следующие поля: страна (поле Country), дата въезда в Россию (поле EntryDate) и дата отъезда из России (поле ExitDate). Такую запись мы объявляем в листинге 2.1.



    Вкладка Packages диалогового окна Project Options

    Рисунок 20.1. Вкладка Packages диалогового окна Project Options

    Вкладка 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

    Пиктограмма Package диалогового окна New Items
    Редактор пакета включает в себя два раздела: содержания (Contains) и требований (Requires). Для добавления нового модуля в раздел содержания выберите раздел Contains щелчком мыши, затем щелкните на кнопке Add редактора пакета. Появится диалоговое окно Add (Рисунок 20.6).


    Редактор пакета

    Рисунок 20.5. Редактор пакета

    Редактор пакета

    Вкладка Add Unit диалогового окна Add

    Рисунок 20.6. Вкладка Add Unit диалогового окна Add

    Вкладка Add Unit диалогового окна Add
    На вкладке Add Unit диалогового окна Add запишите в поле имени файла модуля имя файла pas, который вы хотите включить в пакет, либо воспользуйтесь кнопкой Browse для непосредственного указания файла. В результате выбранный файл модуля будет добавлен в раздел Contains вашего пакета.

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

    3. Для добавления пакетов в раздел Requires выберите этот раздел щелчком мыши, затем нажмите кнопку Add редактора пакета.


    Диалоговое окно Add

    Рисунок 20.7. Диалоговое окно Add

    Диалоговое окно 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

    Диалоговое окно Project Options
    Редактировать уже существующий файл пакета можно по-разному:

  • выбрать пункт главного меню Kylix File/Open и в нем уже — файл пакета, который необходимо редактировать;
  • выбрать пункт главного меню Kylix Component/Install Component, выбрать нужный пакет в списке пакетов и нажать кнопку Edit;
  • в открытом редакторе пакета выбрать в разделе Requires нужный пакет, щелкнуть на нем правой кнопкой мыши для появления контекстного меню, где выбрать пункт Open.
  • Кроме того, вы можете редактировать файл пакета точно так же, как и файл проекта — вручную, как текстовый файл. Файл пакета содержит в себе три раздела:

  • название пакета (в разделе Package);
  • раздел требуемых файлов для данного пакета (раздел Requires);
  • раздел, содержащий названия файлов модулей, входящих в данный пакет (раздел Contains).
  • Приведем в качестве примера содержимое файла пакета user:

    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

    Модуль Unitl pas
    Рассмотрим состав модуля более подробно:

    unit имя модуля; interface // Начало раздела интерфейса
    uses // Список используемых модулей
    const // Раздел объявления констант
    type // Раздел объявления типов
    var // Раздел объявления переменных
    // Заголовки процедур // Заголовки функций implementation // Раздел реализации
    uses // Список используемых модулей const // Раздел объявления констант
    type // Раздел объявления типов
    var // Раздел объявления переменных
    // Описание процедур // Описание функций
    initialization // Раздел инициализации // Операторы и команды finalization // Раздел завершения // Операторы и команды
    end.
    Первый раздел — раздел интерфейса, который является как бы "лицом" данного модуля. В нем размещены описания модулей, используемых данным модулем, а также объявляются типы, константы, переменные, функции и процедуры, описываются идентификаторы, являющиеся доступными всем модулям и программам, использующим данный модуль. Заметим, что для функций и процедур в данном разделе записываются только их заголовки. Непосредственно процедуры и функции размещены в следующем разделе — разделе реализации.

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

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

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

    Назад

    Иерархия классов Kylix

    Рисунок 7.1. Иерархия классов Kylix

    Иерархия классов Kylix
    Следующий базовый класс, являющийся прямым потомком TObject, — класс TPersistent. Данный класс является предком всех классов, предназначенных для работы с потоками. Класс TPersistent наследует все свойства и методы своего предка — класса TObject, и может, кроме того, считывать данные из потока и записывать их в поток. Класс TPersistent обеспечивает:

  • определения процедур для загрузки и помещения данных в поток;
  • назначение свойствам экземпляра класса конкретных значений;
  • средства для передачи содержимого одного экземпляра класса другому.
  • На одном уровне с классом TPersistent находится класс TStream, который тоже является прямым потомком класса TObject. Класс TStream является базовым для объектов потока. Этот класс может читать или записывать данные с носителей разных видов (файлы на дисках, динамическая память и т. д.). В дополнение к методам чтения, записи и копирования данных из потока настоящий класс обеспечивает поиск нужной позиции внутри потока. Этот класс относится к абстрактным классам и имеет следующие дочерние классы:

  • TFileStream — для работы с файлами;
  • TStringStream — для манипулирования строками в памяти;
  • TMemoryStream — для работы с буфером памяти.
  • Потомком класса TPersistent является класс TComponent — базовый класс всех компонентов библиотеки компонентов CLX Kylix. Наследники класса TComponent, как и сам класс, имеют следующие возможности:

  • способность отображаться на палитре компонентов Kylix,
  • способность размещения на форме;
  • способность быть обладателем других компонентов и управлять другими компонентами.
  • На одном уровне с классом TComponent находятся еще несколько классов. Рассмотрим наиболее интересные из них.

    Класс TGraphic — потомок класса Tpersistent, абстрактный класс. Данный класс является родительским для таких объектов, как иконки, растровые изображения и метафайлы, которые могут хранить и отображать визуальные изображения. Данный класс, кроме того, предоставляет методы для работы с объектом TPicture и буфером обмена.

    Класс THandleComponent — является базовым для невизуальных компонентов, у которых имеется дескриптор окна.

    Дескриптор окна — это число (индекс), индивидуальное для данного конкретного окна, назначаемое системой Linux.

    Класс TField — является базовым для всех компонентов, содержащих поля. Данный класс инкапсулирует свойства, события и методы, которые используются для:

  • смены значения поля в наборе данных;
  • конвертирования типов данных внутри поля;
  • подтверждения ввода данных в поле;
  • определения того, в каком качестве находятся данные внутри поля: в качестве редактируемых или отображаемых;
  • подсчета результата в полях данных с помощью события OnCalcFields;
  • просмотра значений полей из других наборов данных.
  • Класс TDialog — это абстрактный класс, являющийся предком для всех диалоговых окон. Он используется как базовый класс для двух основных типов диалоговых окон CLX:

  • TQtDialog — базовый класс, инкапсулирующий библиотеку диалогов Qt. Он используется для таких задач, как открытие и сохранение файлов, установка шрифта и цвета, а также для печати;
  • TCustomDialog — используется для решения задач поиска и замены текста в файле.
  • Следующий класс — потомок вышеописанного класса TComponent — класс TControl. Класс TControl является базовым классом для всех визуальных компонентов, т. е. потомки этого класса будут видны и доступны пользователю во время выполнения приложения. Все классы, являющиеся потомками TControl, имеют свойства, методы и события, которые определяют особенности данного класса, например положение компонента на экране, размер и т. д.

    Нам осталось рассмотреть еще два класса, которые являются потомками класса TControl.

    Первый из этих классов — класс TGraphicControl. Данный класс предназначен для создания визуальных компонентов, которые не являются окнами, т. е. не могут содержать в себе других компонентов и не могут получать фокус ввода. Главное предназначение данного класса — способность отображать графику или текст на компоненте. Примерами потомков класса TGraphicControl могут выступать такие компоненты, как, например, TBevel, TImage. Класс TGraphicControl передает своим потомкам свойство Сanvas, позволяющее получать доступ к поверхности компонента, на которой можно рисовать или писать. Кроме того, класс TGraphicControl передает своим потомкам метод Paint.

    Примечание

    Подробному изучению графических возможностей Kylix посвящена глава 13 книги.

    Второй из этих классов — класс TWidgetControl. Данный класс является базовым классом для всех оконных визуальных компонентов.

    Оконный визуальный компонент — это компонент, который:

  • может получать фокус ввода во время выполнения приложения;
  • может содержать в себе другие компоненты. Компонент, который содержит в себе другие компоненты, называется родительским (parent). Компонент, содержащийся в другом компоненте, называется дочерним (child);
  • П имеет идентификатор окна (handle). Каждый оконный компонент обрабатывается непосредственно операционной системой, поэтому ему назначается индивидуальный уникальный идентификатор. В CLX свойство Handle является ничем иным, как указателем на Qt-объект, но называется дескриптором для совместимости с кодом VCL Delphi.
  • Примером оконного компонента является TCustomEdit.
    Займемся теперь потомками класса 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. Для начала перечислим эти события:

  • OnChange
  • OnClick
  • OnDblClick
  • OnDragDrop
  • OnDragOver
  • OnKeyPress
  • OnKeyUp
  • OnMouseDown
  • OnMouseMove
  • OnPain
  • OnEndDrag
  • OnEnter
  • OnExit
  • OnKeyDown
  • OnProgress
  • OnStartDrag
  • OnMouseUp
  • Рассмотрим каждое событие более подробно.

  • Событие OnChange наступает после изменения какого-либо графического объекта. Создавайте обработчик такого события для выполнения каких-либо операций, происходящих, после изменения графического объекта.
  • Событие OnClick какого-либо компонента наступает в случае, если пользователь нажал и отпустил левую кнопку мыши в тот момент, когда указатель мыши находился на компоненте. Кроме того, событие OnClick происходит в следующих случаях:
    • при выборе пользователем путем нажатия клавиш управления курсором элемента в сетке (Grid), дереве (Trее), списке (List) или выпадающем списке (DropDown List);

    • при нажатии пользователем клавиши < Пробел> или в тот момент, когда компонент (например, кнопка) был в фокусе (Component. Focused = True);

    • при нажатии пользователем клавиши в случае, если активная форма имеет кнопку по умолчанию;

    • при нажатии пользователем клавиши в случае, если активная форма имеет кнопку прерывания;

    • при нажатии пользователем комбинации клавиш быстрого доступа ("горячих" клавиш) для доступа к кнопке или пункту меню. Например, в свойстве Caption кнопки формы записано &Пуск, при этом надпись на кнопке имеет вид Пуск. В этом случае, если пользователь нажимает комбинацию клавиш +<П>, происходит событие OnClick;

    • при установке приложением свойства Сhecked переключателя RadioButton в true;

    • при изменении приложением свойства Checked индикатора CheckBox;

    • при вызове метода Click элемента меню приложения.

  • Событие OnClick возникает для формы в том случае, когда пользователь щелкнул на любом месте формы, незанятом компонентами.
  • Событие OnDblClick наступает тогда, когда пользователь дважды щелкнул левой кнопкой мыши на компоненте, причем отпустил кнопку мыши после второго щелчка над компонентом.
    Примечаниe
    К одному и тому же компоненту нельзя написать обработчики событий OnClick и OnDblClick, поскольку первый из них всегда перехватит первый из щелчков.

  • Событие OnStartDrag наступает, когда пользователь начинает перетаскивать компонент, т. е. нажал над компонентом левую кнопку мыши и, не отпуская ее, начал смещать курсор мыши. Событие имеет параметр Sender, который содержит наименование перетаскиваемого компонента, или объекта перетаскивания (в случае, если компонент является компонентом контейнерного типа).
  • Событие OnDragDrop компонента наступает, когда пользователь отпускает перетаскиваемый компонент над другим компонентом. В обработчике события нужно описать, что должно происходить в момент отпускания перетаскиваемого компонента. При этом параметр Source должен соответствовать перетаскиваемому компоненту, а параметр sender должен соответствовать компоненту, над которым компонент будет отпущен. Кроме того, два параметра (X и Y) служат для хранения координат курсора мыши над компонентом. Система координат в данном случае соответствует клиентской части компонента.
  • Событие OnDragOver компонента наступает, когда перетаскиваемый компонент пересекает границу данного компонента и оказывается над ним. Это событие возникает все время, пока пользователь перемещает компонент над компонентом-приемником. Как только пользователь отпускает компонент (отпускает левую кнопку мыши), происходит событие OnDragDrop, описанное выше. Для того чтобы определить, компоненты какого типа принимает данный компонент, используют параметр Accept. Если компонент может принимать любые компоненты, можно оставить обработчик OnDragOver пустым, но он обязательно должен присутствовать. Например:
  • procedure TForm1.ListBox2DragOver(Sender, Source: TOtrject; X, Y: Integer;
    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).

    Менеджер помощи содержит список всех зарегистрированных в системе программ для отображения файлов помощи и передает ему запросы вашего приложения. Запросы передаются в две фазы:

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

  • Итак, CLX обеспечивает связь между вашим приложением и программой для просмотра файлов справки с помощью интерфейсов. Эти интерфейсы описаны в файле HelpIntfs.pas, который также содержит код, реализующий менеджер помощи (см. Приложение 1):

  • ICustomHelpViewer обеспечивает поддержку отображения помощи по заданному ключевому слову, а также отображения оглавления файла справки;
  • IExtendedHelpViewer обеспечивает поддержку отображения помощи по номеру контекста справки, а также отображения тем. В большинстве справочных систем функция темы в обеспечении ключевых слов высшего уровня (например, в справочной системе Kylix слово IntToStr является ключевым словом, но строка String manipulation routines является названием темы);
  • ISpecialWinHelpViewer обеспечивает поддержку ответа на специализированные сообщения WinHelp в случае, если приложение запущено под Windows. В поддержке данного интерфейса нуждаются только те приложения, которые работают в среде Windows. Более того, это необходимо, когда приложение использует нестандартные сообщения WinHelp;
  • IHelpManager обеспечивает механизм для обратной связи программы просмотра файлов помощи с менеджером помощи вашего приложения. Этот механизм необходим, если программа просмотра помощи нуждается в дополнительной информации;
  • IHelpSystem обеспечивает механизм, с помощью которого TApplication отсылает запросы в систему помощи. TApplication получает экземпляр объекта, который поддерживает два интерфейса IHelpSystem и IHelpManager;
  • IHelpSelector обеспечивает механизм, с помощью которого система помощи может использовать пользовательский интерфейс для того, чтобы узнать у пользователя, какую программу необходимо применить для просмотра файлов справки, если более чем один просмотрщик файлов справки может отображать данный файл.
  • Интерфейс ICustomHelpViewer содержит три типа методов:

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

  • ICustomHelpViewer. GetViewerName: String; — Вызывается, когда менеджер помощи должен узнать имя программы для показа файлов справки (например, когда приложение запрашивает список всех зарегистрированных в системе программ просмотра файлов помощи). Данная функция возвращает информацию в строковой форме (String);
  • ICustomHelpViewer.NotifyID(const ViewerID: Integer); — вызывается немедленно после регистрации программы для просмотра файлов помощи, чтобы присвоить ей уникальный идентификационный номер;
  • ICustomHelpViewer.ShutDown; - вызывается из менеджера помощи для уведомления программы — просмотрщика помощи в том, что менеджер отключается и ресурсы, занятые просмотрщиком помощи, должны быть освобождены.
  • Интерфейс IHelpManager позволяет просмотрщику помощи передавать четыре запроса:

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

  • IHelpManager.GetHandle : LongInt; — вызывается просмотрщиком файлов помощи, если он нуждается в дескрипторе текущего оконного компонента;
  • IHelpManager.GetHelpFile: String; — вызывается просмотрщиком помощи, если ему необходимо узнать имя файла помощи, который назначен активному оконному компоненту;
  • IHelpManager.GetHelpPath: String; — вызывается просмотрщиком помощи, если ему нужно узнать путь к файлу справки. Данная информация не предоставляется по умолчанию, т. к. многие из внешних систем помощи способны самостоятельно определить путь с помощью переменных среды или другими способами;
  • IHelpManager.Release; — вызывается для уведомления менеджера помощи об отключении просмотрщика помощи. Данный метод никогда не должен вызываться в ответ на запрос, приходящий из ICustomHelpViewer.ShutDown. Метод используется только для уведомления менеджера помощи о неожиданном разрыве соединения.
  • Запросы на отображение разделов справки обычно идут по ключевому слову, в этом случае просмотрщик помощи обеспечивает помощь, основанную на строке текста. Второй вариант основан на контексте справки, в этом случае просмотрщик обеспечивает помощь, основанную на числовом иденти-фикат.оре. Последний вариант является обычным вариантом предоставления справки в приложениях, работающих в среде Windows и использующих систему WinHelp. Несмотря на то, что CLX поддерживает данный вариант, он не рекомендуется, т. к. большинство справочных систем Linux не поддерживают его.

    Интерфейс ICustomHelpViewer необходим для обеспечения поддержки помощи по ключевому слову. Интерфейс IExtendedHelpViewer необходим для поддержки контекстно-зависимой помощи.

    Интерфейс ICustomHelpViewer предоставляет три метода для работы со справкой по ключевому слову:

  • ICustomHelpViewer.CanShowKeyword(const HelpString: String): Integer; — метод, который вызывается менеджером помощи. Данный метод опрашивает каждый из зарегистрированных в системе просмoтрщиков помощи на возможность отображения справки по ключевому слову. Ожидается, что просмотрщик даст ответ в виде целого числа, которое указывает, сколько различных страниц справки может отобразить данный просмотрщик в ответ на запрос менеджера помощи. Просмотрщик может использовать любые методы для определения этого числа. Если просмотрщик не поддерживает помощь по данному ключевому слову, он возвращает нулевое значение. Отрицательные значения, возвращаемые просмотрщиками, в настоящее время расцениваются как нулевые, но в будущем могут использоваться для каких-либо других целей;
  • ICustomHelpViewer.GetHelpStrings(const HelpString: String):TStringList; — вызывается менеджером помощи если более одного про-смотрщика способны отобразить помощь для данного ключевого слова. При вызове данного метода ожидается, что просмотрщик возвратит значение типа TStringList. Строки возвращаемого списка должны указывать на страницы, которые содержат данное ключевое слово, но характеристики данного списка могут отличаться у разных просмотрщиков. В случае, когда ответ приходит от просмотрщика HyperHelp, список строк всегда содержит всего одну ссылку на каждую из страниц, в которой есть ключевое слово;
  • ICustomHelpViewer.ShowHelp(const HelpString: String); —вызывается менеджером помощи, если необходим просмотрщик помощи для отображения справки по ключевому слову.
  • Интерфейс ICustomHelpViewer обеспечивает два метода, связанных с отображением содержания файла справки:

  • CanShowTableOfContents;
  • ShoWTableOfContents.
  • Теоретически их работа схожа с работой методов просмотра помощи по ключевому слову: менеджер помощи сначала запрашивает все просмотрщики с помощью метода ICustomHelpViewer.CanShowTableOfContents: Boolean;, затем вызывает конкретную программу-просмотрщик с помощью вызова метода ICustomHelpViewer.ShowTableOfContents.

    Для того чтобы менеджер помощи мог работать с интерфейсами ICustomHelpViewer, IExtendedHelpViewer, ISpecialWinHelpViewer и IhelpSelector, необходимо осуществить регистрацию объекта справочной системы.

    Модуль, который содержит описание данного объекта, должен иметь в списке используемых модулей модули HelpIntfs и QForms. Экземпляр объекта должен быть объявлен в секции var раздела реализации (implementing) модуля.

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

    /kylix/demos/helpviewers/.

    Здесь располагаются три основных файла:

  • HelpViewers.dpk
  • ManViewer.pas
  • WinHelpViewer.pas
  • Прежде чем рассмотреть эти три файла, отметим, что справочная система CLX имеет подключаемую архитектуру, которая работает через интерфейс IHelpSystem.

    Модуль WinHelpViewer обеспечивает связь между приложением и HyperHelp (эмулятором WinHelp под Linux).

    Модуль ManViewer обеспечивает связь между приложением и системой Linux man.

    Пакет HelpViewers представляет собой пример пакета, который содержит модуль ManViewer. Этот пакет зарегистрирован как пакет времени разработки в IDE и обеспечивает связь IDE со страницами man. Данный пакет не может быть использован во время работы приложения.

    с конкретным кодом, называемым обработчиком

    События

    Событие (event) — это механизм, который связывает какое-либо происшествие с конкретным кодом, называемым обработчиком события (event handler).

    Механизм обработки событий будет подробно рассмотрен во второй части книги. Пока лишь отметим, что среда Kylix поддерживает два основных типа событий:

  • пользовательские (widget);
  • системные (system).
  • К пользовательским относят события, которые происходят из-за взаимодействия пользователя с программой. Например, движение мышкой, нажатие кнопки и т. д.

    Системные события — это события, происходящие в операционной системе. Например, тикание системного таймера.

    Назад Вперед

    Сообщения и системные события

    Сообщения и системные события

    Сообщения и события в 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 позволяет создавать приложения двух моделей пользовательского интерфейса:

  • одиночный интерфейс документа (Single document interface, SDI),
  • многооконный интерфейс документа (Multiple document interface, MDI).
  • В MDI-приложении в главном родительском окне может располагаться более чем одно дочернее окно или документ Такая форма наиболее часто используется в приложениях электронных таблиц или текстовых процессорах. В SDI-приложении, напротив, может содержаться только один документ или может быть активным всего одно окно. Для того чтобы приложение имело вид SDI, необходимо установить свойство FormStyle для формы приложения в fsNormal.

    Примечание

    По умолчанию свойство 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, как уже говорилось ранее, содержит имена файлов пакетов, необходимых для работы рассматриваемого пакета. Следует заметить, что пакеты не могут содержать круговые ссылки, т. е. не должно возникать следующих ситуаций:

  • пакет не должен содержать ссылку на самого себя;
  • если пакет Package1 содержит в разделе Requires пакет Package2, то Package2 не должен содержать в своем разделе Requires пакет Package1;
  • если пакету Package1 требуется пакет Package2, а пакету Package2 — Package3, то пакет Package3 не должен содержать в разделе Requires пакет Package1.
  • Раздел Contains включает в себя файлы модулей (pas), входящих в проект.

    Назад Вперед

    Структура программы

    Структура программы

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

    Структура программы состоит из:

  • заголовка программы (program heading);
  • раздела uses (данный раздел может не входить в структуру программы);
  • блока описания и исполнения (block of declarations and statements).
  • Заголовок программы находится в самом ее начале и нужен для определения имени программы:

    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.

    Выражение-селектор должно быть обязательно порядкового типа. Нельзя использовать в качестве селектора строковые типы.

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

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



    Структурные типы данных

    Структурные типы данных

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

  • строки;
  • множества;
  • массивы;
  • записи;
  • файлы.
  • Рассмотрим эти типы данных.

    Строки

    В Object Pascal имеются строковые типы данных, которые перечислены в табл. 2.4.



    Свойства сгруппированные по категориям

    Рисунок 6.6. Свойства, сгруппированные по категориям

    Свойства сгруппированные по категориям

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

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

    CLX представляет собой иерархию классов Kylix, написанных на языке Object Pascal. Все классы библиотеки имеют свои свойства, события и методы. Мы их подробно рассмотрим в следующей главе. Пока же дадим здесь общее описание.

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

    Компоненты CLX могут генерировать и обрабатывать несколько десятков самых разнообразных событий. События всегда принадлежат определенному типу. Большинство событий имеет тип "уведомляющее" (то есть принадлежит типу TNotifyEvent). Данный тип описывается следующим образом:

    type TNotifyEvent = procedure (Sender: TObject) of object;

    Таким образом, события уведомляющего типа указывают на источник события. Источник события записывается в параметре Sender.

    Напомним, что все события в Kylix делятся на:
  • пользовательские, или оконные (widget);
  • системные (system),.
  • Пользовательские (оконные) события — это события, которые происходят в результате каких-либо действий пользователя (движение мышью, нажатие кнопки и т. д.).

    Системные события — это события, которые происходят внутри системы независимо от действий пользователя (тикание таймера и т. д.).

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

    Назад Вперед

    Свойства события и методы основных компонентов Kylix

    Свойства, события и методы основных компонентов Kylix

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

    Типы свойств

    Следует отметить, что к свойствам применимы те же правила, которые используются для описания типов в Object Pascal. Типы свойств компонента нужны в первую очередь для отображения и редактирования его в окне инспектора объектов. Перечислим основные типы свойств компонентов Kylix (табл. 8.12).



    и поля, определяют атрибуты объекта.

    Свойства

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

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

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

    property Имя свойства: тип описания;

  • имя свойства должно быть уникальным;
  • тип — определяет, значения какого типа могут быть записаны в данном свойстве;
  • описания — объявления способов доступа к данному свойству.
  • Каждое свойство объекта должно иметь, как минимум, одно обязательное объявление способа доступа к свойству. Имеется два обязательных описания доступа к свойству объекта: чтение (read) значения свойства и запись (write) значения свойства.

    Синтаксис обязательных описаний 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

    Определяет текущую позицию пера

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



    Методы объекта 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.5.



    События мыши

    Таблица 13.4. События мыши

    Событие мыши

    Описание

    OnMouseDown

    Происходит, когда пользователь нажимает кнопку мыши в тот момент, когда указатель мыши расположен над компонентом

    OnMouseMove

    Происходит, когда пользователь двигает мышью в тот момент, когда указатель мыши расположен над компонентом



    Параметры событий мыши

    Таблица 13.5. Параметры событий мыши

    Параметр

    Значение

    Sender

    Имя объекта, над которым произошло событие мыши

    Button

    Указывает, какая из трех кнопок мыши нажата. Может принимать значения: mbLeft — левая; mbMiddle — средняя и mbRight — правая

    Shift

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

    X, Y

    Координаты клиентской части компонента, над которым произошло событие мыши

    Обработка события OnMouseDown

    Всякий раз, когда пользователь нажимает любую кнопку мыши, происходит событие 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

    Компонент TClientDataSet представляет собой клиентский набор данных, который не зависит от типа используемой базы данных. Описание его свойств представлено в табл. 16.2.



    Содержит список наименований полей таблицы,

    Таблица 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

    Компонент TDataSetProvider — предназначен для формирования пакетов данных для отправки их клиентам. Свойства этого компонента перечислены в табл. 16.3.



    Свойства компонента 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
    Компонент TSQLDataSet — представляет собой однонаправленный набор данных. В табл. 16,5 перечислены его основные свойства.


    Свойства компонента 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

    Таблица 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
    Компонент TSQLStoredProc — предназначен для работы с процедурами, хранимыми на сервере базы данных. При получении данных ведет себя однонаправленно. Табл. 16.7 дает описание основных свойств этого компонента.



    Определяет список параметров процедуры. Имеет

    Таблица 16.7 (окончание)

    Свойство
    Описание
    Params
    Определяет список параметров процедуры. Имеет тип Tparams
    SQLConnection
    Содержит имя компонента TSQLConnection, с помощью которого будет осуществляться соединение с базой данных. Имеет
    тип TSQLConnection
    Tag
    Свойство, которое может использоваться по усмотрению программиста, и у него нет специального назначения. Свойство имеет тип Integer
    Компонент TSQLTablе — задает таблицу баз данных и представляет собой однонаправленный набор данных. В табл. 16.8 перечислены основные свойства компонента.


    Свойства компонента 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

    Таблица 16.9. Свойства компонента TSQLMonitor

    Свойство
    Описание
    ActiveОпределяет, является ли монитор активным. Свойство имеет тип
    Boolean
    AutoSaveОпределяет, будет ли производиться автоматическое сохранение журнала событий в файл, указанный в свойстве FileName данного компонента. Имеет тип Boolean
    FileNameОпределяет имя файла, в который будет производиться запись журнала событий. Имеет тип String
    SQLConnectionСодержит имя компонента TSQLConnection, с помощью которого будет осуществляться соединение с базой данных. Имеет тип TSQLConnection
    TagСвойство, которое может использоваться по усмотрению программиста, и у него нет специального назначения. Свойство имеет тип Integer
    TraceListДанное свойство содержит журнал событий. Имеет тип Tstrings
    Компонент TSQLClientDataSet — представляет собой клиентский набор данных. Описание его основных свойств представлено в табл. 16.10.



    Основные операторы определения данных

    Таблица 17.1. Основные операторы определения данных

    Оператор

    Описание

    CREATE TABLE

    Предназначен для создания таблицы базы данных

    ALTER TABLE

    Удаляет таблицу

    DROP TABLE

    Изменяет структуру таблицы

    CREATE INDEX

    Создает индекс

    DROP INDEX

    Удаляет индекс

    CREATE VIEW

    Создает представление

    DROP VIEW

    Удаляет представление

    Операторы управления данными — предназначены для управления привилегиями доступа к данным. Основные операторы представлены в табл. 17.2.



    Основные операторы управления данными

    Таблица 17.2. Основные операторы управления данными

    Оператор

    Описание

    GRAND

    Назначает привилегии пользователям

    REVOKE

    Удаляет привилегии пользователей

    Операторы манипулирования данными — предназначены для работы с записями таблиц. Основные операторы кратко описаны в табл. 17.3.



    Основные операторы манипулирования данными

    Таблица 17.3. Основные операторы манипулирования данными

    Оператор

    Описание

    SELECT

    Предназначен для выборки записей по определенному формату

    UPDATE

    Предназначен для изменения и обновления записей

    INSERT

    Вставляет новые записи в таблицу

    DELETE

    Удаляет записи из таблицы

    Использование приведенных в табл. 17.1—17.3 операторов мы рассмотрим далее в этой главе.

    Примечание

    Обратите внимание на тот факт, что проверка синтаксиса запроса происходит только во время работы приложения. Компилятор Kylix не обрабатывает SQL-запросы во время разработки приложения.

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

    Осталось отметить, что регистр букв команд SQL-запросов не влияет на их выполнение. Мы для наглядности будем применять заглавные буквы для операторов языка SQL. Точка с запятой также не обязательна в конце каждой SQL-команды. Элементы списков, такие как имена таблиц и полей, обязательно разделяются запятыми. Имена таблиц и полей заключаются в одинарные или двойные кавычки, например 'Number', "Table 1". В случае если имя не содержит пробелов и других специальных символов, его можно не заключать в кавычки.

    Вперед

    Основные статистические функции

    Таблица 17.4. Основные статистические функции

    Функция

    Описание

    AVG ( )

    Получение среднего значения

    COUNT ( )

    Определяет количество значений

    COUNT ( * )

    Определяет количество ненулевых значений

    MAX ( )

    Максимальное значение

    MIN( )

    Минимальное значение

    SUM ( )

    Сумма значений

    Строковые функции — функции, предназначенные для работы со строковыми значениями. Наиболее часто используемые из них представлены в табл. 17.5.



    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счетчикftAutoInc0
    Nameимя клиентаFtString50
    Определения полей


    Поля определяемые в свойстве ChlidDefs

    Таблица 18.2. Поля, определяемые в свойстве ChlidDefs

    Имя поля
    Описание
    Тип данных
    Размер
    IDсчетчикFtAutoInс0
    OrderNameописание заказаFtString20
    Priceцена заказаFtCurrency0
    Осталось только на основе описанных определений создать набор данных (щелкнув правой кнопкой мыши и выбрав пункт выпадающего меню Create Data Set). Затем сохранить в файл (Save to MyBase xml table) и на основе этих определений явным образом создать поля (дважды щелкнув на Clients, затем щелнув правой кнопкой мыши и выбрав пункт Add all fields). Откроем созданный xml-файл (листинг 18.2).

    Базовые классы CLX

    Таблица 19.1. Базовые классы CLX

    Класс

    Возможности класса

    TObject

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

    TCoraponent

    Применяется для создания невизуальных компонентов

    TGraphicControl

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

    TWidgetControl

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

    TCustomControl

    Данный класс является потомком TWinControl и дополняет его областью вывода (канвой). В этот класс добавлен метод Paint. Рекомендуется использовать такой класс для создания пользовательских оконных компонентов



    Библиотека визуальных компонентов содержит несколько

    Таблица 19.1 (окончание)

    Класс

    Возможности класса

    TCustomClassName

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

    TComponentName

    Позволяет создавать компоненты-потомки, предками которых являются обычные компоненты или классы CLX Kylix. Таким образом, если перед разработчиком стоит задача расширить возможности какого-либо компонента 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 в шестибайтовый.

    О вышеперечисленных типах можно еще сказать следующее:

  • тип Real 48 добавлен в язык для обратной совместимости со старыми версиями программ. Так как такой формат данных не является "родным" для процессоров семейства Intel, использование типа Real 48 замедляет скорость выполнения программы;
  • тип Extended предлагает большую точность, чем другие вещественные типы, но является наименее компактным. Будьте осторожны при использовании данного типа, если вы хотите создавать программы сразу для нескольких платформ;
  • тип Comp является "родным" для семейства процессоров Intel и представляет собой 64-разрядное целое число. Данный тип не относится к целым типам, т. к. не является порядковым и при присваивании переменной данного типа вещественного числа происходит его округление до ближайшего целого. Кроме того, данный тип не поддерживает некоторые операции, допустимые над целыми порядковыми числами (Inc(x), Dec(x) и др.). Этот тип используется лишь для обратной совместимости. Для лучшего быстродействия воспользуйтесь типом Int64;
  • тип Currency является типом с фиксированной запятой, которая применяется для уменьшения ошибок при вычислениях, связанных с денежными суммами. Данный тип представляет собой 64-разрядное целое число с четырьмя знаками после запятой.
  • Над вещественными числами допускается осуществлять следующие операции:

  • Round (х) — округление числа х;
  • Trunc (х) — отбрасывание дробной части числа х.
  • Логические типы данных

    Для хранения логических значений Object Pascal использует тип данных Boolean. Переменная логического типа занимает один байт памяти и может принимать два значения: 1 или 0. Значение 1 соответствует значению True (истина). Значение 0 соответствует значению False (ложь). Из-за того, что данный тип не совместим с подобными логическими типами, применяемыми в других языках программирования, Object Pascal имеет три дополнительных логических типа:

  • ByteBool — порядковое численное значение от 0 до 255, где 0 соответствует значению False, а все остальные числа — значению True. Данный тип занимает 1 байт памяти;
  • WordBool — порядковое числовое значение от 0 до 65 535, где 0 соответствует значению False, а все остальные числа — значению True. Данный тип занимает 2 байта памяти;
  • LongBool — порядковое числовое значение от 0 до 4 294 967 295, где 0 соответствует значению False, а все остальные числа — значению True. Данный тип занимает 4 байта памяти.
  • Операции над этими типами могут привести к разным значениям. В табл. 2.3 вы найдете отличия в результатах операций над различными логическими типами.



    Основным символьным типом является С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 имеет еще два символьных типа:

  • AnsiChar является полным аналогом типа Сhar. Занимает 1 байт памяти;
  • WideChar — тип, который используется для хранения символов в кодировке Unicode. Данная кодировка ограничена не 256-ю а 65 535-ю символами. Занимает 2 байта памяти.
  • Над символьными типами данных допустимы следующие операции:

  • Chr (x) — возвращает символ с кодом, который соответствует целочисленному значению х;
  • UрСаsе(с) — возвращает символ с, преобразованный в верхний регистр (то есть преобразует прописные буквы в заглавные).
  • Назад Вперед

    Отличия результатов операций над логическими типами

    Таблица 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-серверов и интерфейсов

    Кроме того, наиболее часто применяется тип данных String. Свойства данного типа зависят от директивы компилятора {$H}: если она включена {$H+}, то данный тип эквивалентен типу AnsiString. Если же она выключена {$H-}, то тип String будет равносилен типу ShortString. По умолчанию данная директива выключена.

    Строки, по своему определению, являются массивами символов. Поэтому для обращения к любому символу строки достаточно указать название строковой переменной и номер символа (как при обращении к элементу массива):

    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

    Рассмотрим теперь пакеты разработки, которые поставляются вместе с Kylix (табл. 20.3). Напомним, что данные пакеты используются IDE Kylix для установки компонентов в палитру компонентов, задания свойств компонентов и многого другого.



    Основные 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

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

    В дополнение ко всем рассмотренным выше пакетам вы можете устанавливать в 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

    Рассмотрим более подробно директиву {$WEAKPACKAGEUNIT}.

    Слабый пакет применяется, когда пакет ссылается на отсутствующие библиотеки 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

    В VisualCLX Widgets используется вместо оконных компонентов VCL. В CLX TWidgetControl используется как TWinControl в VCL. Другие компоненты (такие как TScrollingWidget) имеют соответствующие имена. Вам не нужно самостоятельно изменять TWinControl на TWidgetControl. В файле ресурсов OControls.pas имеются объявления типов, такие как:

    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 эквивалентом файлов dll Windows являются файлы библиотек разделяемых объектов so, которые содержат независимый от расположения код (position-independent code, PIC). Это приводит к следующему:

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

    В 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
    В Kylix имеются два модуля, эквивалентов для которых нет в Delphi. Это модули:

  • DirSel — отвечает за выбор каталога;
  • QStyle — отвечает за графический интерфейс пользователя.
  • Табл. 21.4 содержит список модулей, которые не поддерживаются средой Kylix, т. к. содержат объекты, специфичные для среды Windows.


    Совместимые модули Delphi и Kylix

    Таблица 21.3. Совместимые модули Delphi и Kylix

    Модуль Delphi
    Модуль Kylix
    ActnListQactnList
    ButtonsQbuttons
    CheckLstQcheckLst
    ClassesClasses
    ClipbrdQclipbrd
    ComCtrlsQcomCtrls
    ConstsConsts, QConsts и RTLConsts
    ContnrsContnrs
    ControlsQcontrols
    ConvUtilsConvUtils
    DateUtilsDateUtils
    DBDB
    DBActnsQDBActns
    DBClientDBClient
    DBCommonDBCommon
    DBConnAdminDBConnAdmin
    DBConstsDBConsts
    DBCtrlsQDBCtrls
    DBGridsQDBGrids
    DBLocalDBLocal
    DBLocalSDBLocalS
    DBLogDlgDBLogDlg
    DBXpressDBXpress
    DialogsQdialpgs
    DSIntfDSIntf
    ExtCtrlsQExtCtrls
    FMTBCDFMTBCD
    FormsQForms
    CraphicisQGraphics


    Модули 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 не имеет специального символа, обозначающего конец текстового файла. Текстовые данные завершаются в конце файла



    в 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 (TSQLTable, TSQLQuery, TSQLStoredProc и 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. Установите свойства нового набора данных в соответствии с оригинальным набором данных:

  • если оригинальным набором данных был компонент TTable,TADOTable или TIBTable, задайте свойствоTableName компонента TSQLTable таким же, как и свойство TableName оригинального набора данных. Также скопируйте значения всех свойств, используемых для установки типа связи и определения индексов. Свойства, устанавливающие границы и фильтры, должны быть установлены в клиентском наборе данных, а не в компоненте TSQLTable;
  • если оригинальным набором данных был компонент TQuery, TADOQuery или TIBQuery, установите свойство SQL компонента TSQLQuery равным значению свойства SQL оригинального набора данных. Задайте свойство Params компонента TSQLQuery в соответствии со значением свойства Params или Parameters оригинального набора данных. Если вы используете свойство DataSource для установки связей, скопируйте его значение тоже;
  • если оригинальным набором данных был компонент TstoredProc, TADOStoredProc или TIBStoredProc, установите свойство StoredProcName компонента TSQLStoredProc равным значению свой-
    ствa StoredProcName или ProcedureName оригинального набора данных, а свойство Params компонента TSQLStoredProc равным значению свойства Params или Parameters оригинального набора данных.
  • 6. Для всех компонентов, предназначенных для соединения с базой данных в oригинальном приложении (TDatabase, TIBDatabase или TADOConnection), добавьте компонент TSQLConnection в новый модуль данных. Нужно также добавить компонент TSQLConnection для каждого сервера баз данных, с которым будет осуществляться соединение без использования компонента соединения с базой данных (например, использующих свойство ConnectionString в наборе данных ADO или свойство DatabaseName
    в наборе данных BDE).

    7. Для каждого набора данных dbExpress, которые созданы в четвертом шаге, установите их свойства SQLConnection в значение компонентов TSQLConnection, соответствующих нужной базе данных.

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

    Обновление данных в приложениях dbExpress

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

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


    Арифметические операции над двумя операндами

    Таблица 3.1. Арифметические операции над двумя операндами

    Знак операции
    Операция
    Типы операндов
    Тип результата
    Пример
    +СложениеInteger, realInteger, realX+Y
    -ВычитаниеInteger, realInteger, realX-Y
    *УмножениеInteger, realInteger, realX*Y
    /ДелениеInteger, realRealX/10
    divЦелочисленное делениеIntegerIntegerX div Y
    modЦелочисленный остаток от деленияIntegerIntegerX mod Y
    Стоит сказать несколько слов по поводу операций div и mod. Результатом целочисленного деления X div Y будет результат деления X/Y, округленный в сторону нуля до ближайшего целого числа.

    Результатом операции mod будет остаток от целочисленного деления операндов. Таким образом, выражение X mod Y эквивалентно выражению X - (X div Y) *Y. Например, результатом выражения 4 div 2 будет 0, а результатом выражения 9 div 4 будет 1.

    В табл. 3.2 приведены операции, осуществляемые над одним операндом.



    Арифметические операции над одним операндом

    Таблица 3.2. Арифметические операции над одним операндом

    Знак операции
    Операция
    Тип операнда
    Тип результата
    Пример
    +Сохранение знака числаInteger, realInteger, real+7
    -Отрицание знака числаInteger, realInteger, real-X
    Приведем примеры использования арифметических операций с одним и двумя операндами (листинг 3.1).

    Поразрядные арифметические операции

    Таблица 3.3. Поразрядные арифметические операции

    Знак операции
    Операция
    Типы операндов
    Тип результата
    Пример
    notПоразрядное отрицаниеIntegerIntegernot X
    andПоразрядное умножениеIntegerIntegerX and Y
    orПоразрядное сложениеIntegerIntegerX or Y
    xorПоразрядное исключающее ИЛИIntegerIntegerX xor Y
    shlПоразрядный сдвиг числа влевоIntegerIntegerX shl 2
    shrПоразрядный сдвиг числа вправоIntegerIntegerX shr 1
    В табл. 3.4 показаны результаты выполнения поразрядных арифметических операций.



    Приведем примеры использования побитовых арифметических

    Таблица 3.4 (окончание)

    Знак операцииОперация Бит1Бит 2Результирующий бит
    100
    111
    orПоразрядное сложение000
    011
    101
    111
    хоr Поразрядное исключающее ИЛИ000
    011
    101
    110
    Приведем примеры использования побитовых арифметических операций (листинг 3.2).

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

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

    Знак операции
    Операция
    Бит1
    Бит 2
    Результирующий бит
    notПоразрядное отрицание01
    10
    andПоразрядное умножение000
    010


    Логические операции языка Object Pascal

    Таблица 3.5. Логические операции языка Object Pascal

    Знак операцииОперацияТипы операндовТип результатаПример
    notОтрицаниеBooleanBooleannot (С in MySet)


    Как видно из примеров табл.

    Таблица 3.5 (окончание)

    Знак операции
    Операция
    Типы операндов
    Тип результата
    Пример
    and
    Конъюнкция (логическое И)
    Boolean
    Boolean
    A and В
    or
    Дизъюнкция (логическое ИЛИ)
    Boolean
    Boolean
    A or В
    xor
    Исключающая дизъюнкция (исключающее ИЛИ)
    Boolean
    Boolean
    A xor В
    Как видно из примеров табл. 3.5, логические операции and, or и xor являются операциями над двумя операндами, а операции not — над одним операндом. В следующей таблице (табл. 3.6) приведены результаты выполнения логических операций.


    Результаты выполнения логических операций

    Таблица 3.6. Результаты выполнения логических операций

    Знак операции
    Операция
    Операнд 1
    Операнд 2
    Результат
    notОтрицаниеFalseTrue
    TrueFalse
    andКонъюнкция (логическое И)FalseFalseFalse
    FalseTrueFalse
    TrueFalseFalse
    TrueTrueTrue
    orДизъюнкция (логическое ИЛИ)FalseFalseFalse
    FalseTrueTrue
    TrueFalseTrue
    TrueTrueTrue
    xorИсключающая дизъюнкция (исключающее ИЛИ)FalseFalseFalse
    FalseTrueTrue
    TrueFalseTrue
    TrueTrueFalse
    Для установки отношений между двумя значениями вы можете использовать операции отношения или сравнения. В языке Object Pascal имеется шесть операций отношения:

  • = — равенство;
  • < — меньше;
  • > — больше;
  • <= — меньше или равно;
  • >= — больше или равно;
  • <> — не равно.
  • Если операция отношения истинна, то результатом ее выполнения является значение True, например истинным является выражение 4 < 10; в противном случае — результат False, например 12 <> 12.

    Рассмотрим теперь такой немаловажный вопрос: в каком порядке выполняются те или иные операции? Если в сложном выражении записаны несколько операций подряд, то последовательность их выполнения определяется старшинством. Для того чтобы был четкий порядок выполнения операции, в языке Object Pascal существует такое понятие, как приоритет.

    Приоритет определяет старшинство операций и служит для установления порядка выполнения операций. Операции с более высоким уровнем приоритета выполняются раньше остальных.

    По приоритету все операции делятся на четыре уровня:

  • первый (наивысший) уровень приоритета. К нему относятся операции @
    и not;
  • второй уровень приоритета — операции *, /, div, mod, and, shl, shr и as;
  • третий уровень приоритета — операции +, -, or и хоr;
  • четвертый (самый низкий) уровень приоритета — операции =, <>, <, >, <=, >=, in и is.
  • Если подряд идут несколько операций с одинаковым приоритетом, то операции выполняются слева направо.

    Строковые выражения

    Строковые выражения содержат строковые операции и функции. Для строк в Object Pascal определена одна операция — операция объединения строк (конкатенации строк). Знаком операции конкатенации является +. Операндами для этой операции могут быть строки, упакованные строки, а также символы. В то же время, если один из операндов имеет тип WideChar, другой операнд должен быть длинной строкой. Результат операции объединения строк — строка символов. Этот результат совместим со всеми строковыми типами языка. В то же время, если количество символов после операции объединения строк превысит 255, то результатом станут первые 255 символов, а оставшиеся будут просто отброшены.

    Для строк определены также следующие функции:

  • Concat (s1, s2, ..., sn) — возвращает строку, представляющую собой объединение строк s1 ... sn;
  • Copy(S; Index, Count) — возвращает строковое значение, являющееся подстрокой строки S, начиная с символа под номером Index, и длиной Count;
  • Length (s) — возвращает целое число, равное количеству символов в строке s;
  • Pos(Substr; s) — возвращает целое число, определяющее позицию первого символа, начиная с которого подстрока Substr входит в строку s. Если такой подстроки в строке нет, то результатом будет 0;
  • Trim(s) — возвращает строку, полученную в результате отбрасывания от строки s пробелов и управляющих символов в начале и конце строки;
  • TrimLeft(s) — возвращает строку, полученную в результате отбрасывания от строки s пробелов и управляющих символов в начале строки;
  • TrimRight(s) — возвращает строку, полученную в результате отбрасывания от строки s пробелов и управляющих символов в конце строки.
  • Кроме перечисленных выше функций существует несколько дополнительных функций для преобразования одних типов данных в другие:

  • DateToStr (Date) — возвращает строку, полученную в результате преобразования значения даты Date в строку;
  • FioatToStr (value) — возвращает строку, полученную в результате преобразования вещественного числа value в строку;
  • IntToStr (value) — возвращает строку, полученную в результате преобразования целого числа value в строку;
  • LowerCase (s) — возвращает строку, полученную в результате преобразования строки s в строку символов нижнего регистра (прописные буквы);
  • StrToDate(s) — возвращает значение типа "дата", полученное в результате преобразования строки s в значение даты;
  • StrToDateTime(s) — возвращает значение типа "дата и время", полученное в результате преобразования строки s в значение даты и времени;
  • StrToFloat (s) — возвращает значение вещественного типа, полученное в результате преобразования строки s в вещественное число;
  • StrToInt(s) — возвращает целочисленное значение, полученное в результате преобразования строки s в целое число;
  • StrToTime (s) — возвращает значение типа "время", полученное в результате преобразования строки s в значение времени;
  • TimeToStr (time) — возвращает строку, полученную в результате преобразования значения времени time в строку;
  • UpperCase (s) — возвращает строку, полученную в результате преобразования строки s в строку символов верхнего регистра (заглавные буквы);
  • Приведем примеры строковых выражений:
  • S:='Мама'; // Результат в переменной S - слово Мама
  • S:=s + ' мыла'; // Результат - Мама мыла
  • S:=s + Uppercase(' раму'); // Результат - Мама мыла РАМУ
  • Результаты выполнения логических операций Результаты выполнения логических операций Результаты выполнения логических операций

    Методы для работы с RTTI

    Таблица 5.1. Методы для работы с RTTI

    Название метода

    Тип возвращаемого результата

    Результат

    Classlnfo

    Pointer

    Указатель на информацию о типе объекта

    ClassName

    String

    Имя класса объекта

    ClassParent

    Tclass

    Тип класса-предка объекта

    ClassType

    Tclass

    Тип объекта

    InheritsFrom

    Boolean

    Является ли объект потомком данного класса

    InstanceSize

    Word

    Размер объекта как экземпляра класса в байтах

    Для работы с информацией о типе времени исполнения в Kylix имеется два основных оператора: is и as.

    Синтаксис использования оператора 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
    Есть
    Есть
    Далее мы будем ориентироваться на описание наиболее полной версии Kylix Server Developer.

    Если вы знакомы со средой программирования Borland Delphi, то переход к программированию в Kylix будет достаточно легким, т. к. многое в Kylix напоминает Delphi.

    Интегрированная среда Kylix является достаточно удобным средством эффективной и быстрой разработки приложений в Linux. Среда Kylix вобрала в себя много хорошего от своего предшественника — Delphi.

    Интегрированная среда разработки Kylix состоит из четырех основных окон, которые отображаются при запуске среды:

  • главного окна (Main Window);
  • конструктора форм (Form Designer);
  • инспектора объектов (Object Inspector);
  • редактора кода (Code Editor).
  • Главное окно является основной частью интегрированной среды разработки (Рисунок 6.1). Оно, в свою очередь, состоит из трех частей:

  • меню
  • панели инструментов;
  • палитры компонентов.
  • Средство ведения списка задач, подлежащих

    Возможности 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
    Список действий
    Позволяет вашему приложению централизованно реагировать на какие-либо действия пользователя. Например, копирование данных из поля для ввода
    Следующая вкладка палитры компонентов Kylix называется Additional (Рисунок 8.2).

    Создает так называемый контейнер, который

    Служит для создания главного меню

    Таблица 8.1 (продолжение)

    Название на английском языке
    Название на русском языке
    Краткое описание компонента
    MainMenu
    Главное меню
    Служит для создания главного меню вашего приложения. Расположите этот компонент на форме и после двойного щелчка на нем добавьте новые пункты вашего меню
    PopupMenu
    Всплывающее меню
    Служит для создания так называемого всплывающего меню — меню, которое отображается после щелчка правой кнопкой мыши в определенной области приложения
    Label
    Метка
    Служит для простого отображения текстовой информации, которую пользователь не может редактировать во время работы приложения
    Edit
    Поле для ввода
    Служит для отображения текстовой информации, которую пользователь может изменять. Удобно применять для ввода или редактирования какой-либо текстовой информации
    Memo
    Многострочное поле
    Работает как и поле для ввода, только позволяет вводить (редактировать) несколько строк текста
    Button
    Кнопка
    Обычная кнопка предназначена для выполнения какого-либо кода по нажатии на кнопку пользователем
    CheckBox
    Флажок
    Представляет опцию, благодаря которой пользователь может изменять положение переключателя вкл./выкл.
    RadioButton
    Переключатель
    Данный переключатель работает обычно в группе с другими. Если на форме располагается несколько таких переключателей, только один из них может принимать включенное положение
    ListBox
    Список
    Предназначен для вывода нескольких строк текста. Пользователь может выбрать любую из этих строк простым нажатием на ней
    ComboBox
    Выпадающий список
    Является как бы комбинацией списка и поля для ввода. Пользователь может ввести самостоятельно текст в поле либо выбрать нужный из предоставленного списка
    ScrollBar
    Полоса прокрутки
    Предназначена для смены видимой области отображения формы. Нужна для просмотра большого количества информации, которая просто не помещается на экран


    Компоненты вкладки Indy Servers

    Таблица 8.10. Компоненты вкладки Indy Servers

    Название
    Название на русском языке
    Краткое описание компонента
    IdTCPServerTCP-серверИнкапсулирует полную функциональность TCP-сервера, включая поддержку сокетов, и может быть использован для создания заказных программных средств
    IdUDPServerUDP-серверИнкапсулирует полную функциональность UDP-сервера и может быть использован для создания заказных программных средств
    IdChargenServerChargen-серверОбеспечивает создание Chargen-сервера
    IdDayTimeServerСервер даты/времениОбеспечивает поддержку протокола даты/времени (RFC 876) как сервер
    IdDictServerDictionary-серверОбеспечивает поддержку протокола Dictionary Server, DICT (RFC 2229)
    IdDiscardServerDiscard-серверОбеспечивает поддержку протокола Discard (RFC 863) как сервер


    позволяющий получить доступ клиентов через

    Таблица 8.10 (окончание)

    Название
    Название на русском языке
    Краткое описание компонента
    IdTunneIMaster
    TCP-сервер с поддержкой IP-туннелей
    Позволяет создавать серверы, поддерживающие IP-туннели
    IdTunnelSlave
    Сервер доступа к туннельным соединениям
    Сервер, позволяющий получить доступ клиентов через туннельное соединение
    IdWhoIsServer
    Whois-сервер
    Поддерживает протокол Nickname или Whois (RFC 954) как сервер
    И наконец, последняя вкладка палитры компонентов Kylix, которая называется Indy Misc (Рисунок 8.11).

    позволяющий получить доступ клиентов через

    Обеспечивает поддержку протокола 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
    На этом пока закончим обзор компонентов, входящих в среду Kylix. Добавим только, что все эти компоненты поставляются с Kylix Server Developer. Применение данных компонентов будет рассмотрено далее на примерах.

    На этом пока закончим обзор На этом пока закончим обзор

    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

    Рассмотрим свойства, которые имеют стандартные компоненты Kylix. Для начала — основные свойства, которые присущи компонентам — наследникам класса TControl. Кроме краткого описания свойства, мы будем приводить строку кода, описывающего данное свойство внутри класса TControl.
    Это поможет вам понять, какой тип имеет данное свойство.

  • Свойство Action предназначено для определения действия, связанного с элементом управления (меню, кнопкой и т. д). Оно описывается в классе TControl следующим образом:
    property Action: TBasicAction;
  • Значение этого свойства устанавливается во время разработки приложения путем выбора из выпадающего списка предусмотренных действий. Данный список формируется путем размещения на форме компонента TActionList и задания его свойств.
  • Свойство ActionLink устанавливает связь между элементом управления и действием, определенным в свойстве Action. Оно описывается следующим образом:
    property ActionLink: TControlActionLink;
  • Свойство Align предназначено для задания способа выравнивания компонента внутри компонента контейнерного типа. Оно описывается так:
    property Align: TAlign;
  • Перечислим возможные значения данного свойства:

    • alNone — компонент остается на том месте, где он был размещен во время разработки приложения. Данное значение присваивается свойству Align по умолчанию;

    • alTop — компонент занимает всю верхнюю часть компонента-контейнера. Во время выполнения приложения ширина компонента зависит от ширины компонента-контейнера. Высота компонента остается неизменной, независимо от высоты контейнера;

    • alBottom - аналогичен alTop, за исключением того, что компонент занимает всю нижнюю часть компонента-контейнера;

    • alLeft — компонент занимает всю левую часть компонента-контейнера. Во время выполнения приложения высота компонента зависит от высоты компонента-контейнера. При изменении ширины компонента-контейнера ширина компонента остается неизменной;

    • alRight — аналогичен alLeft, за исключением того, что компонент занимает всю правую часть компонента-контейнера;

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

    Примечание

    Значения alTop и alBottom имеют больший приоритет по сравнению со значениями alLeft и alRight. Таким образом, если вы вывели на форму два компонента, присвоив свойству Align одного из них значение alTop, а другому — alRight, то первый компонент вытеснит верхнюю часть второго компонента (Рисунок 8.12).
  • Свойство Anchors предназначено для определения привязки компонента к родительскому компоненту при изменении размеров родительского компонента. Оно определяется следующим образом:
    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-эффектах для активных компонентов
    Данные константы цвета, начиная с clBackground, определяются той цветовой схемой Х-Windows, которая установлена пользователей на конкретном компьютере. Эти цвета рекомендуется использовать при разработке приложений для передачи третьим лицам.

  • Свойство Components хранит в себе массив компонентов, владельцем которых является данный компонент. Параметр свойств Index позволяет выбрать любой компонент из массива, благодаря свойству Component Index (см. далее). Индексы компонентов нумеруются, начиная с нуля. Число компонентов, содержащихся в массиве, можно определить с помощью свойства ComponentCount (см. далее).
  • Свойство ComponentIndex определяет индекс (порядковый номер) компонента, содержащегося в компоненте-контейнере, а свойство ComponentCount — число компонентов, входящих в данный компонент контейнерного типа.
  • Рассмотрим пример применения данных свойств.Предположим, что на форме имеется несколько компонентов. Задача — сместить все компоненты, которые присутствуют на форме, кроме компонента Button1, вправо на 10 единиц. Для этого можно использовать следующий код:

    for i := 0 to ComponentCount - 1 do
    if (Components[ i ].Name <> 'Button1') then
    (Components[ i ] as TControl).Left: = (Components[ i ] as TControl).Left + 10;

  • Свойство Constraints определяет размер ограничений, т. е. максимальную и минимальную величины ширины и длины компонента. Оно описывается следующим образом:
    property Constraints: TSizeConstraints;Примечание
    He устанавливайте данное свойство, если вы используете свойства Align или Anchors, т. к. это может привести к конфликту свойств и неправильной работе приложения.

  • Свойство Control State предназначено для определения текущего состояния компонента во время выполнения приложения. Данное свойство описано следующим образом:
    property ControlState: TControlState;
  • Значение свойства ControlState состоит из набора флагов, обозначения которых приведены в табл. 8.14.


    Цвет фона для активных текстовых

    Таблица 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 в процессе перерисовки
  • Свойство ControlStyle определяет различные атрибуты компонента. Например, может ли компонент быть захвачен мышью, имеет ли компонент фиксированные размеры и др. Данное свойство определяет не экземпляры класса, а класс в целом. Оно описано следующим образом:
    property ControlStyle: TControlStyle;
  • Значение данного свойства также состоит из флагов (табл. 8.15).


    Флаги значения свойства 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
    Элемент управления реагирует на команды системного меню
  • Свойство Cursor определяет вид указателя мыши, когда он находится над данным компонентом. Оно описывается следующим образом:
    property Cursor:TCursor;
  • В свою очередь, тип TCursor описан так:
    type TCursor = -32768 .. 32768;

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


    Указатели мыши

    Таблица 8.16. Указатели мыши

    Значение свойства
    Cursor
    Числовое значение
    Изображение указателя мыши
    CrDefault0Указатель, принятый по умолчанию. Обычно
    это с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Указатель в форме руки
  • Свойство DragMode определяет поведение компонента в процессе его перетаскивания. Свойство описывается следующим образом:
    property DragMode: TDragMode;
    Данное свойство может принимать одно из двух значений: dmAutomatic или dmManual. В первом случае от разработчика не требуется обработки событий. Достаточно щелкнуть кнопкой мыши на компоненте и начать его перетаскивание. Во втором случае компонент не может начать процесс перетаскивания, пока приложение не вызовет метод BeginDrag.
  • Свойство DragObject содержит значение, определяющее объект перетаскивания, ассоциированный с элементом управления. Данное свойство описано так:
    property DragObject: TDragObject;
    Оно предназначено только для чтения и используется в основном при создании собственных компонентов.
  • Свойство Enabled показывает, будет ли компонент доступен пользователю во время работы приложения. Это свойство описывается следующим образом:
    property Enabled: Boolean;
    Недоступный компонент (Enabled = false) отображается серым цветом. Он игнорирует события клавиатуры, мыши и таймера. Данное свойство применяется для временного ограничения доступа пользователя к компонентам. Например, если вы хотите сделать временно недоступной кнопку, нужно в свойстве Enabled кнопки установить значение false:
    Button1.Enabled := false;
  • Свойство Font предназначено для установки шрифта, а также всех его атрибутов (размера, стиля, цвета и т. д.). Описано так:
    property Font: TFont;
  • Свойство Height применяется для задания высоты компонента. Описывается это свойство так:
    property Height: Integer;
  • Свойство HelpContext определяет номер, используемый в контекстно-зависимой справке. То есть задается номер страницы справки, которая будет отображаться на экране, когда пользователь нажмет клавишу . Данное свойство описано следующим образом:
    property HelpContext: THelpContext;
  • Свойство HelpFile описано следующим образом:
    property HelpFile: String;
    Данное свойство содержит имя файла, который будет использоваться приложением в качестве файла контекстно-зависимой справки.
  • Свойство HelpKeywordпредназначено для осуществления поиска в файле контекстно-зависимой справки по ключевому слову. Данное свойство описано следующим образом:
    property HelpKeyword: String;
  • Свойство Hint применяется для задания текста всплывающей подсказки. Это свойство описано так:
    property Hint: String;
    Данное свойство обычно состоит из двух частей, разделяемых символом " |". Например,
    Button1.Hint := "Открыть|Выбор и открытие файла рисунка";
    В данном случае при наведении указателя мыши на кнопку Button1 будет выдана всплывающая подсказка "Открыть", вторая часть подсказки будет выведена в специальную область, отведенную для таких подсказок, например на панель состояния. Разработчик может пользоваться только первой частью подсказки, без использования символа "|". Кроме того, для отображения всплывающих подсказок нужно дополнительно установить свойство ShowHint в true (см. далее).
  • Свойство Left применяется для задания координаты левого края компонента. За начало координат всех компонентов берется левый верхний угол клиентской области родительского компонента. Для форм началом координат является левый верхний угол экрана.
    Данное свойство описано следующим образом:
    property Left: Integer;
  • Свойство MouseCapture используется для определения факта захвата мышью элемента управления. Данное свойство имеет логический тип и описано следующим образом:
    property MouseCapture: Boolean;
    Если элемент управления захвачен мышью — возвращается True, иначе —False.
  • Свойство Name определяет имя компонента, по которому на него ссылаются другие компоненты и которое в дальнейшем используется разработчиком. Данное свойство описано так:
    property Name: TComponentName;
    Имя задается в процессе разработки программы и не должно изменяться во время работы программы. Kylix по умолчанию самостоятельно дает имена новым компонентам, например: Button1, Button2, Label1 и т. п. Рекомендуется изменять эти имена на более осмысленные.
  • Свойство Parent определяет родительский компонент контейнерного типа, в пределах которого располагается данный компонент. Это свойство описано следующим образом:
    property Parent: TWidgetControl;Примечание
    Важно различать два похожих свойства. Свойство Parent определяет родительский компонент, т. е. тот компонент, на котором располагается данный компонент. Свойство Owner определяет владельца компонента. Владелец — это компонент, который передается в качестве параметра в конструктор данного компонента и который владеет им. Например, форма является владельцем всех расположенных на ней компонентов и одновременно — родителем.
  • Свойство ParentColor указывает, будет ли данный компонент иметь такой же цвет, как и его предок. Свойство описано так:
    property ParentColor: Boolean;
  • Ecли вы хотите, чтобы компонент унаследовал значения цвета от своего предка, то установите данное свойство в true. Если это свойство будет иметь значение False, компонент будет использовать цвета, заданные в его собственных свойствах.
  • Свойство ParentFont предназначено для определения, будет ли для данного компонента использоваться шрифт, применяемый в родительском компоненте контейнерного типа. Например, если на форме находится кнопка, то при установке у данной кнопки свойства ParentFont в true приведет к тому, что надпись на кнопке будет выполнена тем шрифтом, который указан в свойстве Font формы. Данное свойство описано так:
    property ParentFont: Boolean;
  • Свойство ParentShowHint предназначено для включения и выключения родительского свойства ShowHint. Оно описано следующим образом:
    property ParentShowHint: Boolean;
    Данное свойство используется для одновременного разрешения или запрещения показа всплывающих подсказок в пределах некоторой формы или компонента контейнерного типа.
  • Свойство РорupMenu служит для сопоставления с данным компонентом всплывающего по щелчку правой кнопки мыши меню. Данное свойство описано так:
    property PopupMenu: TPopupMenu;
  • Свойство ScalingFlags служит для определения, какие атрибуты элемента управления могут изменять размеры (масштабироваться). Данное свойство описано следующим образом:
    property ScalingFlags: TScalingFlags;
  • Тип TScalingFlags представляет собой набор флагов, которые описаны в табл. 8.17.


    Флаги TScalingFlagФлаг

    Таблица 8.17. Флаги TScalingFlag
    Флаг

    Значение
    sfLeftЛевая сторона элемента управления не может масштабироваться
    sfTopВерх элемента управления не может масштабироваться
    sf WidthШирина элемента управления не может масштабироваться
    sfHeightВысота элемента управления не может масштабироваться
    sfFontШрифт элемента управления не может масштабироваться
  • Свойство ShowHint применяется для включения или выключения показа всплывающих подсказок при задержке указателя мыши над компонентом. Текст подсказки задается в свойстве Hint. Свойство ShowHint описано следующим образом:
    property ShowHint: Boolean;
  • Свойство Text предназначено для задания или чтения строки текста, связанной с данным компонентом. Данное свойство описано так:
    property Text: TCaption;
    Это свойство применяется в компонентах типа TEdit и в компонентах-списках.
  • Свойство Tор применяется для задания или чтения значения, определяющего координату верхнего края компонента. Данное свойство описано следующим образом:
    property Top: Integer;
  • Свойство Visible применяется для определения, будет ли виден компонент на форме во время выполнения программы. Оно описано так:
    property Visible: Boolean;
  • Если свойство имеет значение true, то компонент будет виден, иначе — невидим.
  • Свойство Width применяется для установки горизонтального размера компонента, а также для чтения текущего значения ширины компонента. Данное свойство имеет целый тип и описано следующим образом:
    property Width: Integer;
  • Рассмотрим теперь свойства, характерные для класса TWidgetControl и его наследников.
  • Свойство Bitmap служит для задания растрового изображения, которое отображается как фоновый рисунок элемента управления. Данное свойство в классе TWidgetControl описано следующим образом:
    property Bitmap: TBitmap;
  • Свойство Brush предназначено для установки цвета и кисти для закраски фонового изображения элемента управления. Данное свойство описано так:
    property Brush: TBrush;
  • Свойство ChlidHandle возвращает ссылку на элемент управления. Данная ссылка является дескриптором дочернего окна, который применяется, когда происходит вызов родительского окна. Свойство используется только для чтения и описано следующим образом:
    property ChildHandle: QwidgetH; library;
  • Свойство ControlCount возвращает число дочерних элементов управления от данного. Оно описано так:
    property ControlCount: Integer;
    Это свойство применяется только для чтения. Значение, хранящееся в данном свойстве, всегда на единицу больше, чем самый последний индекс дочернего элемента (см. свойство Controls ниже), т. к. первый индекс всегда равен нулю.
  • Свойство Controls представляет собой массив, содержащий список всех дочерних элементов управления по отношению к данному элементу. Это свойство описывается следующим образом:
    property Controls[Index: Integer]: TControl;Примечаниe
    He путайте свойство Controls со свойством Components. Свойство Controls содержит список всех дочерних окон от данного, а свойство Components — список всех компонентов, владельцем которых этот компонент является.
  • Данное свойство применяется только для чтения. Для добавления или удаления дочерних элементов управления используйте соответствующие методы InsertControl и Remove Control.

  • Свойство Handle обеспечивает доступ к дескриптору окна элемента управления. Описано следующим образом:
    property Handle: QWidgetH read GetHandle; library;
    Данное свойство применяется только для чтения
  • Свойство InputKeys определяет тип клавиш, которые могут применяться для ввода информации внутри данного элемента управления при получении им фокуса. Свойство описано следующим образом;
    property InputKeys: TInputKeys;
  • Стоит сказать несколько слов о типе TInputKeys. Этот тип представляет собой перечисляемый тип, значения которого показаны в табл. 8.18.

    Таблицa 8.18. Значения типа TInputKeys

    Значение
    Описание
    ikAllВвод любых символов клавиатуры
    ikArrowsКлавиши со стрелками (<влево>, <вправо>, <вверх>, <вниз>)
    ikCharsЛюбые нефункциональные клавиши без и
    ikReturnsКлавиша ввода ()
    ikTabsКлавиша табуляции (<Таb>) и комбинация клавиш обратной табуляции (+)
    ikEditКлавиши редактирования (, , )
    ikNavКлавиши навигации по тексту (<вверх>, <вниз>, <влево>, <вправо>, , , , )
    ikEscКлавиша
  • Свойство Masked включает или выключает свойство Automask для отображения непрямоугольных окон. Описано следующим образом:
    property Masked: Boolean;
    Принимает значение True, если окно имеет непрямоугольную форму.
  • Свойство Palette хранит значение текущей палитры, которая используется для рисования данного элемента управления. Описано следующим образом:
    property Palette: TWidgetPalette;
  • Свойство ParentWidget служит для ссылки на родительский элемент управления, т.е. на дескриптор окна родителя данного элемента управления. Описано следующим образом:
    property ParentWidget: QWidgetH;
  • Свойство Style предназначено для задания стиля компонента. Описано так:
    property Style: TWidgetStyle;
  • Свойство TabOrder применяется для задания последовательности перехода от одного компонента формы к другому при помощи клавиши <Таb>. Свойство описано следующим образом:
    property TabOrder: TTabOrder;
    Нумерация осуществляется, начиная с нуля. Если задать свойству TabOrder компонента значение -1, этот компонент не сможет получить фокус при помощи клавиши <Таb>. Предположим, что на форме расположены три кнопки: Button1, Button2 и Button3. Для того чтобы фокус между этими кнопками передавался следующим образом: сначала активна кнопка Button2, затем — Button1 и потом уже Button3, нужно установить свойство TabOrder для кнопки Button1 равным 1, для Button2 — 0, а для Button3 — 2.
  • Свойство TabStop применяется для указания возможности передачи фокуса на компонент при помощи клавиши <Таb>. Оно описывается следующим образом:
    property TabStop: Boolean;
  • Если значение данного свойства равно true, то при помощи клавиши <Таb> можно передать фокус этому компоненту, в зависимости от его свойства TabOrder. Если значение свойства TabStop равно false, то независимо от свойства TabOrder фокус будет невозможно передать при помощи клавиши <Таb>.
    Методы
    Методы — это процедуры или функции, принадлежащие объекту. Методы определяют поведение объекта. Для вызова метода объекта нужно указать объект, с которым ассоциирован данный метод, затем, через точку, — название метода. Например:

    Button1.Click

    Вызывается метод нажатием (Click) кнопки (Button1).

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

    type TMyComponent = class(TObject)
    . . .
    procedure DoSomething; . . .
    end;
    Здесь, внутри описания нового компонента, мы объявляем метод DoSomething с помощью служебного слова procedure. После того как мы объявили новый метод, необходимо создать тело данного метода. Эта процедура может находиться где угодно внутри модуля, в котором был описан компонент. Например:

    procedure TMyComponent.DoSomething; begin
    // Здесь размещаем команды и операторы, которые должны выполняться
    // при вызове метода DoSomething на выполнение end;
    Заметим, что при создании процедуры DoSomething мы должны указывать его полное имя вместе с указанием имени компонента или класса

    (procedure TMyComponent.DoSomething;).
    Рассмотрим основные методы среды Kylix.

  • Метод Add предназначен для добавления нового элемента в список типа TList, TStringList или TStrings. Если список не отсортирован, то новый элемент добавляется в самый конец списка. Если список отсортирован, новый элемент добавляется в позицию списка, определяемую сортировкой. Вызов настоящего метода увеличивает значение свойства count для этого списка. При выполнении данного метода может возникнуть исключение EListError в случае, когда список отсортирован, добавляемая строка уже присутствует в списке и для данного списка свойство
    Duplicates установлено в dupError.
  • Флаги TScalingFlagФлаг

    Коды клавиш

    Таблица 8.19. Коды клавиш

    Символическое имя клавиши
    Название клавиши
    Символическое имя клавиши
    Название клавиши
    Key_EscapeKey_Period<.>
    Key_ TabKey_ Slash
    Key_ Backtab,
    Key_ BackTab
    +Key_0<0>
    Key_Backspace, Key_BackSpaceKey_1<1>
    Key_ReturnKey_2<2>
    Key_EnterKey_3<3>
    Key_InsertKey_4<4>
    Key_DeleteKey_5<5>
    Key_ PauseKey_6<6>
    Key_PrintKey_7<7>
    Key_SysReqKey_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

    Параметр Shift является множеством, которое может быть пустым или может содержать следующие элементы:

  • ssShift — при нажатой клавише ;
  • ssAlt — при нажатой клавише ;
  • ssCtrl — при нажатой клавише .
  • Приведем пример использования события OnKeyDown. Предположим, что нам необходимо распознать, когда пользователь нажмет комбинацию клавиш ++. В обработчике события OnKeyDown напишем следующий код:

    if ( (Key = ord ('L') ) and (ssShift in Shift) and (ssCtrl in Shift) )
    then ShowMessage ('Нажата комбинация клавиш ++');
    В вышеприведенном примере мы использовали функцию ord ( ), которая позволяет по символу клавиши получить код клавиши (в нашем случае, код клавиши ). Теперь всякий раз, когда фокус будет у компонента, к которому привязан данный обработчик, и как только пользователь нажмет комбинацию клавиш ++, будет выводиться окно (Рисунок 8.21).

    Параметр Shift является множеством, которое

    Символическое имя

    Таблица 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 _CapsLockKey_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Список иконокОтображает список или данные в виде строк и столбцов маленьких или больших иконок
    Следующая вкладка палитры компонентов Kylix — это вкладка Dialogs (Рисунок 8.4).

    Отображает содержимое текстового файла или

    Компоненты вкладки 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

    Таблица 8.6. Компоненты вкладки dbExpress

    Название
    Название на русском языке
    Краткое описание компонента
    SQLConnectionSQL-соединениеКомпонент для обеспечения связи с сервером базы данных dbExpress
    SQLDataSetНабор данных SQLПредставляет собой набор данных, работающий с базами данных dbExpress
    SQLQuerySQL-запросКомпонент, позволяющий создавать и выполнять SQL-запросы для работы с таблицами баз данных dbExpress
    SQLStoredProcХранимая SQL-процедураХранимая на сервере dbExpress процедура, выполняемая с помощью соответствующего вызова
    SQLTableSQL-таблица


    и ClientDataSet, этот компонент сохраняет

    Таблица 8.6 (окончание)

    Название
    Название на русском языке
    Краткое описание компонента
    SQLClientDataSet
    Набор данных SQL-клиента
    Как и ClientDataSet, этот компонент сохраняет в оперативной памяти данные и любые изменения, сделанные приложением в физические таблицы
    Следующая вкладка палитры компонентов Kylix называется Data Controls (Рисунок 8.7).

    и 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), содержит компоненты для создания Web-приложений.

    Содержащий данные компонент, предназначенный для

    Компоненты вкладки 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 в виде таблицы
    TcpClientTCP-клиентДобавляет на форму или модуль данных объект типа TTCPClient для "превращения" приложения в приложение-клиент TCP/IP (Transmission Control Protocol/Internet Protocol). TCP-клиент устанавливает желаемое соединение с TCP/IP-сбрвером, обслуживает текущее соединение и завершает соединение
    TcpServerTCP-серверДобавляет на форму или модуль данных объект типа TTCPServer для "превращения" приложения в приложение-сервер TCP/IP. TCP-сервер ожидает запросы на TCP/IP-соединение от других компьютеров сети, и если такой запрос получен — устанавливает соединение


    Добавляет на форму или модуль

    Таблица 8.8 (окончание)

    Название
    Название на русском языке
    Краткое описание компонента
    UdpSocket
    UDP-сокет
    Добавляет на форму или модуль данных объект типа TUDPSocket для "превращения" приложения в UDP/IP (User Datagram Protocol/ Internet Protocol)-клиент или сервер
    Следующие три вкладки содержат компоненты, созданные компанией Nev-rona. Эти компоненты предназначены для разработки Интернет-приложений и поддержки различных сетевых протоколов, таких как HTTP, FTP, SMTP, UDP, Telnet, POP3.

    Первая из этих трех вкладок носит имя Indy Clients (Рисунок 8.9).

    Добавляет на форму или модуль

    Компоненты вкладки Indy Clients

    Таблица 8.9. Компоненты вкладки Indy Clients

    Название
    Название на русском языке
    Краткое описание компонента
    IdTCPClientTCP-клиентИнкапсулирует полную функциональность TCP-клиента, включая поддержку сокетов, и может быть использован для создания заказных программных средств
    IdUDPClientUDP-клиентИнкапсулирует полную функциональность 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) как клиент
    Вторая вкладка из группы Indy носит название Indy Servers (Рисунок 8.10).

    Компонент поддерживает протокол Trivial File

    Обеспечивает поддержку протокола 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Файл уже открыт
  • EIntError — потомок класса EExternal. Базовый класс для целочисленных математических ошибок.
  • EIntfCastError — потомок класса Exception. Неверное использование оператора as.
  • EIntoverfiow — потомок класса EIntError. Превышено максимальное значение целого числа.
  • EInvalidArgument — потомок класса EMathError. Аргумент математической функции задан неправильно.
  • EInvalidCast — потомок класса Exception. Неверное использование оператора as.
  • EInvalidGraphic — потомок класса Exception. Нераспознаваемый графический файл.
  • EInvalidGraphicOperation — потомок класса Exception. Неверное использование графических операций.
  • EInvalidGridOperation — потомок класса Exception. Неверное использование сетки (Grid).
  • EInvalidHandleException. Базовый класс для ошибок при оперировании объектами TFont, TPen и Tbrush.
  • EInvalidlmage — потомок класса EFilerError. Невозможно прочитать файл ресурсов.
  • EInvalidOp — потомок класса EMathError. Неизвестная операция с плавающей запятой.
  • EInvalidOperation — потомок класса Exception. Неверное действие над компонентом.
    Примечание
    Не путайте классы исключений EInvalidOp и EInvalidOperation!

  • EinvalidParam - базовый класс для неверных потоковых операций с ресурсами mime.
  • EInvalidPointer — потомок класса EHeapException. Неверная операция над указателем.
  • EMaskException — потомок класса Exception. Ошибка сравнения имени файла по маске.
  • EMathError — потомок класса EExternal. Абстрактный класс исключений для математических операций над вещественными числами.
  • EMenuError — потомок класса Exception. Ошибка при работе с системным меню.
  • EOutOfMemory — потомок класса EHeapException. Ошибка распределения памяти.
  • EOutOfResources — потомок класса EOutOfMemory. Ошибка распределения дескрипторов окон.
  • EOverflow — потомок класса EMathError. Превышено максимально возможное вещественное значение.
  • EPackageError — потомок класса Exception. Ошибка загрузки или уничтожения пакета.
  • EParserError — потомок класса Exception. Ошибка преобразования текста в двоичную форму.
  • EPrinter — потомок класса Exception. Ошибка вывода на печатающее устройство.
  • EPrivilege — потомок класса EExternal. Попытка выполнения инструкции процессора, которая является недоступной при данном уровне привилегий процессора.
  • EPropertyConvertError — потомок класса Exception. Ошибка установки или получения значения свойства компонента.
  • EPropertyError — потомок класса Exception. Ошибка при установке нового значения свойства компонента.
  • EQtDialogException — потомок класса Exception. Ошибка при работе с Qt-диалогом.
  • ERangeError — потомок класса EIntError. Значение целочисленной переменной превысило максимально возможное.
  • EReadError — потомок класса EFilerError. Ошибка чтения данных из потока.
  • EReconcileError — потомок класса EDBClient. Ошибка обновления набора данных клиента.
  • ERegisterActionsException — потомок класса Exception. He произведена инициализация регистрации системы.
  • EResNotFound — потомок класса Exception. Ошибка работы с файлами ресурсов.
  • ESafecallException — потомок класса Exception. Ошибка при выполнении безопасного вызова процедуры.
  • ESocketError — потомок класса Exception. Ошибка инициализации или отключения сокета.
  • EstackOverf low — потомок класса EExternal. Переполнение стека.
  • EstreamError — потомок класса Exception. Базовый класс ошибок, связанных с потоками.
  • EStringListError — потомок класса Exception. Неверная работа со списком.
  • EThread — потомок класса Exception. Ошибка синхронизации потоков.
  • ETreeViewError — потомок класса Exception. Неверная работа с деревом.
  • EUnderflow — потомок класса EMathError. Вещественное значение слишком мало.
  • EUpdateError — потомок класса EDatabaseError. Ошибка обновления набора данных сервера.
  • EVariantError — потомок класса Exception. Ошибка при работе с типом данных Variant.
  • EWebBrokerException — потомок класса Exception. Ошибка при работе с объектом WebBroker.
  • EWriteError — потомок класса EFilerError. Ошибка при записи данных в поток.
  • EZeroDivide — потомок класса EMathError. Ошибка деления вещественного числа на ноль.
  • Коды ошибок ввода/вывода Коды ошибок ввода/вывода Коды ошибок ввода/вывода

    базы данных dbExpress

    Таблица базы данных dbExpress

    SQLMonitorSQL-мониторПрерывает сообщения, проходящие между компонентом SQLConnection и сервером базы данных, и сохраняет их в списке

    может содержать разнотипные

    Таблица может содержать разнотипные данные. Например, пусть таблица состоит из четырех полей: 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)



    со строками

    Таблица со строками

    Компонент позволяет работать со строками текста, размещая их в таблицу. Позволяет быстро создавать приложения наподобие электронных таблицDrawGrid

    Таблица

    Таблица

    Позволяет работать с произвольной информацией в таблицеImageРисунокСлужит для отображения графического растрового файла, иконки или метафайлаShapeГеометрическая фигураПозволяет отображать произвольные геометрические фигуры. Например, эллипс, треугольник, прямоугольник и др.BevelФаскаПозволяет украсить ваше приложение путем размещения "трехмерных" линий или прямоугольниковScrollBoxОбласть прокруткиСоздает контейнер, который в случае необходимости автоматически, без вмешательства программиста, добавляет полосы прокруткиCheckListBoxСписок переключателейОтображает похожий на список компонент, который позволяет выбирать сразу несколько строк одновременноSplitterРазделитель

    /Размещается между двумя выровненными компонентами-контейнерами и позволяет пользователю во время работы приложения изменять размеры этих компонентов с помощью перемещения разделителяStaticTextСтатический текстКомпонент похож на метку, но имеет некоторые дополнительные возможности, о которых мы поговорим в дальнейшемControlBarПанель инструментовПозволяет быстро создавать панели инструментовLCDNumberLCD-номерТекстовое окно, в которое можно вводить текст или цифры. Все введенные значения будут отображаться на LCD-дисплееTimerТаймерНевизуальный компонент, генерирующий событие OnTimer циклически через определенный промежуток времениPaintBoxОкно для рисованияРазмещает на форме область, в которой можно рисовать, используя графические средства KylixТретья вкладка палитры компонентов Kylix называется Common Controls (Рисунок 8.3).

    Таблица

    баз данных

    Таблицы баз данных

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

    Рассмотрим структуру таблицы (Рисунок 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

    Установка свойств поля ID в окне Object Inspector

    Установка свойств поля Name в окне Object Inspector

    Рисунок 18.6. Установка свойств поля Name в окне Object Inspector

    Установка свойств поля 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) при наведении курсора на любую кнопку панели инструментов. Кроме того, имеется возможность разрешить или запретить показывать во всплывающих подсказках комбинации "горячих клавиш", выполняющих ту же функцию, что и кнопки панели инструментов.

    Вкладка Commands

    Вкладка 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

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

  • DataFields — определяет поле, значения которого будут отображаться в данном компоненте;
  • DataSource — определяет источник данных для этого компонента, т. е. компонент типа TDataSource.
  • На этом мы закончим краткий обзор компонентов для работы с базами данных.

    Назад

    Вкладка 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 пункт Tools/Environment Options (Средства/Настройки среды).

    Когда разработчик начинает новый проект, 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.

    Вкладка Events

    Вкладка 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 (Компонент/ Конфигурация палитры). Палитра компонентов состоит из следующих вкладок:

  • Standard (содержит стандартные компоненты, такие как кнопки, надписи и т. д.);
  • Additional (дополнительные компоненты, такие как рисунок, маска ввода и т. д.);
  • Common Controls (доступ к графическому пользовательскому интерфейсу);
  • Dialogs (стандартные диалоги для открытия, сохранения и печати файлов. Диалоги вызываются с помощью метода Execute. Возвращаемые значения: True — если пользователь нажал ОК и False — если пользователь выбрал Cancel);
  • Data Access (компоненты доступа к данным);
  • dbExpress (компоненты доступа к базам данных dbExpress);
  • Data Controls (управление данными);
  • Internet (создание Web-серверов для сети Интернет);
  • Indy Clients (последние три вкладки представляют компоненты для работы с различными сетевыми протоколами: TCP/IP, NNTP, HTTP и др.);
  • Indy Servers; П Indy Misc.
  • Конструктор форм (см. Рисунок 4.1) при первоначальном запуске Kylix представляет собой окно, не содержащее никаких элементов. Это окно называется формой (Form).

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

    Компоненты, расположенные на вкладках панели компонентов, делятся на:

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

    Примечание

    Визуальные компоненты могут быть не видны на форме, если они перекрыты другими компонентами или свойство видимости компонента (Visible) имеет значение False.

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

    Для настройки свойств, методов и событий компонентов используется Инспектор объектов (Object Inspector) (Рисунок 6.5).

    Инспектор объектов предназначен для выполнения трех основных функций:
  • установки свойств компонентов, размещенных на форме;
  • помощи в навигации и создании обработчиков событий;
  • фильтрации свойств и событий.
  • Инспектор объектов состоит из списка объектов и вкладок свойств (Properties) и событий (Events).

    Вкладка Options

    Вкладка Standart

    Рисунок 8.1. Вкладка Standart

    На этой вкладке расположены стандартные компоненты, такие как кнопки, фреймы, меню и т. д.

    Рассмотрим по порядку (слева направо) компоненты, расположенные на этой вкладке (табл. 8.1).



    Введение в создание компонентов

    Введение в создание компонентов

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

    Основы создания компонентов

    Итак, мы приступаем к процессу создания собственного визуального или невизуального компонента. Для создания собственного компонента важно иметь представление о библиотеке визуальных компонентов Kylix, об иерархии компонентов. Все это вам уже знакомо.

    Для чего же нужны новые компоненты? Зачем их создавать? Решение о создании новых компонентов может быть принято по ряду причин, среди которых:

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

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

  • определите для себя, какие действия должен выполнять компонент;
  • разработайте краткий алгоритм, по которому будет работать компонент;
  • разбейте всю конструкцию компонента на независимые части;
  • предоставьте возможность дальнейшей разработки компонента (возможно, в будущем вы захотите создать на его основе компонент-потомок);
  • напишите код компонента (этот пункт разбивается на такие этапы):
  • выбор предка для вашего компонента;
  • создание заготовки (модуля) компонента;
  • создание свойств, событий и методов компонента;
  • отладка и тестирование;
  • регистрация компонента в среде 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 произойдет создание нового метода вместо замещения старого.

    Замещение методов не работает со статическими методами — при замещении статического метода новым произойдет простая замена метода родителя в потомке.

    Назад Вперед

    Защита ресурсов

    Защита ресурсов

    

        Программирование: Языки - Технологии - Разработка