Окно сообщения
Рисунок 9.1. Окно сообщения
Примечание
Знание имен классов исключений необходимо при обработке исключительных ситуаций. Мы рассмотрим их далее в этой главе.
В листинге 9.4 приведен пример использования временного имени объекта исключения в своих целях.
Окно сообщения об исключении
Рисунок 9.2. Окно сообщения об исключении
Примечание
С объектами исключений нужно работать очень осторожно. Ни в коем случае самостоятельно не уничтожайте объекты исключения — это может привести к ошибке работы программы. После завершения обработки исключения Kylix самостоятельно позаботится об его уничтожении.
Рассмотрим теперь классы исключений. Они необходимы для обработки конкретных исключительных ситуаций. Мы представляем классы исключений не в иерархии, а в алфавитном порядке.
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.
Окно свойств редактора
Рисунок 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).
выдаваемое при успешном перетаскивании
Рисунок 8.18. Окно, выдаваемое при успешном перетаскивании строки из ListBox1 в ListBox2
Операторы
Операторы
Оператор — это законченное предложение языка Object Pascal, которое выполняет какое-либо действие. Операторы могут быть:
структурированные.
Простые операторы — это операторы, которые не нарушают линейного выполнения программы, например операторы присваивания или арифметические операторы.
Структурированные операторы — операторы, которые влияют на ход выполнения программы. К таким операторам относятся операторы ветвления, цикла и некоторые другие.
Все операторы должны разделяться символом "точка с запятой". Если между операторами присутствует несколько точек с запятой, это не является ошибкой. Такие операторы (пустоты между двумя точками с запятой) называют пустыми операторами:
А:=5 ; ; ; / / один оператор присваивания и два пустых оператора
Заметим, что лишние точки с запятой недопустимы в описательной части программы. Их наличие может привести к ошибке компиляции.
Операторы языка Object Pascal мы подробно рассмотрим в главе 3 книги.
Операторы манипулирования данными
Операторы манипулирования данными
Главным оператором манипулирования данными является оператор 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.
Основы баз данных
Основы баз данных
В этой главе мы рассмотрим основные определения и термины, использующиеся при разработке баз данных. Изучим основные архитектуры приложений баз данных, которые поддерживает 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 можно разделить на три группы. Рассмотрим эти группы, а также операторы, входящие в каждую из групп.
Операторы определения данных — предназначены для создания, удаления и изменения структуры данных. Основные из них перечислены в табл. 17.1.
Отличия CLX от VCL
Отличия CLX от VCL
Хотя многое в CLX и VCL выполнено одинаково, они имеют некоторые отличия. Рассмотрим их.
В Linux вы можете использовать свойство TApplioation.Style для задания внешнего вида приложения (начертания графических элементов).Можно оставить стиль таким, каким он установлен в Linux, но все же рекомендуется использовать свойство Style.
Весь код для работы с вариантным типом данных (variant), который находился в модуле system, в CLX содержится в двух новых модулях:
Variants.pas;
VarUtils.pas.
Таким образом, если вы хотите использовать в своем приложении вариантные переменные, не забудьте добавить в раздел uses модуль Variants.
Нажатие клавиши <Enter> не имитирует событие щелчка кнопки мыши, как это происходит в Delphi.
Компонент TColorDialog не имеет свойства TColorDialog.Options. Таким образом, вы не можете настроить работу и функциональность диалога выбора. Кроме того, TColorDialog не всегда является модальным (модальным называется окно, которое не позволяет пользователю работать с другими окнами, пока не будет закрыто).
Во время выполнения приложения комбинированные списки (TComboBox) работают по-разному в Kylix и Delphi. В Kylix вы можете добавить строку в список, введя нужный текст строки и нажав на клавишу <Enter> для ввода комбинированного списка. Эту опцию можно отключить, установив свойство InsertMode в ciNone. Также в Kylix можно добавить пустой (не содержащий строку) элемент списка в комбинированный список. Если вы нажмете и будете удерживать клавишу <Ї> на клавиатуре управления курсором при активном комбинированном списке, то список не остановится на последней строке как в Delphi, а будет прокручиваться опять сверху вниз.
Компонент TCustomEdit нe поддерживает Undo, ClearUndo и CanUndo. Но пользователь приложения может отменить редактирование в поле для ввода TEdit во время работы приложения, нажав правую кнопку мыши над полем для ввода и выбрав в выпадающем меню пункт Undo.
Значение кода клавиши <Enter> при использовании событий OnKeyDown или OnKeyUp в Windows равно 13. В Linux для этой же клавиши код имеет значение 4100.
Пакеты компонентов
Пакеты компонентов
Пакеты — это специальные динамически присоединяемые компоненты (аналоги файлов so — разделяемых объектов, Shared Objects). По своему использованию пакеты делятся на:
пакеты, используемые во время разработки приложения (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).
Параметры и аргументы
Параметры и аргументы
Параметры — это элементы подпрограммы, которые используются при описании блока подпрограммы.
Аргументы — это элементы, которые указываются при вызове подпрограмм. Они замещаются соответствующими параметрами подпрограммы.
В качестве параметров могут выступать:
константы;
переменные.
Параметрами могут быть элементы абсолютно любого типа.
Все параметры разделяются на группы, в зависимости от того, чем они являются:
Параметры-значения — это параметры, перед которыми в заголовке подпрограммы не стоит слово 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 обеспечивает программисту три пути для доступа к информации, содержащейся в базах данных;
Эти три метода не применяются в 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 не содержит встроенную поддержку обновления данных, кроме способности выполнения запросов 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
Подпрограммы и модули
Подпрограммы и модули
В этой главе мы расскажем о принципах описания функций и процедур языка Object Pascal. Вы узнаете, чем отличается параметр подпрограммы от аргумента и научитесь сами создавать процедуры и функции. В конце главы мы рассмотрим понятие модуля.
Подпрограммы
Подпрограмма — это небольшая законченная программа, состоящая из операторов и команд языка и оформленная специальным образом.
Подпрограммы используются для сокращения объема программы и могут вызываться из любого места основной программы. Уменьшение объема программы достигается за счет того, что в программах часто имеются одинаковые участки кода, которые можно вынести в подпрограмму и вызывать ее в нужных местах программы.
По своей структуре подпрограмма аналогична обычной программе, но блок uses в подпрограмме отсутствует. Подпрограмма также имеет некоторые отличия в оформлении заголовка.
Прежде чем работать с подпрограммой, ее необходимо описать.
При описании и вызове подпрограммы записываются имя подпрограммы, список и значения параметров (аргументов), которые передаются данной подпрограмме для работы, а также действия, выполняемые этой подпрограммой.
В качестве параметров функции могут выступать любые описанные в ней переменные. Параметры используются для передачи данных из основной программы в подпрограмму. Однако подпрограмма может не иметь параметров.
В модулях Kylix имеется несколько десятков стандартных подпрограмм, которые могут вызываться без предварительного их описания.
Все подпрограммы в языке Object Pascal делятся на две группы:
процедуры; функции. Главным отличием функции от процедуры является то, что функция может возвращать под своим именем какое-либо значение. Процедура этого делать не может.
Для досрочного выхода из подпрограммы и передачи управления основной программы достаточно вызвать процедуру Exit. Подпрограммы допускается вызывать из других подпрограмм.
Поля
Поля
Поле объекта предназначено для хранения данных, содержащихся в объекте. Описание поля не отличается от описания обычной переменной и может быть любого типа. Приведем пример описания поля объекта:
type TNumber = class
FInt: Integer; end;
Данный пример создает в классе TNumber новое поле FInt целочисленного типа.
Примечание
По взаимному соглашению разработчиков, имена полей должны начинаться с буквы F (по-английски field означает поле).
Обратите внимание на то, что данный класс TNumber является прямым потомком класса TObject. Так как после слова class в круглых скобках не указывается класс-предок. Поэтому объявление типа в первой строке примера может быть таким:
type TNumber = class(TObject)
После создания нового класса он наследует все поля своего класса-предка. Удалить или переопределить поля класса-предка невозможно.
Поля ID и Name
Рисунок 18.7. Поля ID и Name
Правой кнопкой мыши щелкнем на компоненте Clients и выберем в выпадающем меню пункт CreateDataSet, а затем — пункт Save To MyBase Xml UTF-8 table. В появившемся диалоговом окне укажем имя xml-файла, который будет хранить данные о клиентах — Clients.xml и являться главной таблицей нашей базы данных (Рисунок 18,8).
Для того чтобы при запуске программы клиентский набор данных Clients читал данные из созданного нами xml-файла, значение его свойства FileName должно быть равно полному имени xml-файла.
Поля компонента Clients
Рисунок 18.9. Поля компонента Clients
Разместим в модуле данных компонент DataSource, установим его свойство Name в ds_Clients и свяжем его с компонентом Clients (свойство DataSet компонента ds_Clients установим равным Сlients). Затем установим свойство DataSource в ds__Clients. Окончательный вид модуля данных показан на Рисунок 18.10.
Посмотрим, как устроен внутри файл базы данных xml. После создания набора данных типичный файл базы данных выглядит, как представлено в листинге 18.1.
Помощи
помощи
Здесь представлены листинги модулей для создания системы помощи.
Понятие исключения
Понятие исключения
Среда Kylix предназначена для быстрой разработки довольно сложных программных комплексов. Сложная программа может по-разному взаимодействовать с операционной системой и уже запущенными в ней приложениями. Кроме того, пользователи вносят частичку непредсказуемости при работе с программой. В результате любое из вышеописанных взаимодействий может не выполниться или завершиться неправильно. Такие ситуации мы и будем рассматривать далее в этой главе. Ошибочных ситуаций, которые могут возникнуть, достаточно много. Простейшим примером может являться попытка программы выполнить деление на ноль или открытие несуществующего файла на диске. Все возможные ошибки программист предугадать не может. Для облегчения труда разработчика программ Kylix включает поддержку так называемых исключений или исключительных ситуаций.
Исключительная ситуация — это непредвиденное событие, произошедшее при выполнении программы и способное повлиять на ее дальнейшее выполнение.
Kylix предоставляет программисту механизм обработки исключительных ситуаций. Обработчик исключений позволяет приложению корректно обработать возникшую исключительную ситуацию (ошибку) и продолжить выполнение программы без потери данных и ресурсов. Для создания таких безопасных программ нужно лишь научиться писать обработчики исключительных ситуаций.
Далее мы рассмотрим задачи, которые можно решать с помощью исключений.
Построение компонентов
Построение компонентов
Теперь дополним модуль — заготовку нового компонента всем необходимым: свойствами, событиями и методами. Создадим работоспособный компонент и зарегистрируем его в среде Kylix. Затем рассмотрим, как можно модифицировать уже существующие компоненты визуальной библиотеки компонентов Kylix.
Создание свойств компонента
Добавление новых свойств в компонент осуществляется очень просто. Достаточно задать поля и свойства, определив при этом их тип и доступ (чтение, запись). Пример простого задания свойств в новый компонент представлен в листинге 19.2.
Применение свойства Align
Рисунок 8.12. Применение свойства Align
В случае, когда существует привязка к противоположным сторонам родительского компонента, при изменении его размеров будет происходить сжатие или растяжение дочернего компонента вплоть до полного исчезновения его изображения. Таким образом, данное свойство определяет как бы фиксацию расстояния от компонента до краев родительского компонента.
property BoundsRect: TRect;
Примечание
Настоящие координаты можно получить из следующих свойств компонента: Left (левый край компонента), Tор (верхний край), Width (ширина компонента) и Height (высота). Описание этих свойств приводится ниже.
Таким образом, запись
R := Control.BoundsRect;
эквивалентна записи
R.Top := Control.Top;
R.Left := Control.Left;
R.Right :- Control.Left + Control.Width;
R.Bottom := Control.Top + Control.Height;
Началом координат считается левый верхний угол окна, содержащего данный компонент.
property Caption: TCaption;
По умолчанию свойство устанавливается таким же, как имя компонента (свойство Name). Для пунктов меню и кнопок с помощью этого свойства можно задать кнопку быстрого вызова, для чего перед символом кнопки быстрого вызова ставится символ амперсанда (&). Например, для быстрого вызова меню Файл перед буквой "Ф" в свойстве Caption данного пункта меню можно поставить знак амперсанда: &Файл. При этом буква "Ф" в пункте меню станет подчеркнутой. Теперь для вызова данного пункта меню пользователю будет достаточно воспользоваться комбина-цией клавиш <Alt>+<Ф>. Для того чтобы отобразить в заголовке символ &, вы можете использовать такую запись: &&.
property ClientHeight: Integer;
Оно применяется при изменении размеров компонента, которые содержат в себе другие компоненты. При таком изменении будет происходить изменение компонентов, содержащихся в компоненте-контейнере.
Свойство ClientOrigin предназначено для получения экранных координат (х и у) левого верхнего угла клиентской области компонента. Началом координат является верхний левый угол экрана. Возвращаемые координаты передаются в структуре типа TPoint. Данное свойство предназначено только для чтения. Оно описано следующим образом:
property ClientOrigin: TPoint;
Свойство ClientRect возвращает координаты углов клиентской области компонента. Данное свойство также предназначено только для чтения. Координаты возвращаются в структуре типа TRect. Свойство описывается так:
property ClientRect: TRect;
Вместо вызова данного свойства можно воспользоваться свойствами Rect,
ClientWidth и ClientHeight (они описаны ниже):
Rect (0, 0, ClientWidth, ClientHeight)
property ClientWidth: Integer;
Свойство Сolor определяет цвет фона компонента. Значение данного свойства может быть или числом, определяющим интенсивность трех основных цветов (красного, зеленого и синего), или константой, определенной в Kylix (табл. 8.13).
Пример иллюстрирующий работу событий OnEnter и OnExit
Рисунок 8.20. Пример, иллюстрирующий работу событий OnEnter и OnExit
Запустим приложение. Фокус при запуске будет передан компоненту, который был размещен на форме первым (в нашем случае это кнопка Button1).
Если теперь выбрать щелчком мыши любой переключатель группы переключателей, то произойдет следующее:
для группы переключателей RadioGroup1 наступит событие OnEnter;
для выбранного переключателя из группы наступит событие OnEnter.
Если после этого выбрать щелчком мыши кнопку Button1, то события произойдут в следующем порядке:
для группы переключателей наступит событие OnExit ;
для кнопки Button1 наступит событие OnEnter.
Событие OnKeyDown наступает, когда пользователь нажимает любую клавишу. Данное событие происходит для компонента, имеющего фокус в момент нажатия кнопки. С помощью данного события можно обрабатывать все клавиши, включая <Shift>, <Alt> и <Ctrl>. В процедуру-обработчик передаются, кроме параметра 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).
Для создания файла базы данных необходимо указать поля и их типы. Сделать это можно двумя способами:
Проблемы переноса приложений
Проблемы переноса приложений
Kylix предоставляет возможность разработки так называемых кроссплат-форменных (межплатформенных) 32-разрядных приложений, которые могут работать как в среде Linux, так и в Windows, Для этого вы можете выбрать один из двух вариантов:
создать в среде Kylix новое приложение, следуя рекомендациям, которые представлены в данной главе.
Примечание
Большинство приложений, разработанных для работы в среде Linux (если не используются специфичные для Linux вызовы API), могут после перекомпиляции работать под Windows.
Процедуры
Процедуры
Процедура — это обыкновенная подпрограмма, которая не возвращает никакого значения под своим именем.
Описание процедуры также состоит из двух частей: заголовка и блока. Заголовок процедуры имеет следующий вид:
Procedure имя процедуры (параметры);
Имя процедуры должно быть уникальным и должно однозначно идентифицировать процедуру.
Параметры процедуры являются необязательными и служат для передачи каких-либо данных из основной программы в процедуру.
Блок процедуры содержит операторы и команды языка Object Pascal. Блок процедуры может быть пустым.
Вызов процедуры происходит по ее имени и списку аргументов, заключенных в круглые скобки.
Рассмотрим пример описания процедуры. Создадим процедуру, которая преобразует целое число в строку (листинг 4.2). Для этого в процедуру потребуется передавать два параметра — целое число и строку, в которую будет записан результат.
Процессы и потоки
Процессы и потоки
В этой главе мы рассмотрим проблему одновременного выполнения нескольких задач внутри одного приложения. Вы научитесь использовать объекты потоков и координировать их работу.
Первое определение, которое мы рассмотрим, — это многопоточность. Многопоточность используется для:
организации поведения приложения. Благодаря использованию потоков вы можете организовать выполнение частей приложения так, как вам захочется. Например, вы можете для каждой задачи приложения (если каждой задаче выделен свой поток) распределить приоритеты выполнения. Таким образом, задача, имеющая наибольший приоритет, будет занимать больше процессорного времени, что очень важно для решения критических задач;
поддержки мультипроцессорной обработки. Если в компьютере, на котором запущено многопоточное приложение, имеется несколько процессоров, то Можно значительно увеличить скорость выполнения вашего приложения, направляя на каждый процессор свой поток.
Примечание
Linux — это многопоточная операционная система с поддержкой архитектуры Intel MP. Процессы в Linux представляют собой отдельные задачи. Каждый процесс запускается в собственном виртуальном адресном пространстве и не способен взаимодействовать с другими процессами Исключение составляют лишь процессы, обеспечивающие механизмы защиты Linux, и процессы ядра операционной системы.
Простые операторы
Простые операторы
Для выполнения каких-либо действий в программе на языке Object Pascal применяются операторы. Операторы — это команды компилятору языка на выполнение определенных действий. Как мы уже отмечали ранее, все операторы делятся на простые и структурированные.
Напомним, что простые операторы не влияют на ход выполнения программы, т. е. сохраняют линейность выполнения команд программы.
Кроме рассмотренных ранее арифметических логических и строковых операторов, к числу простых операторов относятся:
пустой оператор;
составной оператор;
оператор доступа.
Оператор присваивания
Данный оператор является наиболее часто используемым в программах на языке Object Pascal. Оператор присваивания записывается с помощью знака :=. Данный оператор применяется для присваивания значения, записанного справа от знака присваивания переменной, которая записана слева от знака присваивания:
А:=10; // Переменной А присваивается значение 10
Если справа от знака присваивания стоит не конкретное значение, а выражение, оно будет вычислено и присвоено переменной слева от знака присваивания:
Переменная и выражение справа должны быть одного и того же или совместимого типа. Слева от оператора присваивания допустимо помещать не только переменную, Но и элементы массивов, поля записей и другие объекты.
Пустой оператор
Пустой оператор мы уже рассматривали ранее. Он представляет собой точку с запятой и может быть расположен в любом месте программы, где допускается наличие операторов. Данный оператор не выполняет никаких действий, но бывает иногда необходим.
Составной оператор
Составной оператор — это группа операторов, которые заключены между операторными скобками begin и end и отделены друг от друга точкой с запятой.
Таким образом, составной оператор представляет собой следующую конструкцию:
operator1; operator2;
. . . ;
operatorn; end; Такой оператор рассматривается как единое целое и может располагаться в любом месте программы, где допустимо наличие операторов.
Составные операторы могут быть вложены друг в друга. Например,
begin // Начало внешнего составного оператора operator1; begin // Начало внутреннего составного оператора
operator2_1;
operator2_2;
. . . ;
operator2_k;
end; // Конец внутреннего оператора
. . . ; operatorn; end; // Конец внешнего оператора
Количество вложений операторов друг в друга языком Object Pascal не ограничивается.
Оператор доступа
Оператор доступа предназначен для быстрого и удобного доступа к составным частям отдельных объектов. Например, удобно использовать оператор доступа при работе с полями записи. Если вы помните, для доступа к отдельному полю записи необходимо сначала указать имя этой записи и через точку — имя поля. Если нужно проделать несколько операций с разными полями записи, то оператор доступа использовать очень удобно.
Оператор доступа представлен следующим образом:
with объект do действие
Чтобы быстрее понять работу этого оператора, обратимся к листингу 3.3.
Простые типы данных
Простые типы данных
Работа с буфером обмена
Работа с буфером обмена
Вы можете использовать системный буфер обмена для копирования и вставки графики внутрь вашего приложения, а также для переноса графики из вашего приложения в другие и из других приложений в ваше. Для этого используется специальный объект Kylix Сlipboard. Этот объект позволяет оперировать различным типом информации, включая графику и текст.
Прежде чем вы сможете воспользоваться данным объектом, необходимо добавить в блок uses модуля, в котором будет использоваться буфер обмена, имя модуля OClipbrd:
uses
SysUtils, Types, Classes, Variants, QGraphics, QControls, QForms, QDia-logs, QStdCtrls, OClipbrd;
Данный модуль позволит обращаться к объекту Clipboard.
Копирование графики в буфер обмена
Для копирования графической информации в буфер обмена нужно ассоциировать графический объект с объектом Clipboard. Это можно сделать с помощью метода Assign.
Код, приведенный в листинге 13.21, показывает, как можно скопировать графический образ, содержащийся в компоненте типа Timage, имеющем имя Image, в буфер обмена, выбрав пункт меню Edit/Copy формы Form1.
Работа с графикой
Работа с графикой
Работа с мышью
Работа с мышью
Ваше приложение может реагировать на действия пользователя, которые он выполняет с помощью мыши. В этой части главы мы расскажем, как можно обрабатывать события мыши.
Событие мыши происходит в тот момент, когда пользователь двигает мышью или нажимает кнопки мыши. CLX поддерживает три события мыши, которые перечислены в табл. 13.4.
Работа с сокетами
Работа с сокетами
В этой главе мы рассмотрим некоторые сетевые возможности, предоставляемые средой Kylix на примере работы с сокетами.
Сокеты — это специальные компоненты, позволяющие вашему приложению соединяться с другими компьютерами, использующими сетевой протокол TCP/IP. Кроме того, сокеты дают возможность работать и с другими сетевыми протоколами, такими как XNS (Xerox Network System), DECnet и Novell IPX/SPX.
Используя сокеты, вы можете читать или посылать данные на другие компьютеры, не беспокоясь об установленном на компьютерах сетевом программном обеспечении. То есть сокеты предоставляют интерфейс между приложением-клиентом или приложением-сервером и сетевым программным обеспечением, установленным на данном компьютере.
Таким образом, сокеты позволяют создавать приложения как для клиентов, так и для серверов сети. Эти приложения могут предоставлять один из двух сервисов: Hypertext Transfer Protocol (HTTP) или File Transfer Protocol (FTP)
Перед написанием приложения клиента или сервера сети вы должны знать, какие услуги будет предоставлять ваше приложение, если это приложение-сервер, или какие услуги будет получать приложение-клиент. Если вы используете стандартные протоколы, такие как HTTP или FTP, то вопрос о предоставляемых услугах обычно не возникает.
Большинство стандартных услуг протоколов ассоциированы, по соглашению, с определенными номерами портов. Для получения конкретной услуги вы должны указать номер порта и цифровой код услуги. Если вы используете стандартные услуги, предоставляемые компонентом-сокетом TTCPClient, то он самостоятельно определит номер порта для нужной услуги. Если вы создаете собственные услуги, вы должны указать ассоциированный с ней номер порта в файле /etc/services. Данный файл представляет собой ASCII-файл, содержащий список сетевых услуг, включая их имя, номер порта и тип протокола передачи данных (листинг 11.1).
Различие сред Linux и Windows
Различие сред Linux и Windows
В табл. 21.5 приводится список отличий сред Linux и Windows.
Регистрация компонента в среде Kylix
Регистрация компонента в среде Kylix
Регистрация компонента необходима для размещения компонента в палитре компонентов.
При использовании эксперта компонентов для создания нового компонента Kylix самостоятельно создает процедуру регистрации компонента в модуле-заготовке. Создателю компонента в данном случае ничего не нужно делать, кроме следующих шагов:
указать имя подключаемого модуля (естественно, предварительно нужно сохранить модуль компонента).
После компиляции на выбранной вкладке палитры компонентов появится новый компонент.
Если же вы создаете компонент без использования эксперта компонентов, вам придется самостоятельно дописывать процедуру регистрации компонента. В разделе interface модуля компонента нужно дописать строку:
procedure Register;
А в разделе implementation — добавить процедуру регистрации. Например:
procedure Register; begin RegisterComponent ('Samples', [TMyButton] ); end;
В результате, компонент с именем TMyButton будет размещен на вкладке Samples палитры компонентов (Рисунок 19.8).
Результат работы компонента TWeek
Рисунок 19.6. Результат работы компонента TWeek
Создание собственных редакторов свойств
Перед тем как создавать собственный редактор свойств компонента, рассмотрим сначала имеющиеся в Kylix редакторы свойств. Их достаточно легко видеть в окне инспектора объектов, когда вы пытаетесь изменить какое-либо свойство компонента. Например, когда вы изменяете свойство Color для какого-либо компонента, вы видите редактор свойства цвета. Важно заметить, что все свойства компонентов имеют свои редакторы, даже такие простейшие свойства, как Caption, Height, Enabled имеют свои редакторы свойств. Особенностью этих редакторов является то, что компоненты "не знают", какие редакторы вы используете для изменения их свойств. Это может навести на мысль использовать собственный редактор свойств вместо заданного. Например, можно написать редактор свойства Width, который будет ограничен каким-либо числом.
Редакторы свойств имеют свою иерархию. Рассмотрим ее.
Базовым классом в иерархии редакторов свойств является TPropertyEditor. Названия классов говорят сами за себя. Например, класс TColorProperty отвечает за свойство цвета компонента, класс TIntegerProperty связан с теми свойствами, которые имеют тип Integer, и т. д. В листинге 19.9 приведен код, определяющий базовый класс TPropertyEditor.
Результат выполнения метода Pie
Рисунок 8.15. Результат выполнения метода Pie
Метод PolyLine рисует да канве незамкнутый многоугольник, т. е. кусочно-линейную кривую. Основное отличие этого метода от метода Polygon заключается в том, что PolyLine не соединяет первую и последнюю точки массива Points.
Метод Rectangle предназначен для рисования на канве прямоугольника. В качестве параметров метода передаются координаты двух точек: верхнего левого и правого нижнего углов прямоугольника. Прямоугольник рисуется текущим пером Реn и закрашивается цветом, определенным в свойстве Brush.
Примечание
Для рисования прямоугольника без рамки используйте метод FillRect. Для рисования прямоугольника со скругленными углами используйте метод RoundRect. Чтобы нарисовать незакрашенный прямоугольник, используйте метод FrameRect.
Метод 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).
Одномерный массив на десять переменных
Рисунок 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.
Форма приложения
Рисунок 4.1. Форма приложения
Для каждой формы приложения Kylix создается новый модуль. Например, при первоначальном запуске среды вы видите на экране форму с именем Form1 (Рисунок 4.1) и модуль формы с именем Unit1.pas (Рисунок 4.2).
Модуль Unitl pas
Рисунок 4.2. Модуль Unitl.pas
Рассмотрим состав модуля более подробно:
unit имя модуля; interface // Начало раздела интерфейса
uses // Список используемых модулей
const // Раздел объявления констант
type // Раздел объявления типов
var // Раздел объявления переменных
// Заголовки процедур // Заголовки функций implementation // Раздел реализации
uses // Список используемых модулей const // Раздел объявления констант
type // Раздел объявления типов
var // Раздел объявления переменных
// Описание процедур // Описание функций
initialization // Раздел инициализации // Операторы и команды finalization // Раздел завершения // Операторы и команды
end.
Первый раздел — раздел интерфейса, который является как бы "лицом" данного модуля. В нем размещены описания модулей, используемых данным модулем, а также объявляются типы, константы, переменные, функции и процедуры, описываются идентификаторы, являющиеся доступными всем модулям и программам, использующим данный модуль. Заметим, что для функций и процедур в данном разделе записываются только их заголовки. Непосредственно процедуры и функции размещены в следующем разделе — разделе реализации.
В разделе реализации, кроме процедур и функций, описываются типы, константы, переменные, а также модули, которые используются только в этом модуле, а за его пределами не видны. Кроме того, в данном разделе размещаются директивы компилятора — служебные команды среды разработки.
Последние два раздела не являются обязательными. В разделе инициализации размещаются операторы и команды, которые должны выполняться в начале работы программы, подключающей эти модули.
При наличии раздела инициализации в модуле может присутствовать раздел завершения. В данном разделе находятся операторы и команды, которые выполняются при завершении работы программы.
Иерархия классов Kylix
Рисунок 7.1. Иерархия классов Kylix
Следующий базовый класс, являющийся прямым потомком TObject, — класс TPersistent. Данный класс является предком всех классов, предназначенных для работы с потоками. Класс TPersistent наследует все свойства и методы своего предка — класса TObject, и может, кроме того, считывать данные из потока и записывать их в поток. Класс TPersistent обеспечивает:
назначение свойствам экземпляра класса конкретных значений;
средства для передачи содержимого одного экземпляра класса другому.
На одном уровне с классом TPersistent находится класс TStream, который тоже является прямым потомком класса TObject. Класс TStream является базовым для объектов потока. Этот класс может читать или записывать данные с носителей разных видов (файлы на дисках, динамическая память и т. д.). В дополнение к методам чтения, записи и копирования данных из потока настоящий класс обеспечивает поиск нужной позиции внутри потока. Этот класс относится к абстрактным классам и имеет следующие дочерние классы:
TStringStream — для манипулирования строками в памяти;
TMemoryStream — для работы с буфером памяти.
Потомком класса TPersistent является класс TComponent — базовый класс всех компонентов библиотеки компонентов CLX Kylix. Наследники класса TComponent, как и сам класс, имеют следующие возможности:
способность быть обладателем других компонентов и управлять другими компонентами.
На одном уровне с классом TComponent находятся еще несколько классов. Рассмотрим наиболее интересные из них.
Класс TGraphic — потомок класса Tpersistent, абстрактный класс. Данный класс является родительским для таких объектов, как иконки, растровые изображения и метафайлы, которые могут хранить и отображать визуальные изображения. Данный класс, кроме того, предоставляет методы для работы с объектом TPicture и буфером обмена.
Класс THandleComponent — является базовым для невизуальных компонентов, у которых имеется дескриптор окна.
Дескриптор окна — это число (индекс), индивидуальное для данного конкретного окна, назначаемое системой Linux.
Класс TField — является базовым для всех компонентов, содержащих поля. Данный класс инкапсулирует свойства, события и методы, которые используются для:
конвертирования типов данных внутри поля;
подтверждения ввода данных в поле;
определения того, в каком качестве находятся данные внутри поля: в качестве редактируемых или отображаемых;
подсчета результата в полях данных с помощью события OnCalcFields; просмотра значений полей из других наборов данных.
Класс TDialog — это абстрактный класс, являющийся предком для всех диалоговых окон. Он используется как базовый класс для двух основных типов диалоговых окон CLX:
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
Диалоговое окно New Items
Рисунок 10.1. Диалоговое окно New Items
2. Щелкните на пиктограмме Application.
3. Нажмите кнопку ОК.
Для создания нового MDI-приложения выполните следующие шаги:
1. Выберите в главном меню Kylix пункт File/New для вызова диалогового окна New Items.
2. Выберите в диалоговом окне вкладку Projects и щелкните на пиктограмме MDI Application (Рисунок 10.2).
3 Нажмите кнопку ОК.
Вкладка Projects
Рисунок 10.2. Вкладка Projects
В MDI-приложении главная форма содержит несколько дочерних форм, которые могут размещаться внутри главной, но не могут выходить за ее пределы. Для определения, какая форма будет главной, а какая дочерней, установите свойство FormStyle каждой из форм в следующие значения:
При создании MDI-приложения Kylix делает большую часть работы за программиста. Если вы выполнили вышеперечисленные шаги для создания MDI-приложения, то можете видеть, что Kylix уже создал главную форму (Рисунок 10.3).
Главная форма MDIприложения
Рисунок 10.3. Главная форма MDI-приложения
Более того, данная форма имеет необходимые компоненты для работы со многими дочерними окнами, а также главное меню для работы с файлами и окнами. Кроме того, меню содержит пункт Edit для работы с текстом. Таким образом, Kylix уже сделал для нас простейший многооконный текстовый редактор. Естественно, вы можете самостоятельно расширить его функциональность либо удалить ненужные компоненты.