Как составить программу в делфи

Программирование в Delphi – YouTube

Уроки для новичков

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

Урок 2 – Переменные и их типы

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

Урок 3 – Конструкция IF…THEN…ELSE

Здравствуйте, в этом уроке я познакомлю вас с конструкцией if…then…else и мы напишем программу проверки логина и пароля!И так, приступим! Конструкцией if…then…else можно проверять какое-нибудь условие, дословно она переводится так: если…то…иначе…

Урок 4 – Циклы

Цикл – это многократно повторяющаяся последовательность действий. Первый цикл, с которым мы познакомимся называется While…Do (делай пока верно условие)…

Урок 5 – Функции

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

Урок 6 – Одномерные массивы

Представьте себе поезд, у которого есть определенное количество вагончиков.У каждого вагона есть номер и внутри каждого, пронумерованного вагона можно хранить информацию.Дак вот массив примерно так и выглядит, только он не поезд :)…

Урок 7 – Многомерные массивы

Многомерные массивы – это практически то же самое, что и одномерные, только они представляют из себя матрицу…

Урок 8 – Форма и её свойства

Пришло время погрузиться в практическую часть и в этом уроке мы рассмотрим форму и ее основные свойства.Как вы уже знаете, все свойства любого объекта в Delphi располагаются в Object Inspector…

Урок 9 – События. Программное изменение свойств

В этом уроке я расскажу, что такое событие, реакция на событие и мы научимся программно изменять свойство компонентов.Создаем новый проект, на форму кидаем компонент Button с закладки Standard.Все свойства, выделенного компонента находятся в Object Inspector на вкладке Events…

Урок 10 – Знакомство с компонентами (часть 1/12)

Здравствуйте, дорогие друзья! В этом, десятом уроке, мы начинаем подробное знакомство с компонентами. Всего будет 11 уроков на эту тему.
В этом уроке мы будем знакомиться с компонентами на вкладке Standard…

Урок 11 – Знакомство с компонентами (часть 2/12)

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

Урок 12 – Знакомство с компонентами (часть 3/12)

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

Урок 13 – Знакомство с компонентами (часть 4/12)

Прошу прощения за задержку публикации тринадцатого урока.У меня было много дел и мало времени, но сейчас не об этом!
Давайте же продолжим изучение компонентов Delphi со вкладки Additional…

Урок 14 – Знакомство с компонентами (часть 5/12)

В этом уроке мы переходим на вкладку Win32!Первый компонент, который мы будем рассматривать на этой вкладке называется ImageList или как говорят в народе ”хранилище картинок”…

Урок 15 – Знакомство с компонентами (часть 6/12)

В этом уроке мы продолжаем знакомится с компонентами из вкладки Win32 и сейчас рассмотрим компонент под названием TrackBar.Компонент TrackBar представляет из себя некое поле с засечками и бегунок…

Урок 16 – Знакомство с компонентами (часть 7/12)

Продолжаем изучать закладку Win32 и в этом уроке мы познакомимся с двумя компонентами, а именно: Animate и StatusBar.Компонент Animate позволяет проигрывать на форме клипы в формате AVI и отображать стандартную анимацию…

Урок 17 – Знакомство с компонентами (часть 8/12)

В этом уроке мы продолжаем изучать вкладку Win32.В этот раз мы будем рассматривать компонент под названием ListView…

Урок 18 – Знакомство с компонентами (часть 9/12)

В этом уроке мы продолжаем изучать вкладку Win32.В этот раз мы будем рассматривать компонент под названием TreeView. Мы научимся добавлять, удалять, изменять и сортировать.Этот компонент предназначен для отображения сложной иерархической структуры данных. Например в левой области проводника Windows используется этот компонент для быстрой навигации по папкам…

Урок 19 – Знакомство с компонентами (часть 10/12)

В этом уроке мы продолжаем изучать вкладку Win32.Сейчас мы будем рассматривать компонент под названием Timer.Этот не визуальный компонент предназначен для повторения участка кода через определённые промежутки времени…

Урок 20 – Знакомство с компонентами (часть 11/12)

В этом уроке мы продолжаем изучать вкладку System.В этот раз мы будем рассматривать компонент под названием MediaPlayer…

Урок 21 – Знакомство с компонентами (часть 12/12)

Здравствуйте, дорогие друзья! Сегодня я расскажу вам про вкладку с компонентами – Dialogs.Компонент OpenDialog позволяет инициализировать диалог открытия файла.

Урок 22 – Принцип работы с файлами

В этом уроке изучим принцип работы с файлами.

Урок 23 – Функции для работы с мышью

В этом уроке мы изучим функции для работы с мышью.Итак, начнём! Вытащим на форму 5 кнопок и зададим свойства Caption: ‘Переместить курсор’, ‘Скрыть курсор’, ‘Показать курсор’, ‘Поменять кнопки’, ‘Вернуть кнопки’…

Урок 24 – Изучаем компонент PaintBox

В этом уроке изучим компонент под PaintBox на вкладке System.У этого компонента есть один недостаток проявляющий себя только на Windows XP: работающую программу перекрасть окном другой программы то все содержимое компонента стирается…

Урок 25 – Подробное изучение RichEdit’a

В этом уроке изучим компонент на вкладке .Кинем на форму компонент RichEdit и ToolBar, свойство Align у RichEdit установим на alClient и наш компонент растянется на всю форму. Определимся что будет уметь делать наш редактор: Загружать, сохранять, выравнивание (По левому краю, по центру, по правому краю), стилизация текста…

Урок 26 – Создаем игру Ping-pong – часть(1/3)

Начинаем писать простенькую игру Пинг-Понг.Думаю, смысл игры Пинг-Понг давно всем известен :)…

Урок 27 – Создаем игру Ping-pong – часть(2/3)

Продолжаем писать игру Пинг-Понг. В этом уроке мы займемся реализацией игрока.

Урок 28 – Создаем игру Ping-pong – часть(3/3)

Заканчиваем писать игру Пинг-Понг и в этом уроке мы сделаем искусственный интеллект…

Урок 29 – Работа с DLL

В этом уроке мы ознакомимся с динамическими библиотеками Windows. Научимся её использовать и создавать…

Урок 30 – Знакомство с базами данных

В этом уроке мы создадим простую базу данных. Я буду использовать Microsoft Access 2013…

Урок 31 – Продолжение работы с базами данных

В этом уроке мы откроем нашу ранее созданную базу данных в Delphi.Для того чтобы открыть базу данных нам понадобятся 4 компонента: ADOConnection, ADOQuery с вкладки AOD, DataSource…

Урок 32 – Объединение всего изученного про базы данных

В этом уроке мы объединим все, что мы прошли ранее…

Урок 33 – Автовыключатель компьютера

В этом уроке мы создадим программу под названием “рубильник”…

Урок 34 – Шифрование информации

В этом уроке мы научимся зашифровывать и расшифровывать текст…

Урок 35 – Создаем Веб браузер

Пишем свой интернет браузер на основе Internet Explorer 🙂 …

Урок 36 – Взаимодействие с веб страницей

В этом уроке мы попробуем авторизоваться на сайте yandex.ru…

Урок 37 – Запись рабочего стола

В этом уроке мы будем делать снимки экрана…

Урок 38 – Запись рабочего стола, интерфейс

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

Урок 39 – Панель быстрого запуска (часть 1/2)

Начинаем создавать панельку быстрого запуска, в этом уроке мы сделаем движение (скрытиепоказ)…

Урок 40 – Панель быстрого запуска (часть 2/2)

В этом уроке мы доработаем панель быстрого запуска и добавим функцию Drag-and-drop…

Урок 41 – Пишем MediaPlayer, часть(1/7)

Мы начинаем писать MediaPlayer с использованием звуковой библиотеки Bass…

Урок 42 – Пишем MediaPlayer, часть (2/7)

В этом уроке мы поработаем над интерфейсом, добавим кнопки ‘Стоп’, ‘Пауза’ и т.д.

Урок 43 – Пишем MediaPlayer, часть(3/7)

В этом уроке мы добавим возможность перематывать файл…

Урок 44 – Пишем MediaPlayer, часть(4/7)

В этом уроке мы поработаем над интерфейсом и добавим плей-лист…

Урок 45 – Пишем MediaPlayer, часть(5/7)

В этом уроке мы научимся удалять файлы, изменять громкость и другое…

Урок 46 – Пишем MediaPlayer, часть(6/7)

В этом уроке мы сделаем сохранение плей-листа в файл и его загрузку…

Урок 47 – Пишем MediaPlayer, часть(7/7)

Этот урок будет завершающим, мы добавим функцию Drag-and-drop и доделаем интерфейс…

Урок 48 – Структурные типы данных, часть (1/2)

В этом уроке мы раскроем важную тему собственных типов данных…

Урок 49 – Структурные типы данных, часть (2/2)

В этом уроке мы продолжаем изучать структуры и рассмотрим Множества и Записи…

Урок 50 – Динамическое создание компонентов, часть (1/2)

В этом уроке мы научимся создавать компоненты во время работы программы (на лету)…

Урок 51 – Динамическое создание компонентов, часть (2/2)

В этом уроке мы узнаем ошибках которые могут возникать в процессе работы…

Урок 52 – Исключительные ситуации

В этом уроке мы научимся правильно обрабатывать ошибки которые могут возникать в процессе выполнения программы…

Урок 53 – Потоки в Delphi, (часть 1/3)

В этом уроке мы познакомимся с методами создания потоков и узнаем что это такое…

Урок 54 – Потоки в Delphi, (часть 2/3)

В этом уроке мы научимся правильно запускать наш поток…

Урок 55 – Потоки в Delphi, (часть 3/3)

В этом уроке мы научимся скачивать файл из интернета в потоке…

Урок 56 – Создание собственных процедур и функций Delphi, (часть 1/3)

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

Урок 57 – Создание собственных процедур и функций Delphi, (часть 2/3)

Продолжаем и пишем программу суммирования двух чисел…

Урок 58 – Создание собственных процедур и функций Delphi, (часть 3/3)

В этом уроке мы узнаем особенности передачи параметров и некоторые возможности…

Урок 59 – Классы Delphi, (часть 1/5)

В этом уроке мы познакомимся с классами, узнаем что это такое и с чем его едят…

Урок 60 – Свойства классов Delphi, (часть 2/5)

В этом уроке мы продолжаем изучать классы и в этом уроке мы разберёмся в их свойствах…

Урок 61 – Свойства классов Delphi, (часть 3/5)

В этом уроке мы продолжаем изучать классы и в этом уроке мы разберёмся в их свойствах…

Урок 62 – Методы, наследование классов, операции с классами Delphi, (часть 4/6)

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

Урок 63 – Методы, наследование классов, операции с классами Delphi, (часть 5/6)

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

Урок 64 – Виртуальные методы, полиморфизм, абстрактные классы Delphi, (часть 6/6)

В этом уроке мы продолжаем изучать классы и мы углубимся в самые дебри классов…

Урок 65 – Ресурсы в Delphi, (часть 1/2)

В этом уроке мы узнаем, что такое ресурсы…

Урок 66 – Ресурсы в Delphi, (часть 2/2)

В этом уроке мы узнаем, что такое ресурсы…

Урок 67 – INI файлы

В этом уроке мы узнаем как пользоваться Ini файлами…

Урок 68 – Реестр Windows, (часть 1/2)

В этом уроке мы узнаем, что такое Реестр Windows и как им пользоватся…

Урок 69 – Реестр Windows, (часть 2/2)

Продолжаем изучать реестр…

Урок 70 – Динамические библиотеки DLL

В этом уроке мы узнаем, что такое и как пользоваться библиотеками…

Урок 71 – Работа с сжатыми файлами

В этом уроке мы узнаем, как работать с архивами…

Урок 72 – Получение хеша файла

В этом уроке мы узнаем, как получить хеш файла и как его можно использовать…

Урок 73 – Указатели

В этом уроке мы узнаем, что такое указатели в delphi…

Урок 74 – Создание и использование интерфейса (часть 1/2)

В этом уроке мы начнем изучать интерфейсы…

Урок 75 – Создание и использование интерфейса (часть 2/2)

В этом уроке мы продолжим изучать интерфейсы…

Урок 76 – Работа с реестром

Из этого урока вы узнаете, как в Delphi 7 работать с реестром Windows…

Урок 77 – Использование потоков данных (часть 1/3)

В этом уроке мы начнем изучать использование потоков данных…

Урок 78 – Использование потоков данных (часть 2/3)

В этом уроке мы продолжим изучать использование потоков данных…

Урок 79 – Использование потоков данных (часть 3/3)

В этом уроке мы закончим изучать использование потоков данных…

Урок 80 – Работа с памятью в системе Windows32 (часть 1/3)

В этом уроке мы начнем изучать принципы работы с памятью в системе Windows 32…

Урок 81 – Работа с памятью в системе Windows32 (часть 2/3)

В этом уроке мы продолжим изучать принципы работы с памятью в системе Windows 32…

Урок 82 – Работа с памятью в системе Windows32 (часть 3/3)

В этом уроке мы закончим изучать принципы работы с памятью в системе Windows 32…

Урок 83 – Создание своих компонентов (часть 1/3)

В этом уроке мы начнем создавать свои компоненты…

Урок 84 – Создание своих компонентов (часть 2/3)

В этом уроке мы продолжим создавать свои компоненты…

Урок 85 – Создание своих компонентов (часть 3/3)

В этом уроке мы закончим создавать свои компоненты…

Урок 86 – Оператор Case

В этому уроке я расскажу о эффективном и удобным для большого количества вложенных условий операторе CASE…

Урок 87 – Оператор GOTO

В этому уроке я расскажу об операторе GOTO…

Урок 88 – Рекурсия

В этому уроке я расскажу о таком явлении как рекурсия…

Урок 89 – Множества

В этому уроке мы рассмотрим такое понятие, как множества в Delphi…

Урок 90 – Создание компонентов

В этому уроке мы научимся создавать компоненты для Delphi…

Печатать книгуПечатать книгу

Введение в программирование на Delphi

Автор: Ачкасов Вячеслав Юрьевич

Сайт: Электронные курсы ТПУ
Курс: Информационные технологии 1
Книга: Программирование на Delphi
Напечатано:: Гость
Дата: Вторник, 16 Май 2023, 13:12

Оглавление

  • 1. Введение
  • 2. Объектно-Ориентированное Программирование (ООП)
  • 3. Строки
  • 4. Собственный Блокнот
  • 5. Вычисления
  • 6. Свойства формы
  • 7. Свойства кнопки TButton
  • 8. Изучаем компоненты Panel, GroupBox, RadioGroup, CheckBox
  • 9. Свойства Enabled и Visible
  • 10. Главное меню
  • 11. Всплывающее меню
  • 12. Модальные окна
  • 13. Структура проекта
  • 14. ListBox – список выбора
  • 15. ComboBox – выпадающий список
  • 16. Диалоги
  • 17. Сетка строк StringGrid
  • 18. Image

1. Введение

На нашем курсе мы будем изучать Delphi 7, наиболее стабильную версию языка программирования для Win32 – то есть 32-разрядных версий Windows. Появились и новые версии Delphi, но они ориентированны на технологию .NET, за которую начинающим программистам браться рановато. Тем более, что эта технология еще не применяется широко, и рынок программного обеспечения, созданного с помощью Delphi, все равно составляют программные продукты, написанные на Delphi 7, и даже более ранних версий.

Основу Delphi составляет не только сам язык, но и RAD (Rapid Application Development)среда быстрой разработки программ. Благодаря визуальному программированию, а также достаточно большой библиотеке визуальных компонентов, Delphi позволяет создавать программы наиболее быстро и эффективно, принимая на себя основную работу, и оставляя программисту творческий процесс. Разумеется, возможность быстрого создания профессиональных приложений для Windows делает Delphi – программистов востребованными во всех отраслях человеческой деятельности.

Первая программа

Традиционно при изучении программирования принято создавать первую программу, которая выводит текст “Hello, world!”. Не будем отступать от традиции и создадим программу, которая выводит этот текст тремя разными способами. Но вначале познакомимся с самой средой программирования Delphi. Предполагается, что на этот момент Delphi 7 уже установлена на вашем ПК. Если это не так, то перед дальнейшим прочтением лекции установите Delphi 7. При загрузке Delphi 7 вы видите такую картину:

Рабочая среда Delphi 7

Рис. 1.1.  Рабочая среда Delphi 7

Познакомьтесь – это Delphi. У нее есть много окон, панелей, компонентов. С большинством из них мы познакомимся со временем, а пока нам нужно обратить внимание на 5 окон:

  1. Главное окно Delphi. Здесь находится основное меню, различные панели инструментов и палитра компонентов, состоящая из множества вкладок.
  2. Конструктор формы. Здесь мы визуально видим, как будет выглядеть форма программы, здесь мы будем создавать интерфейс, перенося на форму различные компоненты, и расставляя их таким образом, чтобы интерфейс выглядел привлекательным. Нам часто придется переключаться между конструктором форм и редактором кода, делается это клавишей F12.
  3. Редактор кода. Здесь мы видим исходный код программы, который создан самой Delphi. Тут же мы будем вводить наш собственный код.
  4. Объектный инспектор. Он предназначен для управления объектами проекта и состоит из двух вкладок – Properties (Свойства) и Events (События).
  5. Дерево объектов. Здесь мы видим, какой именно объект в данный момент является текущим. Это окно будет особенно полезно, когда на форме появится множество компонентов.

Когда открывается Delphi, она автоматически создает и отображает новый проект (программу). На рисунке вы видите проект, который содержит только одну стандартную форму. Форма – это тоже объект, который представляет собой окно программы. Чтобы программа делала что-то полезное, нам придется вносить изменения в нее. Выведем текст “Hello, world!” первым способом. Для этого в инспекторе объектов найдите свойство Caption. В данный момент текущим является объект – форма, и свойство Caption формы отвечает за надпись на системной строке программы (синяя полоса вверху любого программного окна). По умолчанию, свойство Caption содержит надпись “Form1”, также называется и сама форма. Измените эту надпись на “Hello, world!” (конечно, без кавычек). Уже в процессе ввода текста вы видите, что надпись в системной строке принимает новый вид. Мы ввели этот текст одним способом.

Теперь нам нужно сохранить проект. Проект – совокупность файлов разных форматов, из которых создается программа. Об этом мы подробней поговорим в одной из следующих лекций, а пока запомните правило – каждую программу (проект), которую вы создаете, нужно сохранять в отдельной папке. Если вы все проекты станете сохранять в одну папку, то очень скоро запутаетесь. Чтобы сохранить проект, выполним следующие действия:

  1. Выбираем команду меню “File – Save All” (сохранить все), либо нажимаем горячие клавиши <Shift+Ctrl+S>, либо нажимаем одноименную кнопку на панели инструментов

    Кнопки Save (Сохранить) и Save All (Сохранить всё) на панели инструментов

    Рис. 1.2.  Кнопки Save (Сохранить) и Save All (Сохранить всё) на панели инструментов

  2. Затем выходит окно с предложением сохранить модуль – текстовый файл с исходным кодом, принадлежащий форме. Файл имеет расширение *.pas. Имеем в виду, что каждый проект сохраняется в отдельную папку, поэтому вначале щелкнем правой кнопкой мыши по свободному месту окна с папками, и выберем команду “Создать – Папку”. Дадим папке какое-либо имя, например, “01”. После создания папки открываем ее.
  3. Далее в поле “Имя файла” укажем имя сохраняемого модуля. Имя может быть любым, но обязательно латинскими символами. Еще имя модуля не должно совпадать с именем формы. Обычно, имена формам и модулям стараются делать информативными, то есть, по имени можно будет догадаться, что это за файл. Поскольку это главная форма проекта, дадим ей имя “Main”, и нажмем кнопку “Сохранить”.
  4. Затем нам будет предложено дать имя проекту в целом. Имя проекта будет совпадать с именем исполняемого программного файла. Если мы хотим, к примеру, получить файл “hello.exe”, то дадим проекту имя “hello”. Нажмем кнопку “Сохранить”.

Далее нам необходимо скомпилировать программу, то есть, перевести исходный код в выполняемый exe-файл. Для этого мы можем выбрать команду меню “Run – Run”, либо нажать горячую клавишу F9, либо нажать кнопку “Run” на панели инструментов (на кнопке изображение зеленой стрелки, указывающей вправо). В результате, программа была не только скомпилирована, но и запущена. Если вы посмотрите на системную строку Delphi, то увидите надпись “Delphi 7 – hello [Running]”, а окна инспектора объектов и дерева объектов исчезли. Это говорит о том, что программа находится в режиме выполнения. Выполняемая программа имеет точно такой же вид, как наша главная форма, только на форме отсутствует точечная сетка, предназначенная для облегчения дизайна. Окно полученной программы содержит все стандартные кнопки Windows – программы. Щелкнув по красному крестику в правой верхней части окна, закройте программу (но не Delphi), и вы увидите прежнюю форму.

Обратите внимание, что свойства в Объектном Инспекторе принадлежат выделенному в данный момент компоненту. Выделяются компоненты простым щелчком мыши. Имейте в виду, что щелкать нужно один раз. Двойной щелчок создаст обработчик события – процедуру. Если вы ошибочно создадите таким образом процедуру, то просто сохраните проект, ничего в нее не вписывая – при сохранении последние пустые процедуры автоматически удаляются. Удалять их вручную не рекомендуется.

Попробуем второй способ. Обратите внимание на Палитру компонентов. Текущей является вкладка Standard, и на ней находится множество значков – компонентов. Когда вы подводите указатель мыши к какому-либо компоненту, через некоторое время выскакивает подсказка с именем компонента. Нам нужен компонент Label, который представлен на вкладке в виде кнопки с изображением жирной буквы “А”. Щелкните по этой кнопке, затем щелкните по свободному месту на форме, чтобы вставить компонент. Лучше, если вы расположите его ближе к левому верхнему краю формы. Компонент Label появился на форме. Этот компонент представляет собой обычную надпись. Сейчас он выделен, и содержит надпись по умолчанию, – “Label1”. Теперь объектный инспектор показывает свойства этого компонента, а не формы. Label также имеет свойство Caption, которое вы можете изменить в Инспекторе объектов. Найдите это свойство, и вместо “Label1” впишите “Hello, world!”. Текст в компоненте Label изменился. Если вам не нравится место, в котором оказался компонент, вы можете перетащить его мышью на другое место. Кроме того, точное местоположение компонента вы можете задать, если выделите его, и будете нажимать клавиши перемещения курсора, удерживая при этом клавишу <Ctrl>. Теперь попробуйте еще одно свойство компонента Label – свойство Font (шрифт). Найдите это свойство в инспекторе объектов, и выделите его. Справа появится кнопочка с тремя точками, нажмите ее. Откроется стандартное окно выбора шрифта. Здесь вы можете выбрать имя шрифта, его размеры, начертание (например, жирный курсив) и цвет текста. Поэкспериментируйте с размером компонента, его положением и шрифтом. Почти все компоненты, с которыми нам придется иметь дело, имеют эти свойства, так что в дальнейшем вам будет легче осваивать новый компонент.

Снова сохраните проект и нажмите кнопку Run (или <F9>). Убедитесь, что надпись появилась на форме, после чего закройте программу (но не Delphi) и вернитесь к форме.

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

Для начала нужно установить на форму кнопку. Этот компонент также находится на вкладке Standard палитры компонентов, и выглядит как кнопочка с надписью “ОК”. При наведении на него указателя мыши выскакивает подсказка “Button”. Щелкнув по компоненту, щелкните затем по тому месту на форме, где вы хотели бы видеть эту кнопку. Изменим надпись на кнопке. Убедитесь, что кнопка выделена, и найдите в инспекторе объектов ее свойство Caption. Замените надпись “Button1” на “Нажми меня!”. Если надпись не умещается на кнопке, вы можете растянуть кнопку мышью, или использовать для этого клавиши управления курсором с нажатой кнопкой <Shift>.

Далее нам нужно создать обработчик нажатия на кнопку. Обработчик представляет собой процедуру, в которой мы будем писать наш код. Этот код будет выполняться программой всякий раз, когда пользователь нажмет на эту кнопку. Чтобы создать этот обработчик, следует дважды нажать на кнопку на форме. Вы сразу попадаете в редактор кода и видите, что процедура уже создана, курсор мигает в том месте, где мы должны ввести свой код. Пока что не будем разбираться, что тут к чему, а просто впишем строку:

ShowMessage('Hello, world!');

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

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage('Hello, world!');
end;

Если у вас так и получилось, сохраните проект, откомпилируйте его и запустите на выполнение. При нажатии на кнопку будет появляться указанная надпись. Мы создали полноценную программу, выводящую надпись “Hello, world!” тремя различными способами, вписав при этом лишь одну строку исходного кода! Полученный файл hello.exe находится в указанной вами папке
C:Program FilesBorlandDelphi7Projects1

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

2. Объектно-Ориентированное Программирование (ООП)

Объектно-ориентированная компьютерная технология представляет собой одно из перспективных направлений развития инструментального ПО (компиляторы, интерпретаторы с ЯВУ, библиотеки СП, средства редактирования, отладки и тестирования, прикладные утилиты) 90-х годов и  позволяет существенно повышать качественный уровень и время разработок (до 10 раз) и производительность СУБД (до 100 раз). Особая интервенция объектно-ориентированной (ОО) технологии наблюдается в сфере создания графических программных средств. В чем же причина столь разительных перемен и каковы ее основные предпосылки?

Введение в ОО-технологию

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

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

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

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

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

Идеология ООП восходит к 60-м годам в связи с исследованиями по проблеме искусственного интеллекта. Понятие программных объектов впервые было введено в языке Simula-67, ориентированном на создание программ, предназначенных для имитации принятия решений в условиях управляемого множества обстоятельств. Существенным импульсом развитию ООП-технологии в массе пользователей послужило расширение пакета Turbo-Pascal 5.5, поддерживающее все основные аспекты ООП. Такой подход является более простым, чем создание нового ООП-языка и позволяет более естественно вввести пользователя в круг методики и методологии ООП. При ООП-подходе понятия процедуры и данных, используемых в обычных системах программирования, заменяются понятиями объект и сообщение.

Новая методология определяется тремя функциональными характеристиками ООП:

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

Так как ООТ представляет собой множество идей, то ее методологию лучше осваивать на 2-х уровнях: общем – что мы делали до сих пор  и конкретном – на основе конкретного языка,

Переходим к рассмотрению основ ООТ в среде визуального программирования Delphi. Языком программирования в ней является  Object Pascal – расширение языка Pascal.

Объект

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

Свойствами – цвет, текст на кнопке, шрифт текста и так далее.

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

Методами – обеспечивающими работу кнопки, например прорисовка кнопки в нажатом и не нажатом виде, прорисовка фокуса (то есть, фокус ввода находится на кнопке).

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

  • Свойства это переменные, которые влияют на состояние объекта. Например, ширина, высота, положение кнопки на форме или надпись на ней.
  • Методы это те же процедуры и функции, то есть это то, что объект умеет делать (вычислять). Например, объект может иметь процедуру для вывода какого-то текста на экран. Кнопка при нажатии меняет форму – это метод кнопки, процедура прорисовки вида нажатой и не нажатой кнопки.
  • События это те же процедуры и функции, которые вызываются при наступлении определенного события. Например, пользователь нажал на кнопку, вызывается процедура обработки этого нажатия. Или мышка оказалась над кнопкой – вызывается процедура обработки этого события, если программист ее создал.

Как уже упоминалось в первой лекции, программирование с применением объектов для программиста существенно упростилось. Вместо того, чтобы вписывать сотни строк кода, описывающего поведение одной единственной кнопки, программист просто объявляет объект типа “Кнопка”. Далее появились системы визуального программирования, такие как Delphi, которые используют компонентную модель программирования. Здесь уже программисту не нужно самостоятельно задавать такие свойства объекта, как его положение на форме, высоту и ширину. Вы просто устанавливаете нужный компонент на форму, и мышкой или клавиатурой двигаете, растягиваете или сжимаете его до нужных размеров. Серьезное программирование превратилось в детский конструктор, где Вы создаете интерфейс программы даже не задумываясь над тем, сколько кода для этого нужно было бы написать! Delphi это делает за Вас.

Компоненты это более совершенные объекты. То есть, это объекты, с которыми можно работать визуально. Справедливости ради следует отметить, что существуют и не визуальные компоненты, например, диалоги, с которыми нам скоро предстоит познакомиться. Не следует путать понятия “объект” и “компонент”. Каждый компонент – это объект, но не каждый объект является компонентом.

Представим себе отвлеченный пример. Допустим, у нас на палитре компонентов есть компонент ТЧел, который представляет собой усредненного человека. Если мы мышкой щелкнем по этому компоненту, а затем щелкнем по форме, то мы создадим отдельный, автономный объект этого компонента, который уже обладает всеми свойствами, методами и событиями, присущими каждому человеку.

Как у любого объекта, у него есть свойство Name – имя компонента, то имя, по которому мы будем в дальнейшем обращаться к этому объекту. Delphi по умолчанию присвоит ему текст “Чел1”. Если мы установим на форму еще один такой компонент, то будет создан еще один автономный объект, у которого свойство Name будет содержать строку “Чел2”. Итак, свойство Name – это переменная строкового типа, принадлежащая любому объекту, и являющаяся идентификатором (опознавателем), по которому к этому объекту нужно обращаться.

Далее, у нашего воображаемого объекта есть и другие свойства. К примеру, свойства Имя, Фамилия, Отчество. Это также строковые переменные, принадлежащие этому объекту. Мы можем вписать в них нужный текст программно:

Чел1.Имя := 'Иван';
Чел1.Отчество := 'Иванович';
Чел1.Фамилия := 'Иванов';

Обратите внимание, что свойство Name содержит имя объекта, по которому мы к этому объекту обращаемся. Если бы мы изменили в свойстве Name Чел1 на Человек, то код выглядел бы иначе:

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

Далее, этот объект имеет не только строковые, но и другие типы свойств – переменных. Например, возраст (в годах) и рост (в сантиметрах) – это будут переменные целого типа:

Чел1.Возраст := 30;
Чел1.Рост := 180;

Объект может иметь и символьную переменную, например, свойство Пол (м – мужской, ж – женский):

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

Чел1.Военнообязанный := True; 

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

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

Вернемся к реальным компонентам. Возьмем компонент TEdit. Если мы кинем на форму такой компонент, то Delphi автоматически установит свойство Name равным строке Edit1. В дальнейшем мы будем обращаться к этому объекту по этому имени. Если же мы в Инспекторе объектов изменим свойство Name с Edit1 на, скажем, MyEdit, то обращаться придется уже не к Edit1, а к MyEdit. Предположим, мы изменили это свойство. Не забываем, что свойство Name – переменная типа строка.

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

Еще есть свойства Width (ширина компонента) и Height (высота компонента). Это тоже целые типы, они указывают значение в пикселях.

Также нас интересует свойство Text. Это строковая переменная, она указывает, какой текст отображается в этом компоненте. Мы можем ввести в него текст в Инспекторе объектов, и тогда при работе программы он сразу же будет отображаться в поле ввода. Гораздо чаще его оставляют пустым. В Инспекторе объектов просто очищают это свойство, а программно можно присвоить компоненту пустую строку:

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

В данном примере мы присвоили строковой переменной s тот текст, который в данный момент хранился в поле ввода нашего компонента Edit.

Напомним, что присвоение происходит слева – направо, то есть вначале указывается переменная, которой мы собираемся присвоить значение, затем идет знак присваивания:=“, после чего идет то значение, которое мы присваиваем этой переменной.

Мы имеем возможность программно изменить текст в этом объекте, и в данном случае будем указывать переменную – свойство Text:

MyEdit.Text := 'Новый текст';

Теперь наш объект будет отображать строку с новым текстом. Кроме того, мы программно можем изменять и другие свойства. Например, свойство Left – положение от левой границы формы. Мы можем указать:

MyEdit.Left := MyEdit.Left – 5;

Если мы укажем такой текст, например, в процедуре обработки нажатия кнопки, то каждый раз, когда мы нажимаем на кнопку, объект MyEdit будет сдвигаться влево на 5 пикселей. Попробуйте сами! Создайте новое приложение, установите на форму компонент TEdit и кнопку. Если Вы не изменили свойство Name, то придется обращаться к объекту по имени, которое по умолчанию присвоила ему Delphi:

Edit1.Left := Edit1.Left - 5;

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

Как только Вы нажмете кнопку в первый раз, объект послушно сместится влево, и сразу же за этим поменяет имя. Но попробуйте нажать кнопку еще раз, и программа сразу зависнет – она уже не видит объект с новым именем, ведь в коде обработки кнопки мы по прежнему обращаемся к объекту по старому имени, а объекта с таким именем уже не существует!

Не волнуйтесь, ничего страшного не произошло. Просто выберите в меню команду Run – Program Reset. Это заставит программу досрочно прекратить выполнение и закрыться.

Не забывайте еще вот о чем: не у всех компонентов, которые выводят текст на экран, есть свойство строкового типа Text. Например, у компонента TLabel таким свойством является Caption, и если мы хотим в инспекторе объектов вписать в объект какой-то текст, вписывать его нужно именно в свойство Caption. Точно также, Если мы желаем программно изменить текст в объекте Label1, то делаем присвоение нового текста его свойству Caption:

Label1.Caption := 'Новый текст';

Однако, есть объекты и посложней. Возьмем, к примеру, TMemo. У него нет свойства Text в инспекторе объектов, однако это свойство доступно программно. Переменная – свойство Text объекта Memo1 содержит весь текст, все строки, которые находятся в данный момент в компоненте. Однако гораздо чаще применяют свойство Lines. Это свойство уже не простая строковая переменная, а целый массив строк, где каждый элемент содержит отдельную строку текста. Можно сказать, что Lines – это объект в объекте, который также имеет свои методы, то есть функции и процедуры. Чаще всего используют методы SaveToFile() и LoadFromFile(), которые соответственно, сохраняют текст в файл и читают текст из файла. Свойство Lines имеет тип TStrings, то есть не просто строку, а набор строк.

Многие компоненты имеют свойства такого типа. Например, компонент TListBox имеет свойство Items, которое принадлежит к тому же типу TStrings, следовательно, имеет такие же методы, как и Lines у компонента TMemo. Это значит, что вызвав нужный метод, мы можем, к примеру, считать текст из файла и в Memo, и в ListBox:

Memo1.Lines.LoadFromFile('myfile.txt');
ListBox1.Items.LoadFromFile('myfile.txt');

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

События

События – это процедуры, которые выполняются всякий раз, когда это событие происходит. Например, событие OnChange компонента Edit происходит всякий раз, когда меняется текст в поле ввода. События находятся на вкладке Events Инспектора объектов. Если мы ничего не создадим, то при наступлении этого события ничего и не произойдет. Однако, если мы дважды щелкнем мышью по этому событию – создастся процедура обработки этого события. И тот программный код, который мы введем, будет выполняться всякий раз, когда это событие происходит.

Событие OnChange применяют довольно часто, когда нужно проверить правильные ли данные вводит пользователь. Хорошая новость – большинство событий (а также свойств и методов), у большинства компонентов одинаковы. Например, практически любой компонент для ввода пользователем текста имеет событие OnChange. Применяете ли вы Edit или Memo, это событие работает одинаково.

3. Строки

С этим типом переменных приходится работать довольно часто. В примере выше мы указывали строку ‘Это строка’, а в прошлой лекции имели дело со строкой ‘Hello, world!’. Вы уже заметили, что все строки должны быть заключены в одинарные кавычки. Размер строки практически не ограничен. Вы можете записать в строку любой текстовый файл, все зависит от того, сколько места есть у Вас на диске, и какой объем ОЗУ у Вас установлен.

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

Поместите на форму, один под другим, следующие компоненты:

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

Растяните компонент Edit, сделав его примерно вдвое длинней.

Выделите компонент Label (одним нажатием мыши!), и в его свойстве Caption вместо “Label1” впишите “Как твое имя?”.

Теперь выделите компонент Edit, и удалите “Edit1” из свойства Text, оставив там пустое поле. Свойство Text этого компонента содержит тот текст, который в данный момент находится в поле ввода. Вообще, со свойствами компонента можно обращаться, как с переменными. В большинство свойств можно заносить значения не только в Инспекторе объектов, в момент разработки формы, но и во время выполнения программы.

Выделите кнопку, и в ее свойстве Caption напишите “Нажми меня!”. Для красоты, переместите ее в центр формы.

Измените размер формы, чтобы на ней не было много пустого места. А также в свойстве Caption формы напишите “Приветствие”. Напомним, чтобы выделить форму, нужно один раз щелкнуть мышью по любому свободному месту формы. Если вы все сделали правильно, у вас должна получился такая форма:

Внешний вид формы

Рис. 2.1.  Внешний вид формы

Теперь создадим обработчик события для кнопки. Для этого дважды щелкните по кнопке, которую вы разместили на форме. Сразу же вы попадаете в Редактор кода, и курсор мигает между строками begin и end. Begin – это начало процедуры, после него точка с запятой не ставится. End – конец процедуры, после этого оператора точка с запятой обязательна. Если вы присмотритесь, то в последней строке редактора кода увидите end с точкой – это конец программы. Переменные указываются (описываются) перед началом процедуры. Следовательно, строку begin нужно будет опустить, а перед ней вписать раздел переменных var, и указать переменную s. Процедура должна выглядеть так:

procedure TForm1.Button1Click(Sender: TObject);
var
  s: String;
begin
  s:= 'Привет, ' + Edit1.Text + '!';
  ShowMessage(s);
end;

Обратите внимание, что когда вы поставите точку после названия компонента Edit1, выйдет список доступных свойств, методов и событий. Когда мы впишем первую букву “T”, список сортируется – в нем останутся только команды на букву “T”, причем Delphi оценивает контекст, и оставляет в списке только те команды, которые в этом контексте могут быть использованы. В нашем случае, это строка. Свойство Text, которое останется в списке, может быть использовано в качестве строки:

Выбор свойства из списка – подсказки

Рис. 2.2.  Выбор свойства из списка – подсказки

Теперь нет нужды вводить “Text” самим – это свойство выделено в списке, и нам достаточно нажать <Enter>, чтобы вставить его в код. На будущее запомните: всегда, когда вы ставите точку после названия компонента, дождитесь такого списка. Дело не только в том, что так легче вводить код. Если список так и не появился, значит вы допустили ошибку. Возможно, в названии компонента, или даже в предыдущей строке.

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

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

'Привет, ' + Edit1.Text + '!'

прямо в команде ShowMessage:

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage('Привет, ' + Edit1.Text + '!');
end;

4. Собственный Блокнот

Каждый пользователь, работающий с Windows, хоть раз да использовал простой текстовый редактор Блокнот. Сейчас мы создадим немного упрощенную версию Блокнота, которая позволяет вводить текст, сохранять его на диск, и загружать с диска. Для этого нам требуется создать новый проект. Если в данный момент у вас уже открыт какой либо проект, выберите команду меню “File – Close All (Файл – Закрыть всё)”, затем “File – New – Application (Файл – Новое – Приложение)”.

У нас есть новая форма, и пока больше ничего нет. Сразу изменим некоторые свойства формы. В свойстве Caption впишите “Мой блокнот” (естественно, без кавычек). Свойство Name изменим на “fMain”.

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

  1. Перед названием формы будем указывать маленькую букву f, чтобы показать, что это именно форма.
  2. Имена форм будем подбирать информативные, чтобы было понятно, с какой формой мы имеем дело.
  3. Модули форм будем называть также, но без буквы f.
  4. Главную форму всегда будем называть fMain, а модуль, соответственно, Main.

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

Сохраним проект в отдельную папку. Модуль называем Main, а проекту даем имя MyNotebook.

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

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

Заготовка редактора текстов

Рис. 2.3.  Заготовка редактора текстов

Теперь выделим первую кнопку, и в свойстве Caption этой кнопки напишем “Сохранить”. На второй кнопке напишем “Загрузить”, на третьей – “Очистить”.

Выделим компонент Memo, который представляет собой большое белое поле. У компонента есть одно интересное свойство Lines, которое содержит строки текста, набранного в компоненте. Подробней с этим свойством мы познакомимся позже, а пока выделим его в Инспекторе объектов, нажмем на кнопку с тремя точками справа от свойства и тем самым откроем редактор текста. Здесь можно набрать текст, который будет выведен в компонент “по умолчанию”, при каждой загрузке программы. Нам как раз нужно, чтобы текста никакого не было, поэтому удалите все строки, какие там есть и нажмите “ОК”. Компонент Memo очистился.

Это еще не все. Нам нужно, чтобы при вводе текст автоматически переносился на другую строку, а пользователь имел возможность его пролистывать. Найдите свойство ScrollBars (компонент Memo должен быть выделенным), это свойство отвечает за наличие полос прокрутки. Выберите значение ssVertical, чтобы появилась вертикальная полоса прокрутки.

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

Memo1.Lines.SaveToFile('MyFile.txt');

Метод SaveToFile() свойства Lines компонента Memo сохраняет весь текст в указанный файл. Если вы не указываете путь к файлу, по умолчанию файл будет создан там, откуда была запущена программа.

Для второй кнопки напишем две строки:

  if FileExists('MyFile.txt') then
    Memo1.Lines.LoadFromFile('MyFile.txt');

Разберем эти строки. Что, если пользователь нажмет эту кнопку до того, как что-нибудь сохранит в файл? Файла то еще нет! Первая строка как раз выполняет проверку на существование файла. Если файла нет, то вторая строка выполняться не будет. Если он есть, тогда вторая строка считает текст из этого файла в компонент Memo. С условными операторами мы будем знакомиться позже, тогда смысл первой строки будет понятней.

Для третьей кнопки код еще проще:

Эта команда очищает компонент Memo от текста. Вот, собственно, и вся программа. Сохраните ее и скомпилируйте, проверьте, как она работает. Оцените легкость программирования – для создания полноценного редактора текстов мы написали всего 4 строки кода!

Поэкспериментируйте со свойством Font (Шрифт) компонента Memo, посмотрите, каким образом будет изменяться шрифт текста.

5. Вычисления

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

Откройте Delphi, создайте новый проект. На форму нужно поместить три компонента Label, три компонента Edit и одну кнопку, чтобы получилась такая картина:

Внешний вид формы

Рис. 3.1.  Внешний вид формы

Совет: чтобы выполнить одинаковую операцию над несколькими компонентами сразу, их можно выделить один за другим, удерживая клавишу <Shift>. Например, если таким образом выделить все три компонента Edit, то затем можно разом очистить их свойство Text.

Сохраните проект под именем MyCalc. Затем дважды щелкните по кнопке, чтобы создать обработчик нажатия на кнопку.

Перед begin процедуры следует создать раздел var, и объявить там три переменных:

var
  Perem1, Perem2 : Integer;
  Perem3 : Double;

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

Perem1 := Edit1.Text; //ошибочное присвоение 
                      //– несовместимость типов данных

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

то компьютер видит строку символов, а вовсе не число:

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

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

var
   s: String;
   i: Integer;
begin
   s := '1234';
   i := StrToInt(s); //параметр – строковая переменная
   i := StrToInt(‘123456’); //параметр – строка
   i := StrToInt(Edit1.Text); //параметр – свойство Text 
                              //компонента Edit, имеющее строковый тип
end;

Как видно из примера, имеется масса возможностей передать в функцию строку. В первом случае преобразования мы передаем строковую переменную s, в которой хранится строка ‘1234’. Функция преобразует эту строку в целое число, и в результате в переменную i попадет уже число 1234.

Во втором случае мы передаем непосредственно строку ‘123456’, а в переменную i попадает преобразованное из этой строки число. В третьем случае мы в качестве параметра передаем тот текст, который пользователь ввел в поле ввода Edit1. Здесь следует сделать оговорку. Функция сработает правильно, если пользователь ввел туда действительно целое число. В противном случае возникнет ошибка. Пользователь – личность непредсказуемая, поэтому программист в таких случаях перед преобразованием типов всегда делает проверку – а действительно ли в поле ввода имеются только цифры от 0 до 9? Нет ли там случайно буквы или запятой? Такую проверку мы научимся делать позднее. Пока что придется самим следить, чтобы в этих полях ввода были только целые числа.

Вернемся к программе. Сразу после begin присваиваем целым переменным значения, которые ввел пользователь:

  Perem1 := StrToInt(Edit1.Text);
  Perem2 := StrToInt(Edit2.Text);

В третью, вещественную переменную, мы должны записать результат деления первого числа на второе. Тут может крыться еще один “подводный камень” – что, если во второе поле пользователь ввел число 0? Еще со школы все мы знаем, что на ноль делить нельзя. Если же мы попробуем это сделать, то компьютер, в лучшем случае, зависнет. Здесь опять придется делать проверку на правильность введенных данных, ставить, как говорят, “защиту от дураков”. Подробнее о таких проверках мы поговорим на следующих лекциях, когда изучим условные конструкции. А пока просто наберите этот код:

  {защита от дураков:}
  If Perem2 = 0 then begin                   //если это ноль, то:
    ShowMessage('На ноль делить нельзя!');   //выводит сообщение
    Edit3.Text := '0';                 //как результат записываем ноль
  end
  else begin                            //иначе:
    Perem3 := Perem1 / Perem2;         //делим
    Edit3.Text := FloatToStr(Perem3);  //преобразуем вещественное в 
                                       //строку и записываем результат
  end;

Здесь следует обратить внимание на предпоследнюю строку. Функция FloatToStr() в качестве параметра принимает вещественное число, и возвращает это же число в виде строки. Например, в результате преобразования

переменной s будет присвоена строка ‘123.45’, которую затем уже можно будет вывести пользователю в качестве результата. В нашем примере мы результат деления двух целых чисел преобразуем в строку и выводим его в поле Edit3. Справедливости ради следует заметить, что в качестве параметра можно передавать не только значение, но и выражение. Например, если указать

Edit3.Text := FloatToStr(Perem1 / Perem2);

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

6. Свойства формы

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

BorderIcons – свойство определяет, какие кнопки должны быть у полученного окна. Имеет только 4 значения, каждое из которых может быть True, то есть кнопка есть, и False, то есть, ее нет.

  • BiSystemMenu определяет, будет ли у формы системное меню, которое показано в виде иконки слева на заголовке окна. Кроме того, будут ли там другие кнопки заголовка.
  • BiMinimize определяет кнопку минимизации (сворачивания) окна. При этом False не убирает саму кнопку, а только делает ее неактивной.
  • BiMaximize точно также определяет кнопку разворачивания окна.
  • BiHelp – кнопка помощи в виде вопросительного знака. Не покажется у обычного вида формы, даже если поставить в True.

BorderStyle – свойство формы, определяет ее общий вид. Может быть:

  • BsSizeable – обычное окно. Установлено по умолчанию. Стандартное окно, которое может менять размеры.
  • BsDialog – окно в форме диалога, имеет только кнопку “закрыть”.
  • BsNone – окно вообще без оборки и без заголовка окна.
  • BsSingle – отличается от обычного окна тем, что у него нельзя изменить размеры.
  • BsSizeToolWin – окно с тонкой оборкой. Особенно это заметно у заголовка окна.
  • BsToolWindow – такое же, как предыдущее, но у этого окна нельзя менять размеры.

BorderWidth – ширина оборки окна. По умолчанию установлен 0.

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

Cursor – вид указателя мыши. Вы выбираете, как будет выглядеть указатель при наведении на форму.

Font – выбор шрифта по умолчанию. Другими словами, если Вы измените шрифт, то все компоненты, устанавливаемые на форму, по умолчанию примут его.

Height – высота окна. Обратите внимание, что когда вы мышью изменяете размер окна, это свойство автоматически меняет значение.

Icon – иконка в заголовке окна. Если дважды щелкнуть по этому свойству, выйдет окно загрузки другой иконки. По умолчанию установлена стандартная иконка Delphi 7, но можно сделать и свою собственную. Чаще всего используют коллекции иконок, скачанных из интернета. Но если Вы чувствуете в себе талант художника, можете попробовать сделать иконку для своего проекта самостоятельно. Для этого используйте встроенную утилиту Image Editor, ярлык которой находится там же, где Delphi. Выберите команду “File – New – Icon file”, и рисуйте на здоровье!

Name – имя компонента формы. Это свойство вместе со свойством Caption мы уже рассматривали, так что просто вспомним, что Name главной формы желательно всегда указывать одинаково, например, fMain.

Position – расположение окна. Довольно важное свойство! Оно имеет несколько значений:

  • PoDefault – Windows сам будет решать, где расположить Ваше окно на экране, и какие у него будут размеры.
  • PoDefaultPosOnly – Windows решает, где будет окно, а размеры его будут такими же, как Вы их установили.
  • PoDefaultSizeOnly – позиция остается, как Вы указали, но Windows решает, какие у окна будут размеры.
  • PoDesigned – это значение по умолчанию. И позиция, и размеры остаются такими, как Вы их создали.
  • PoDesktopCenter – выбирайте этот вариант, если желаете, чтобы окно всегда выходило по центру рабочего стола.
  • PoMainFormCenter – это значение используют для дочерних окон, о которых речь будет впереди. Если у дочернего окна выбран этот вариант, то оно всегда будет появляться по центру главной формы.
  • PoOwnerFormCenter – это значение заставит дочернее окно появляться по центру того окна, из которого оно вызвано.
  • PoScreenCenter – окно появляется по центру экрана. Почти то же самое, что и PoDesktopCenter.

Width – ширина окна. Как и высота, это свойство меняет свое значение, когда Вы меняете размер формы.

WindowState – состояние окна после запуска. Имеет три значения:

  • WsNormal – по умолчанию. Окно показывается в нормальном состоянии.
  • WsMaximized – окно появляется в развернутом виде.
  • WsMinimized – окно появляется в свернутом виде.

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

7. Свойства кнопки TButton

Здесь мы разберем только основные свойства кнопки, которые нам пригодятся для работы, и которых мы еще не знаем. Большинство свойств мы уже знаем. Свойство ModalResult мы будем разбирать позднее, когда будем работать с модальными окнами. Сейчас обращу Ваше внимание только на три свойства.

Name – это свойство нам вполне знакомо, оно указывает имя этого компонента. Обычно мы изменяли Name только у формы, но в дальнейшем приучайтесь изменять его у всех компонентов. Когда у Вас будут сложные формы со множеством кнопок, очень сложно будет определить в редакторе кода, что делает кнопка Button1 или Button12. Поэтому будет лучше, если Вы приучитесь давать кнопкам осмысленные названия. К примеру, в редакторе текстов мы устанавливали 3 кнопки: Загрузить, Сохранить и Очистить. Следовательно, было бы правильным изменить имена кнопок на bLoad, bSave и bClear. Первая буква b подскажет нам, что это кнопка, а название после этой буквы скажет, что кнопка должна делать. Приучайтесь сразу к хорошему стилю программирования, если не хотите иметь неряшливый код, в котором легко запутаться. Если Вам не нравятся правила, что форму мы начинаем с буквы f, а кнопку с буквы b – придумайте свои правила, но в дальнейшем всегда придерживайтесь их!

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

Top – это положение кнопки от верхней границы формы. Работает также, как Left, но двигает кнопку по вертикали.

Шуточная программа

Теперь мы можем написать шуточную программу с формой и кнопкой, где пользователь ни за что на свете не сможет нажать на кнопку мышью, потому что кнопка будет убегать от указателя мыши. Эта простая программа была описана в одном из номеров журнала “Хакер”. Она как нельзя лучше показывает, каким образом можно программным способом менять свойства. Как кнопка будет убегать? С помощью программного изменения свойств Left и Top! Однако, чтобы понять код программы от начала до конца, познакомимся с новой функцией. Функция Random() возвращает случайное число. Эту функцию еще называют генератором случайных чисел. Синтаксис функции очень простой:

Random( Integer ) : Integer;

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

Random(5) будет возвращать в случайном порядке числа от 0 до 4 включительно. То есть, возвращаемое значение будет:

0 <= возвращаемое_значение < исходное_число.

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

Создайте форму среднего размера и бросьте на нее только одну кнопку. Для большего эффекта в свойстве Caption формы напишите: “Выиграй приз!”. А на кнопке напишите “Нажми меня”.

Какой бы быстрой ни была реакция пользователя, она никак не сравниться со скоростью, с какой процессор обрабатывает инструкции. А процессор обрабатывает миллионы инструкций в секунду! Поэтому пользователь никогда не сможет нажать на кнопку мышью, но сможет это сделать с помощью клавиши <Enter> на клавиатуре. Учтем это. Создадим обработчик нажатия кнопки и там напишем только одну строку:

ShowMessage('Enter нажимать нечестно, пользуйся мышкой!');

Теперь осталось написать код убегания мыши. В инспекторе объектов откройте вкладку Events (события). Нас интересует событие OnMouseMove, которое происходит всякий раз, когда указатель мыши оказывается над кнопкой. Щелкните дважды по событию, и в редакторе кода введите следующее:

procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  index : Integer;
begin
  index := random(4); //присваиваем переменной случайное значение от 0 до 3

//в зависимости от значения переменной, выбираем действие
case index of
  0: Button1.Left := Button1.Left + Button1.Width; //двигаем кнопку вправо, на значение ширины кнопки
  1: Button1.Left := Button1.Left - Button1.Width; //кнопка влево, на значение ширины
  2: Button1.Top := Button1.Top + Button1.Height; //кнопка вниз, на значение высоты
  3: Button1.Top := Button1.Top - Button1.Height; //кнопка вверх, на значение высоты
end; //case

  {Если кнопка вышла за пределы формы, вернем ее в положение 0}
  if Button1.Left < 0 then Button1.Left := 0; 
  if Button1.Top < 0 then Button1.Top := 0; 

  if (Button1.Left + Button1.Width) > Form1.Width then
    Button1.Left := Form1.Width - Button1.Width;

  if (Button1.Top + Button1.Height) > Form1.Height then
    Button1.Top := Form1.Height - Button1.Height;

end;

Разберем этот код. В самом начале в переменную index мы записываем случайное число, от 0 до 3. Это нам нужно, чтобы знать, куда двигать кнопку, ведь двигать ее можно влево, вправо, вверх или вниз. В зависимости от того, какое значение мы получили, программа выберет направление перемещения кнопки. Для этого используется конструкция case. Если в переменной у нас число 0, то кнопка будет двигаться вправо. Как это происходит? Свойству Left (левая позиция) кнопки мы присваиваем новое значение – левую позицию этой же кнопки, плюс ее ширину. Другими словами, кнопка сдвинется вправо на расстояние, равное ширине этой кнопки. Таким же образом мы сдвигаем кнопку влево, если переменной index будет присвоено число 1. Только здесь мы не прибавляем, а отнимаем ширину.

Почти таким же образом кнопка убегает вверх или вниз, но здесь мы используем другие свойства – Top (расстояние от верхней границы окна до кнопки) и Height (высота кнопки в пикселях). Соответственно, если мы прибавляем высоту к верхней границе, кнопка убегает вниз, и наоборот.

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

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

Точно также проверяем, не вышла ли кнопка за нижнюю границу окна.

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

8. Изучаем компоненты Panel, GroupBox, RadioGroup, CheckBox

Здесь вы познакомитесь с панелями Panel, GroupBox и RadioGroup, научитесь пользоваться “флажком” CheckBox и радиокнопками. В процессе изучения лекции создадите полезную утилиту.

Компонент Panel (Панель)

Компонент Panel находится на вкладке Standard и применяется для улучшения внешнего вида формы, а также для группировки нескольких компонентов. Этот компонент по своим свойствам немного напоминает форму. Если установить несколько других компонентов на Panel, то при смещении панели будут смещаться и компоненты, установленные на ней.

Изучим этот компонент на практике. Создайте новый проект, и установите на форму один компонент Panel. По умолчанию, свойству Caption панели присваивается то же имя, что и свойству Name, то есть прямо по центру панели выходит текст “Panel1”. Нас это не устраивает. Очистим свойство Caption панели – просто удалите этот текст, ничего туда не вписывая.

Разберем другие полезные свойства этого компонента. Свойства семейства Bevel отвечают за внешний вид компонента:

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

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

Еще одно очень важное свойство – Align (Выравнивание). Это свойство часто используют не только у панелей, но и у многих других компонентов. Align имеет несколько значений:

  • AlBottom – указывает, что панель будет занимать весь низ формы. Когда размеры формы меняются, меняется и размер панели, но она по-прежнему занимает весь низ.
  • AlClient – указывает, что панель занимает все пространство формы. Если вы установили панель, и растянули ее по всему верху, а затем установили еще одну панель и указали значение alClient, то вторая панель займет все оставшееся место.
  • AlCustom – указывает пользовательские настройки. При изменении размеров формы такая панель останется, как при разработке дизайна.
  • AlLeft – занимает всю левую часть формы.
  • AlNone – выравнивания нет. Работает практически как AlCustom.
  • AlRight – занимает всю правую часть формы.
  • AlTop – панель вытягивается по всей верхней части формы.

Ранее мы создавали простой редактор текстов. Улучшим этот пример. Укажите у свойства Height (высота) панели значение 40. Свойство Top установите в 0. Тем самым мы прижали панель к самому верху формы. Свойству Align присваиваем значение alTop, растягивая панель по всему верхнему краю. Теперь, если пользователь станет менять размеры формы, сжимая окно или наоборот, растягивая, панель все равно будет занимать весь верх. Устанавливая на эту панель кнопки, мы получим типичную панель инструментов. Так и сделаем: установите на панель три кнопки, одну рядом с другой. На кнопках должен быть текст: “Сохранить”, “Загрузить” и “Очистить”.

На оставшееся внизу место помещаем компонент Memo, дважды щелкаем по свойству Lines, чтобы вызвать редактор текста, и удаляем из Memo весь текст. Свойству Align компонента Memo присвоим значение alClient, чтобы растянуть Memo по всему оставшемуся месту. Вот и все, мы имеем панель инструментов и рабочую область редактора текстов. Сохраните проект, скомпилируйте его и посмотрите, как меняются размеры панели и Memo при изменении размера окна. Запрограммировать кнопки вы сможете самостоятельно, используя пример из второй лекции.

Компоненты GroupBox и CheckBox

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

Создайте новое приложение. Мы сделаем полезную утилиту, меняющую вид формы в зависимости от настроек. На форму установите компонент GroupBox, присвоив его свойствам Left и Top значение 6, чтобы прижать его к верхнему левому краю окна. В свойстве Caption этого компонента напишите текст “BorderIcons”. Поскольку обрамление компонента вплотную подходит к тексту – заголовку, с дизайнерской точки зрения будет нелишним добавить пару пробелов перед текстом, и столько же после него.

Мы уже знаем, что BorderIcons – это свойство формы, программирующее ее внешний вид. Это свойство имеет 4 значения, каждое из которых можно включить, либо выключить. Таким образом, нам нужно 4 классических “флажка”, в которые можно будет поставить “галочку” или убрать ее. Роль таких флажков выполняет компонент CheckBox. Установите 4 CheckBox прямо на панель GroupBox, один над другим:

Внешний вид приложения

Рис. 7.1.  Внешний вид приложения

Измените свойство Caption этих компонентов, написав там, соответственно, “biSystemMenu”, “biMinimize”, “biMaximize” и “biHelp”. Свойство Checked компонента CheckBox показывает включен ли компонент, другими словами, установлена ли в нем “галочка”. У формы по умолчанию первые три значения включены, также сделаем и здесь – у первых трех компонентов CheckBox установите свойство Checked в True.

Компонент RadioGroup

Этот компонент также имеет вид панели и предназначен для группировки так называемых радиокнопок. Включенной может быть лишь одна такая радиокнопка. На рисунке 7.1 в правой части формы вы видите такую панель с установленными радиокнопками. Добавьте компонент RadioGroup на форму, в свойстве Caption установите текст “BorderStyle”, не забывая про пробелы до и после текста. Устанавливать на этой панели радиокнопки значительно легче, чем кнопки CheckBox. Выделите эту панель и дважды щелкните по ее свойству Items. Откроется редактор текста, такой же, как у Memo. В этом редакторе нужно написать названия кнопок, каждую кнопку обязательно нужно писать на отдельной строке. Напишите следующие кнопки:

bsSizeable
bsDialog
bsNone
bsSingle
bsSizeToolWin
bsToolWindow

Как только вы нажмете “ОК” и закроете редактор, на панели RadioGroup появятся описанные кнопки. Ни одна из них не имеет включенного вида. Мы уже знаем, что можно включить только одну такую кнопку из списка. Компонент RadioGroup имеет свойство ItemIndex, которое указывает, какая кнопка в данный момент включена. По умолчанию, ItemIndex равен -1. Поскольку нумерация кнопок начинается с нуля, значение -1 означает, что ни одна кнопка не включена. Установите значение 0, включив тем самым первую кнопку (на форме одноименное свойство включено по умолчанию).

Ниже установите кнопку, написав на ней слово “Применить”. Все, с дизайном окончено, переходим к программированию кнопки. Если вы еще не сохранили проект в новую папку, сделайте это сейчас. Свойству Name формы, как обычно, дайте имя fMain, модулю – просто Main, всему проекту в целом – FormViewer.

Вернемся к кнопке. Щелкните дважды по ней, создав процедуру обработки нажатия кнопки.

Процедура имеет следующий вид:

procedure TfMain.Button1Click(Sender: TObject);
begin
  //обрабатываем компонент BorderIcons
  if CheckBox1.Checked then fMain.BorderIcons := fMain.BorderIcons + [biSystemMenu]
  else fMain.BorderIcons := fMain.BorderIcons - [biSystemMenu];

  if CheckBox2.Checked then fMain.BorderIcons := fMain.BorderIcons + [biMinimize]
  else fMain.BorderIcons := fMain.BorderIcons - [biMinimize];

  if CheckBox3.Checked then fMain.BorderIcons := fMain.BorderIcons + [biMaximize]
  else fMain.BorderIcons := fMain.BorderIcons - [biMaximize];

  if CheckBox4.Checked then fMain.BorderIcons := fMain.BorderIcons + [biHelp]
  else fMain.BorderIcons := fMain.BorderIcons - [biHelp];

  //обрабатываем компонент BorderStyle
  case RadioGroup1.ItemIndex of
    0 : fMain.BorderStyle := bsSizeable;
    1 : fMain.BorderStyle := bsDialog;
    2 : fMain.BorderStyle := bsNone;
    3 : fMain.BorderStyle := bsSingle;
    4 : fMain.BorderStyle := bsSizeToolWin;
    5 : fMain.BorderStyle := bsToolWindow;
  end; //case

end;

Разберемся с кодом. Вначале мы обрабатываем первый флажок CheckBox:

  if CheckBox1.Checked then fMain.BorderIcons := fMain.BorderIcons + [biSystemMenu]
  else fMain.BorderIcons := fMain.BorderIcons - [biSystemMenu];

Если этот флажок включен, его свойство Checked вернет Истину, и тогда к свойству формы BorderIcons будет добавлена константа [biSystemMenu]. О константах, в том числе и встроенных, мы будем говорить позднее. Пока что важно одно – если мы прибавляем эту константу, то включаем это значение в свойство BorderIcons.

Пример взят из встроенного справочника Delphi. Поставьте мигающий курсор внутри слова BorderIcons и нажмите <Ctrl + F1>. Выйдет контекстный справочник с этой командой. Если вам будет предложено выбрать между CLX и VCL, выбирайте последнюю (Visual Components Library – Библиотека визуальных компонентов). Далее щелкните по ссылке “Delphi example” (Пример для Delphi). В показанном в справке примере отключается кнопка “Развернуть окно”.

Таким же образом, мы обрабатываем остальные три компонента CheckBox.

Далее, идет обработка панели RadioGroup. Поскольку только одна кнопка может быть включена, то свойство ItemIndex этой панели может иметь только 6 значений, по количеству кнопок: от 0 до 5. Здесь удобней всего использовать конструкцию case. В зависимости от значения ItemIndex мы присваиваем одноименное включенной кнопке значение свойству BorderStyle формы. Вот и все.

Сохраните пример, скомпилируйте и посмотрите, как работает программа. В зависимости от выбранных значений после нажатия кнопки “Применить” меняется внешний вид формы. В некоторых случаях ее размеры можно менять, раздвигая мышью, в некоторых – нет. В случае, если BorderStyle равен значению bsNone, пропадает и оборка окна, и верхняя системная строка формы. Поэкспериментируйте. Эта утилита может оказаться полезной в дальнейшем, если вы желаете заранее посмотреть, какие настройки выбрать, чтобы окно вашей программы выглядело именно так. Например, чтобы нельзя было менять его размеры, чтобы отсутствовали кнопки “Свернуть” и “Развернуть” и т.п.

9. Свойства Enabled и Visible

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

Откройте проект с редактором текста из прошлой лекции. У вас там есть три кнопки – “Сохранить”, “Загрузить” и “Очистить”. Давайте предположим, что пользователь набрал какой-то важный текст и сохранил его. На следующий день он снова загрузил ваш редактор, но по ошибке вместо кнопки “Загрузить” он нажал кнопку “Сохранить”. Что произойдет? Никакого текста в данный момент компонент Memo не содержит. Если будет выполнена команда

Memo1.Lines.SaveToFile('MyFile.txt');

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

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

Свойство Enabled отвечает за доступность компонентов. Это свойство имеет логический тип, и может быть либо True, либо False. Выделите кнопку с надписью “Сохранить”, найдите ее свойство Enabled и вместо установленного по умолчанию значения True, выберите значение False. На форме не произошло видимых изменений, мы не сможем их увидеть в режиме разработки программы. Однако сохраните проект, скомпилируйте командой Run и посмотрите на результат – кнопка “Сохранить” видна на форме, но ее надпись выходит серым, неактивным цветом, а на кнопку невозможно нажать. Теперь у пользователя нет возможности нажать на эту кнопку, значит, он не совершит такой ошибки.

Но это только полдела, надо все-таки в процессе работы программы ему эту возможность вернуть, иначе как же он сможет сохранить текст?

Выше мы обсуждали событие OnChange, которое происходит всякий раз, когда компонент изменяется. Этим мы и воспользуемся. Выделите компонент Memo, в Инспекторе объектов перейдите на вкладку Events (События) и найдите там событие OnChange. Дважды щелкните по нему, чтобы сгенерировать процедуру – обработчик этого события. В этой процедуре запишем всего только одну строку:

Таким образом, при изменении компонента Memo (пользователь изменил текст), мы делаем доступной кнопку “Сохранить”. Теперь пользователь может сохранить свои изменения.

Подумаем теперь вот о чем: когда пользователь сохранил текст, следует ли оставлять кнопку “Сохранить” доступной? Очевидно, нет, если у текста не произошли изменения. Поэтому щелкайте дважды по кнопке “Сохранить”, и после строки, где текст сохраняется, добавьте строку

Button1.Enabled := False;

Сразу, как только текст будет сохранен, кнопка “Сохранить” снова станет недоступной, пока пользователь не произведет очередных изменений в тексте.

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

Свойство Visible компонентов работает практически также, как свойство Enabled, только вместо того, чтобы делать компонент недоступным, оно делает его невидимым. Visible также имеет логический тип, и может быть либо True (компонент видим), либо False (невидим). Самостоятельно измените все приведенные выше рекомендации, использовав вместо свойства Enabled свойство Visible. Посмотрите на результат. Скрывать или отключать можно не только кнопки, но и вообще все видимые компоненты – редактор Memo, поле Edit, надпись Label. Даже у формы есть эти свойства, поэтому при некоторой фантазии вы можете добиваться вполне профессиональных эффектов.

10. Главное меню

Любая более-менее серьезная программа имеет собственное меню. Пришла пора познакомиться с этим компонентом. Для примера снова загрузим наш редактор текстов. Выделите все кнопки на форме и удалите их. Также удалите и панель, на которой эти кнопки были. Затем нам потребуется удалить все процедуры обработки этих кнопок, но тут нужно проявить осторожность – нельзя просто взять, и удалить процедуру. Каждая сгенерированная процедура прописана в коде и выше. Чтобы без ошибок удалить все ненужные последние процедуры, следует просто удалить из них тот код, который мы писали сами, оставив “пустую” процедуру – имя процедуры и строчки begin.. end :

Удаление ненужных процедур

Рис. 8.1.  Удаление ненужных процедур

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

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

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

На вкладке Standard найдите компонент MainMenu (главное меню), и установите его на любое место формы, прямо на компонент Memo. Компонент MainMenu не визуальный, то есть, пользователь все равно не будет его видеть.

Будем создавать меню. Дважды щелкните по MainMenu, чтобы вызвать редактор меню. Когда редактор откроется, вы увидите, что первый пункт меню выделен синим цветом. Пусть выделение остается, перейдите на свойство Caption и введите текст “Файл”. Нажав <Enter>, вы сформируете в меню команду “Файл”, а выделение переместится направо, к следующей команде. Другой пункт меню мы пока делать не будем, щелкните мышью немного ниже команды “Файл”, чтобы выделить пункт ниже. Получается, что мы сделали пункт меню “Файл”, и сейчас делаем подменю этого пункта. Нам потребуются следующие команды:

  • “Сохранить”
  • “Загрузить”
  • “Очистить”
  • “-“
  • “Выход”

Внешний вид редактора главного меню

Рис. 8.2.  Внешний вид редактора главного меню

Предпоследняя команда, знак “-” (минус), формирует в меню разделительную полосу. Как только вы закроете редактор меню, строка с главным меню сейчас же появится над компонентом Memo. Щелкните один раз по слову “Файл”, и откроется подменю. Щелкните по команде “Сохранить”, и будет создана процедура обработки этой команды. Команда “Сохранить” по-прежнему выглядит, как

Memo1.Lines.SaveToFile('MyFile.txt');

Все остальные команды введите аналогичным образом. Команда “Выход” выглядит так:

Close;  //выход из программы

11. Всплывающее меню

Всплывающее меню вызывается, когда пользователь щелкает правой кнопкой мыши по объекту – форме или какому либо другому компоненту. Найдите на вкладке Standard компонент PopupMenu (всплывающее меню), и также установите его поверх компонента Memo. Редактор этого меню вызывается таким же образом, как и редактор главного меню. Во всплывающем меню, однако, только одна ветка меню, где команды указываются одна под другой. Другими словами, нет возможности делать пункты меню (Файл, Правка, Вид и т.д.) и подпункты (Файл -> Создать, Файл -> Загрузить и т.д.).

Создайте следующие команды:

  • “Сохранить”
  • “Загрузить”
  • “Очистить”
  • “-“
  • “Выход”

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

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

Теперь всплывающее меню нужно привязать к форме, само по себе оно работать не будет. Для этого нам нужно выделить форму, что является непростой задачей – компонент Memo растянут на все окно, и нет возможности щелкнуть по свободному месту формы. Форму проще всего выделить в окне Дерева объектов (Object TreeView). Если у вас в данный момент это окно закрыто, открыть его можно командой меню View->Object TreeView , или горячими клавишами <Shift+Alt+F11>. В этом окне легко можно выделить любой компонент, в том числе и форму.

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

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

12. Модальные окна

Модальным называется дочернее окно, которое не дает главной форме работать, пока не закончена работа этого модального окна.

До сих пор мы делали проекты только с одной формой. Настало время изучить многооконные проекты. Воспользуемся предыдущим примером – редактором текстов. Откройте этот проект, если он закрыт.

Чтобы создать новое окно, выберите команду “File – New – Form”.

В свойстве Caption новой формы напишите “О программе”, форму назовите fAbout и сохраните проект. Модуль новой формы, соответственно, назовите About.

На форму установите компонент Label, напишите в его свойстве Caption “Программа: MyNotebook v 1.0”

Ниже установите еще один Label. Свойство AutoSize (автоматическое изменение размера) поставьте в False, а свойство WordWrap (перенос слов на другую строку) – в True. Здесь напишите такой текст:

Программа предназначена для простого редактирования текстов. Программа позволяет сохранять текст в файл, и считывать его из файла. Файл создается там же, откуда запущена программа, и имеет имя MyFile.txt.

Ниже установим еще один Label. Пишем в нем: “Автор: такой-то”, можете указать свои собственные фамилию, имя и отчество. Будет красиво, если текст этого компонента выйдет посередине. Чтобы добиться этого, свойство AutoSize (автоматическое изменение размера) установите в False, свойство Aligment (выравнивание текста) в taCenter.

Ниже устанавливаем кнопку. Пишем на ней “ОК” и создаем обработчик кнопки для выхода из формы.

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

Внешний вид формы "О программе"

Рис. 8.3.  Внешний вид формы “О программе”

Можете “поиграть” со свойствами Font и Color компонентов, чтобы форма выглядела красивей.

Подобные окна не имеют кнопок “Свернуть” и “Развернуть”, поэтому в свойстве BorderStyle формы fAbout выберите значение bsDialog. А в свойстве Position (Позиция формы при ее открытии) выберите poMainFormCenter, чтобы форма появлялась по центру главного окна. Обратите внимание на последнее свойство. Обычно для главных окон программы это свойство устанавливают в poDesktopCenter, чтобы форма появлялась по центру рабочего стола, запомните это на будущее.

Теперь, чтобы можно было вызывать это окно модально, нужно “привязать” его к главной форме. Сейчас в редакторе кодов имеется две вкладки – Main и About, это модули главной формы и формы “О программе”. Перейдите на вкладку главного окна и нажмите <F12>, чтобы вызвать это окно. Выберите команду “File – Use Unit”. Откроется окно, где мы увидим нашу модальную форму. Выделите ее и нажмите OK. Теперь, если Вы посмотрите код главной формы, под разделом implementation Вы увидите такую картину:

implementation
uses About;

Delphi вставила инструкцию, при которой главная форма использует все, что описано в коде модального окна. Можно было набрать все это вручную, однако во избежание ошибок рекомендуется пользоваться командой “File – Use Unit”. Тогда код точно будет введен без ошибок, и именно в то место, которое нужно.

Теперь в главной форме снова откройте редактор главного меню, дважды щелкнув по компоненту MainMenu. Выделите пункт справа от “Файл”, и в свойстве Caption напишите “Справка”. А в пункте ниже напишите “О программе”:

Редактор главного меню

Рис. 8.4.  Редактор главного меню

При разработке меню не забывайте о стандартах, принятых в Windows. Никто не запрещает Вам засунуть подраздел “О программе” в Пункт “Файл” или какой-нибудь другой. Однако пользователь будет искать его именно в разделе “Справка”. Не заставляйте пользователя привыкать к другим стандартам, если хотите, чтобы ваши программы пользовались спросом!

Теперь нужно написать код вызова модального окна. Дважды щелкните по подразделу меню “О программе”, чтобы создать процедуру обработки этого подраздела. Там введите инструкцию:

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

Сохраните проект, скомпилируйте программу и посмотрите результат.

Форма About средствами Delphi

Форму About вовсе не обязательно разрабатывать самостоятельно, Delphi уже предоставляет нам такую форму. Нужно будет лишь изменить текст, и при необходимости, картинку.

В предыдущем проекте, где мы выводили случайные числа, создайте главное меню. В этом меню создайте пункты “Файл – Выход” и “Справка – О программе”.

Выберите команду “File – New – Other”. Откроется окно репозитария, своеобразной коллекции шаблонов и мастеров для создания нужного окна. Это окно имеет множество вкладок, в которых окна и шаблоны разбиты по тематикам. Перейдем на вкладку Forms и выберем шаблон “About box”. Сразу же переименуем форму в fName, а свойству Caption новой формы присвоим текст “О программе”. Форма имеет вполне законченный дизайн, осталось только вписать нужный текст в компоненты Label и при необходимости, сменить картинку.

В первой label напишем: “Product Name: RandomNums”. Во второй: “Version: 1.0”. Имейте в виду, что в мировом сообществе принято давать номера версий программ от 1.0 и выше. Если в следующей версии произошли незначительные изменения, назовите версию 1.1, потом 1.2 и так далее. Иногда даже указывают три цифры: 1.0.1, 1.0.2 и выше, решать вам. Если изменения значительные, практически у вас получилась другая программа, тогда называйте версию 2.0.

В третьей Label напишите “Copyright: свое ФИО”. Этот раздел указывает, кто имеет авторское право на продукт. В четвертой Label находится раздел Comments. Здесь нужно очень коротко и по существу написать, что делает ваша программа, для чего она предназначена. Вы можете перевести все на русский язык. Вместо “Product Name” напишите “Программа”. “Version” замените на “Версия”. “Comments” замените на “Комментарии”. А вот слово “Copyright” переводить не нужно, именно таким образом принято указывать авторское право в мировом сообществе.

Если вы сделали форму до конца, сохраните ее и пропишите в раздел uses главной формы. Далее в меню главной формы щелкните дважды по подразделу “О программе” и создайте там обработчик вызова новой формы.

13. Структура проекта

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

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

Модуль

Проект в Delphi представляет собой набор программных единиц – модулей. Модуль на английском языке называется Unit. Когда мы разрабатываем форму, мы одновременно обрабатываем модуль этой формы. Модуль – это файл с расширением *.pas. Это расширение – сокращение от языка программирования Pascal, на котором строилась Delphi. Иначе говоря, модуль – исходный код программы, или исходник. Как только мы создаем новую форму, сразу же создается и модуль для нее. Delphi заполняет этот модуль необходимым кодом, а нам остается создавать код для обработки кнопок и различных событий.

Давайте на примере уже рабочей программы посмотрим, из чего состоит проект. Откройте проект MyNotebook. Перейдите на редактор кода.

На самом верху вы видите строку

Unit – это зарезервированное слово, обозначающее Модуль формы. Зарезервированными называются служебные слова, которые уже имеют собственные названия в компиляторе, и такие названия нельзя давать переменным, константам, массивам, компонентам, функциям или процедурам. Зарезервированные слова в коде всегда выделяются жирным шрифтом, вы можете это видеть на примере таких слов, как unit, interface, uses, begin или end, и так далее:

Фрагмент редактора кода

Рис. 11.1.  Фрагмент редактора кода

Когда мы создавали форму, то сразу дали ей имя (свойство Name) fMain. А когда сохраняли проект, Delphi прежде всего запросила имя для модуля формы. Мы назвали модуль также как форму, но без начальной буквы fMain. Вот почему наверху кода unit (Модуль) этой формы имеет имя Main. Теперь вы понимаете, как важно соблюдать правила наименования форм и модулей? Когда в проекте будет много форм, то и модулей будет много, и если вы не будете соблюдать эти правила, то запросто запутаетесь в названиях. И также важно давать формам и модулям осмысленные имена. В сложных проектах таких форм и модулей может быть сотни!

Но вернемся к проекту MyNotebook. Взгляните на код. Далее идет служебное слово interface. Эта директива сообщает компилятору, что начинается раздел интерфейса. В этом разделе, прежде всего, указываются модули, подключенные к данному модулю. Они описываются после служебного слова uses. Когда мы вводим какую-либо функцию или процедуру, мы не задумываемся, откуда она берется. А эта функция описана в одном из подключенных модулей! Давайте в этом убедимся. Спустите курсор в нижнюю часть модуля. Последней у нас описана процедура вызова модального окна fAbout. Ниже этого вызова введите строку:

Она тут совершенно не нужна, и потом мы ее удалим. А пока что установите курсор внутри самого слова ShowMessage, и нажмите <Ctrl>+<F1>. Тем самым, вы вызываете контекстную подсказку именно об этой команде. И в самом начале справки вы видите указание, в каком модуле описана данная процедура:

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

Кстати, количество подключенных к форме модулей объясняет, почему, казалось бы, небольшой проект имеет достаточно большой размер *.exe файла. Ведь подключенные модули содержат множество описаний функций и процедур, и даже если мы их не используем, они все равно доступны. Однако беспокоиться по этому поводу не стоит – нам едва ли придется писать программы, для которых критичен размер исполняемого файла. Это, как правило, драйверы или вирусы, и хотя на Delphi можно написать и то, и другое, для этих задач больше подходит чистый С. А если вы будете использовать Borland C++ Builder или Microsoft C++ Visual, то и они имеют множество подключенных модулей, и размер даже маленькой программки окажется большим.

Вернемся к нашему коду. Далее идет служебное слово type, которое описывает форму – какие в ней находятся компоненты, как они называются, и какие процедуры используются. В этом блоке вы видите разделы:

private
    { Private declarations }
  public
    { Public declarations }

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

Далее идет описание глобальных записей, констант и переменных. Здесь у нас есть только одна глобальная переменная:

Это – форма. Да, да, не удивляйтесь, форма – это переменная типа TForm. Точнее, не просто переменная, а объект со своими свойствами, событиями и методами.

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

В этом разделе глобальных переменных мы можем создать собственную переменную:

var
  fMain: TfMain;
  adres: String; //для адреса, откуда запущена программа

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

adres := ExtractFilePath(Application.ExeName);

Переменную adres в процедуре описывать не нужно – она глобальная, и мы ее уже описали. Функция Application.ExeName вернет полное имя файла нашей программы, а функция ExtractFilePath() вычленит из этого имени адрес, и вернет его. В дальнейшем, в любой процедуре или функции модуля, где будет необходимо обратиться к файлу, например, myparam.ini, который находится там же, откуда запущена программа, достаточно указать:

... adres + 'myparam.ini' ...

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

Далее идет раздел implementation. Это раздел реализации. Он содержит сами процедуры и функции, которые поддерживают работу этой формы. Кроме того, в этом разделе также может присутствовать директива uses, в которой объявлены модули, подключенные к данной форме. Данный раздел необязателен – если в вашем проекте только одна форма, то раздела не будет вовсе. Если есть еще одна форма, как в нашем примере – форма fAbout, модуль которой называется About, то этот раздел добавляется автоматически, как только вы воспользуетесь командой File -> Use Unit. Сразу под ключевым словом implementation у нас есть строка

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

Далее вы видите такую строку, выделенную зеленым цветом:

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

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

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

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

Обратите внимание, что слова begin перед ней нет, и быть не должно! Это – единственное исключение из правила скобок begin..end. Собственно, это даже не исключение, потому что эта end не является закрывающей скобкой, это завершение модуля.

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

Файлы проекта

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

Таблица 11.1. Описание файлов проекта

Расширение Описание файла
*.cfg Этот файл содержит конфигурацию всего проекта, поэтому он один, и имеет имя, как у проекта. Редактировать этот файл вручную не стоит, если не хотите испортить проект.
*.dof Этот файл содержит опции проекта – настройки, версию Delphi, версию проекта, используемые модули и многое другое. Редактировать этот файл вручную нельзя.
*.dpr Это сам проект. Это текстовый файл с описанием используемых форм и модулей, а также процедура инициализации программы. Редактировать такой файл вручную можно, но только опытным программистам, которые точно знают, что они делают, и для чего это нужно. Даже им это бывает необходимо очень редко, поэтому лучше файл не трогать. Однако можно загрузить проект, просто щелкнув по нему дважды, либо поставить на него курсор и нажать Enter. Если Delphi не загружена, она загрузится и загрузит проект.
*.res Файл ресурсов проекта, таких как иконки, курсоры и так далее.
*.pas Модуль формы. Этот файл мы видим в редакторе кода, его мы редактируем. Таких файлов имеется по одному на каждую форму проекта.
*.dfm Это файлы с информацией о форме. Тут содержатся описания используемых компонентов и их настройки.
*.ddp Это вспомогательные файлы модуля, они генерируются автоматически.
*.dcu Откомпилированный файл модуля. Фактически, та же программа, но только для одного модуля. Работать самостоятельно она не может.
*.exe Готовая программа. Компилятор собирает все *.dcu в единый исполняемый файл. Если вы в проекте не использовали других файлов, таких как базы данных, например, то этот файл единственный, который нужен. При распространении программы отдавайте пользователю только его. Однако это не значит, что все остальные файлы можно удалить. Ведь в них ваш проект! В будущем, возможно, вам понадобится процедура или функция, аналогичная той, которую вы использовали в проекте. Чтобы заново не изобретать велосипед, просто откройте старый проект и посмотрите, как вы реализовали эту функцию. Скопируйте ее и вставьте в новый проект, если нужно.
*.~* Файлы, расширение которых начинается с тильды – это резервные копии модулей и форм. Когда вы производите изменения и сохраняете проект, появляется такой файл. Это предыдущее сохранение. Если вы сохранили проект, и увидели, что ошиблись – его можно восстановить из этого файла. Однако лучше всего делать архивные копии проекта перед каждым серьезным изменением программы.

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

14. ListBox – список выбора

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

Чтобы получить доступ к строкам списка, нужно воспользоваться свойством Items компонента ListBox. Это свойство имеет тип TStrings (строки), с таким типом мы сталкивались, когда обрабатывали компонент Memo.

Посмотрим на практике, как работать с данным компонентом. Создайте новое приложение, установите на него один компонент ListBox, и под ним – один Edit для вывода той строки, которую выбрал пользователь:

Внешний вид формы

Рис. 12.1.  Внешний вид формы

Затем дважды щелкните по свойству Items компонента ListBox. Перед вами откроется уже знакомый редактор строк. Наберите названия операционных систем:

MS-DOS
Windows 3.10
Windows 95
Windows 98
Windows ME
Windows 2000
Windows XP
Windows Vista
Unix
Linux
OS/2

Каждое название операционной системы должно быть на отдельной строке. Нажмите “ОК”, чтобы сохранить результат. Теперь создайте для компонента ListBox обработчик события onClick. Мы уже знаем, что это событие срабатывает всякий раз, когда пользователь выберет одну из строк в указанном списке.

В обработчике событий напишите только одну строку:

Edit1.Text := ListBox1.Items.Strings[ListBox1.ItemIndex];

Эта строка присваивает свойству Text компонента Edit тот текст, который хранится в выбранной строке списка ListBox. Свойство Items имеет свое свойство Strings, которое представляет собой массив из строк списка. Указав индекс массива, мы можем получить доступ к нужной строке. В примере в качестве индекса указано свойство ListBox1.ItemIndex, которое имеет тип Integer и возвращает элемент выбранной строки в массиве строк. Кстати, когда вы поставите точку и откроется список, там вы этого свойства не обнаружите, так что придется писать его вручную.

Сохраните пример в новую папку, откомпилируйте и посмотрите, как он работает.

Кроме того, мы имеем возможность программно добавлять в ListBox новую строку или удалять выбранную. Киньте на форму еще две кнопки и напишите на них – “Добавить строку”, “Удалить строку”. Добавлять будем строку, написанную в компоненте Edit, а удалять – выделенную.

Для кнопки “Добавить” впишите:

ListBox1.Items.Add(Edit1.Text);

а для кнопки “Удалить”:

ListBox1.Items.Delete(ListBox1.ItemIndex);

Сохраните проект, откомпилируйте и посмотрите, как он работает.

Часто бывает необходимым предоставить пользователю возможность множественного выбора. Пользователь, удерживая клавишу <Ctrl>, щелкает по строкам и выбирает нужные. Для этого у ListBox имеется свойство MultiSelect (множественный выбор). По умолчанию оно равно False, то есть запрещает пользователю выбрать несколько строк. Создадим еще одно приложение, в котором продемонстрируем возможность множественного выбора.

Установите на форму один ListBox и один Memo, ниже – кнопку с надписью “Копировать”. При нажатии на кнопку будем искать у ListBox выделенные строки и копировать их в Memo. На рисунке 12.2 в левой части установлен компонент ListBox, а в правой – Memo.

Внешний вид приложения

Рис. 12.2.  Внешний вид приложения

Войдите в редактор строк ListBox и напишите там

и так далее, пока не заполните ListBox так, чтобы его не нужно было прокручивать. Установите свойство MultiSelect у ListBox в True. Не забудьте очистить Memo. Теперь для кнопки напишем следующий код:

procedure TForm1.Button1Click(Sender: TObject);
var
  i : Integer;
begin
  Memo1.Clear;
  for i := 0 to ListBox1.Items.Count - 1 do
     if ListBox1.Selected[i] then
        Memo1.Lines.Add(ListBox1.Items.Strings[i]);
end;

Вначале мы очистили Memo, чтобы пользователь мог несколько раз опробовать выбор и копирование строк, и строки в Memo не скапливались.

Затем мы создаем цикл, чтобы обрабатывать ListBox построчно. Первая строка всегда имеет нулевой индекс, а свойство Count во всех объектах TStrings возвращает количество строк в объекте. Нам приходится вычесть единицу, так как индексы начинаются не с 1, а с 0. Далее в цикл мы поместили условный оператор if – если условие верно (то есть строка выделена), то производим добавление строки в Memo. За это отвечает свойство Selected (Выделено) с указанием индекса строки. Если оно равно True, то строка выделена.

15. ComboBox – выпадающий список

Такие списки вы часто встречаете при работе с Windows и различными программами. Действуют и работают они также как ListBox, с той только разницей, что выглядят по-другому, и не позволяют выбрать несколько элементов сразу. Создайте новое приложение, добавьте туда только один ComboBox и один Edit:

Внешний вид приложения

Рис. 12.3.  Внешний вид приложения

Вызовите редактор строк ComboBox (свойство Items) Впишите несколько городов:

Москва
Санкт-Петербург
Киев
Минск
Ташкент
Душанбе

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

Создадим обработчик события OnChange для компонента ComboBox, и там напишем только одну строку:

Edit1.Text := ComboBox1.Items.Strings[ComboBox1.ItemIndex];

Как видите, это почти точная копия работы с ListBox. Сохраните пример в новую папку, откомпилируйте и попробуйте как он работает.

16. Диалоги

Что такое диалоги в Delphi? Это невизуальные, то есть, невидимые пользователю компоненты, которые выполняют стандартные для Windows диалоги пользователя и программы. Например, диалог открытия или сохранения файла, диалог выбора шрифта или цвета, и т.п. Любая серьезная программа содержит такие диалоги. Работа с ними несложная, каждый диалог содержит буквально по два свойства, которые нам будут нужны. Изучим работу диалогов на примере.

Открываем новый проект. Сразу же форму переименовываем в fMain, в свойстве Caption пишем “Мой блокнот”. Сохраните проект под именем Editor. Это будет более профессиональная версия редактора текстов, какой мы уже делали. Считайте, что это вторая версия программы, что и напишете в окне fAbout.

Установите на форму компонент Memo, удалите весь текст из его свойства Lines. Поверх Memo установите MainMenu и PopupMenu. Перейдите на вкладку Dialogs в палитре компонентов, и также поверх Memo установите OpenDialog, SaveDialog, FontDialog и ColorDialog. Все эти компоненты не визуальные, пользователь их видеть не сможет. У Memo сразу же укажите свойство Align=alClient, а свойство ScrollBar=ssVertical. Рекомендую для лучшего вида выбрать шрифт (свойство Font) Times New Roman, а размер = 12. На всех компьютерах с русской Windows есть этот шрифт, однако если вы будете писать программу для продажи в Интернет, лучше оставить шрифт по умолчанию, это гарантирует, что он будет читаться на всех компьютерах в мире.

Во всех диалогах есть один метод, который нас интересует – Execute. Это метод логического типа, он возвращает True, если диалог с пользователем произошел успешно (например, пользователь выбрал открываемый файл), и False в противном случае (например, пользователь отказался от выбора файла). В связи с этим, диалоги обычно применяют вместе с проверкой:

if OpenDialog1.Execute then...

В диалогах, связанных с файлами (OpenDialog – открыть файл, и SaveDialog – сохранить файл), есть свойство FileName, которое возвращает строку – адрес и имя выбранного файла. Вот, собственно, и все, что нам нужно от этих диалогов!

Диалог FontDialog в свойстве Font возвращает выбранный шрифт. Это свойство непростое, оно имеет тип TFont, и присвоить его можно только другому шрифту, например:

Memo1.Font := FontDialog1.Font;

Точно также, диалог ColorDialog возвращает свойство Color – цвет, имеющее тип TColor, и это свойство можно присвоить только объекту, имеющему такой же тип:

Memo1.Color := ColorDialog1.Color;

Продолжим наш проект. Откройте редактор главного меню. Создайте раздел “Файл” и подразделы “Открыть”, “Сохранить”, “Закрыть”, “-” и “Выход”. Создайте раздел “Параметры” и подразделы “Выбрать шрифт” и “Выбрать цвет”. Создайте раздел “Справка” и подраздел “О программе”.

Теперь открываем редактор PopupMenu и вписываем разделы “Открыть”, “Сохранить”, “Закрыть”, “-” и “Выход”. Сразу же на форме выделяем саму форму (это можно сделать в окне Object – TreeView), и в свойстве PopupMenu выбираем наше меню. Теперь это меню откроется, если пользователь щелкнет правой кнопкой по любому месту на форме.

Теперь нам нужно настроить фильтры в диалогах OpenDialog (Открыть) и SaveDialog (Сохранить). Фильтры позволяют отображать в этих диалогах только нужные форматы файлов, и для этого выбора используется маска файла. К примеру, маска *.* будет отображать файлы всех типов! Дважды щелкнув по свойству Filter диалога OpenDialog, откройте редактор фильтров. В первой колонке напишите “Текстовые документы”, во второй – “*.txt”. В строке ниже укажите “Все файлы”, а во второй колонке – “*.*”. Тоже самое сделайте для диалога SaveDialog:

Настройка фильтра файловых диалогов

Рис. 13.1.  Настройка фильтра файловых диалогов

Теперь, открывая файл, вы увидите только эти два типа файлов. Подумаем о том, что программа должна знать – изменился ли текст в Memo. Ведь пользователь может закрыть программу и не сохранить текст, а потом будет ругать программиста за то, что он этого не предусмотрел. При этом имеем в виду, что у нас есть много команд меню, значит, будет много процедур. А чтобы дать программе знать, изменился ли текст, разумнее всего создать переменную логического типа – изменился текст, присваиваем ей True, иначе False. Чтобы с этой переменной можно было работать из всех процедур, она должна быть глобальной. Делаем глобальную переменную перед словом implementation:

izmen : Boolean; //изменился ли текст в Memo

Событию onChange компонента Memo присвойте строку:

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

Теперь еще один момент – программа должна знать имя и адрес открытого файла. Если имени файла нет, то программа будет выводить диалоговое окно, а если мы файл открывали и имя есть, то программа просто будет перезаписывать тот файл без вывода диалогового окна. Стало быть, делаем еще одну глобальную переменную:

myfile : String; //Адрес и имя открытого файла

Я специально не беру широко распространенные слова “File” или “FileName”, так как они могут быть зарезервированными или в компонентах могут быть свойства с такими именами, в результате получится конфликт названий.

Соображаем дальше. Открыть файл можно будет командой меню “Файл – Открыть”, либо командой PopupMenu “Открыть”. Стало быть, нам придется дважды писать один и тот же код? А если он будет большим и сложным? Можно конечно и скопировать его, компилятор это выдержит, и программа будет работать нормально. А как же оптимизация кода? Два одинаковых кода в программе будут занимать в два раза больше места в памяти и на диске! Для этого мы имеем пользовательские функции и процедуры.

Вспоминаем – функцию или процедуру мы должны описать ВЫШЕ того места, где будем ее использовать, значит, первую нашу процедуру мы должны описать в разделе implementation, прямо под строчкой {$R *.dfm}.

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

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

Однако такой код будет не слишком удобен – каждый раз придется обращаться к компонентам через форму. Лишний набор кода, излишне длинный текст. Выход есть – функция with (с). Эта функция имеет вид:

with fMain do begin
   ...
end;

где fMain – имя формы с нужными нам компонентами. Теперь между скобок begin…end этой конструкции мы можем обращаться к компонентам формы напрямую. Пишем общую для всех процедуру открытия файла:

{Процедура открытия файла}
procedure Otkrivaem;
begin
  with fMain do begin //делать вместе с формой
    if OpenDialog1.Execute then begin //если диалог выполнен
      //присваиваем переменной myfile адрес и имя выбранного файла:
      myfile := OpenDialog1.FileName;

      //читаем этот файл в Memo:
      Memo1.Lines.LoadFromFile(myfile);
      izmen := False; //файл только открыт, изменений еще нет
    end; //if
  end; //with
end;

Теперь создаем обработчик событий для команды меню “Файл – Открыть”. Там вызываем нашу процедуру:

Тоже самое делаем для команды PopupMenu “Открыть”.

Дальше – сложней. Открыть файл просто, но вот при сохранении нам придется учитывать много вещей:

  1. Пользователь может сохранять новый файл, который он только что набрал. То есть, переменная myfile пуста и не содержит имя файла. В таком случае придется выводить диалог SaveDialog1, чтобы пользователь указал имя файла. Когда он укажет имя, присвоить его переменной myfile и сохранить Memo в указанный файл.
  2. Пользователь может сохранять новый файл, как в предыдущем примере. Мы выведем диалог, но он его не завершит – нажмет кнопку “отмена” или красный крестик в верхней части окна справа. Значит, сохранять ничего не нужно, мы ведь не знаем, куда сохранять! Но придется его предупредить, что файл не сохранен!
  3. Пользователь может сначала открыть файл и изменить его, а потом сохранять. В переменной myfile это имя уже есть, диалог не нужен, просто перезаписываем этот файл.
  4. Пользователь может сохранять файл, текст которого не изменялся. В таком случае, просто игнорируем его команду!

Видите? Пользоваться диалогами несложно, но как много приходится учитывать во время проверок действий пользователя! Нужно учитывать каждую мелочь, иначе вам скажут, что ваша программа полна “багов” – мелких неисправностей. Итак, пишем процедуру сохранения, сразу под процедурой открытия:

{Процедура сохранения файла}
procedure Sohranyaem;
begin
  with fMain do begin
    //если изменений не было, выходим из процедуры,
    //ничего не делая:
    if not izmen then Exit;

    //Если файл уже открывался, и в переменной myfile
    //есть его адрес и имя, просто перезаписываем этот файл:
    if myfile <> '' then begin
      Memo1.Lines.SaveToFile(myfile);
      izmen := False;
      Exit;  //выходим после сохранения
    end; //if

    {Файл новый, переменная myfile еще пуста. Дальше есть два варианта:
    пользователь выберет или укажет файл в диалоге, или не сделает этого}

    //если выбрал файл:
    if SaveDialog1.Execute then begin
      //прописываем адрес и имя файла в переменную:
      myfile := SaveDialog1.FileName;
      //если нет расширения *.txt то добавляем его:
      if copy(myfile, length(myfile)-4, 4) <> '.txt' then
        myfile := myfile + '.txt';
      //сохраняем Memo в указанный файл:
      Memo1.Lines.SaveToFile(myfile);
      //файл сохранен, изменений нет:
      izmen := False;
    end //if
    //если не выбрал файл:
    else ShowMessage('Вы не указали имени файла, файл не сохранен!');

  end; //with
end;

Приведенный выше код имеет достаточно подробные комментарии, так что все должно быть понятно. Новое, что вы могли увидеть – директива Exit. Эта директива досрочно завершает работу процедуры (или функции). То есть, если выполнено условие и отработан нужный код, Exit заставляет процедуру завершить работу. Остальной код, который есть в этой процедуре, не выполняется.

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

Тоже самое делаем для команды PopupMenu “Сохранить”.

Далее идет команда главного и всплывающего меню “Выход”. Тут все просто, в обоих случаях пишем команду

Далее идет раздел “Параметры”. Создаем обработчик “Выбрать шрифт”, там все просто:

  if FontDialog1.Execute then
    Memo1.Font := FontDialog1.Font;

Точно также и с подразделом “Выбрать цвет”:

  if ColorDialog1.Execute then
    Memo1.Color := ColorDialog1.Color;

Далее вернемся в раздел “Файл”. Здесь у нас остался подраздел “Закрыть”. Создаем для него обработчик, и запишем текст:

  {если файл не сохранен, предупреждаем пользователя об этом. Если он
   желает сохранить, то вызываем процедуру сохранения:}
  if izmen then
    if Application.MessageBox('Файл изменен. Сохранить?', 'Внимание!',
      MB_YESNO+MB_ICONQUESTION) = IDYES then Sohranyaem;

  //теперь закрываем текущий файл:
  Memo1.Clear;  //очищаем Мемо
  myfile := ''; //нет имени текущего файла
  izmen := False; //нет изменений

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

Примерно тоже самое нам придется сделать и для события формы onClose – ведь мы заранее не можем знать, каким образом пользователь закроет форму, через команду главного меню “Файл – Закрыть”, через команду всплывающего меню “Закрыть”, нажмет ли он красный крестик наверху или нажмет горячие клавиши <Alt + F4>! Поэтому для проверки – есть ли в программе несохраненный текст, мы используем событие onClose, которое случается при попытке закрыть форму, то есть в данном случае всю программу. Здесь код будет таким же, как и в предыдущем примере, но раз мы закрываем всю программу, нам не нужно выполнять блок закрытия файла. Просто проверим, есть ли изменения, и если они есть, выведем запрос – сохранить ли их. Если пользователь ответит “Да”, значит, вызовем процедуру сохранения:

  {если файл не сохранен, предупреждаем пользователя об этом. Если он
   желает сохранить, то вызываем процедуру сохранения:}
  if izmen then
    if Application.MessageBox('Файл изменен. Сохранить?', 'Внимание!',
      MB_YESNO+MB_ICONQUESTION) = IDYES then Sohranyaem;

Теперь введем еще одну команду для обоих меню – “Очистить”. Она будет предназначена на случай, если пользователь введет абракадабру, а потом решит очистить текст. Я намеренно оставил это действие на конец, чтобы вы могли усвоить, что в процессе работы над программой меню может изменяться!

Откройте редактор MainMenu, в разделе “Файл” в самом низу добавьте подраздел “Очистить”. Затем мышкой перетащите его на место линии разделов, при этом линия опустится вниз, а новый подраздел встанет на ее место:

Вид главного меню

Рис. 13.2.  Вид главного меню

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

{MainMenu - Файл - Очистить}
procedure TfMain.N17Click(Sender: TObject);
begin
  //очищаем Мемо:
  Memo1.Clear;
  //если открытого файла нет, то нет и изменений:
  if myfile = '' then izmen := false
  //иначе текст изменен:
  else izmen := true;
end;

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

Осталось создать модальное окно fAbout, где Вы укажете, что это текстовый редактор, второй версии. Сделайте это самостоятельно и привяжите вызов этой формы к команде главного меню “Справка – О программе”.

Все, сохраняйте, компилируйте и проверяйте, как работает программа! У нас получился несложный, но вполне профессиональный редактор текстов. Одно замечание: текст мы сохраняем, но вот выбранный шрифт и цвет окна Вы сохранить не можете, об этом мы будем говорить на других лекциях, когда научимся сохранять параметры.

17. Сетка строк StringGrid

Теперь на практике познакомимся с сеткой строк, похожей на ту, что используется в файлах MS Excel. Создайте новое приложение, установите на форму сетку StringGrid с вкладки компонентов Additional. Рядом находится еще сеточка DrawGrid. Разница между ними небольшая, но первую используют чаще. Сетка StringGrid самостоятельно прорисовывает данные в ячейках, при использовании сетки DrawGrid эти данные придется прорисовывать самостоятельно. Сетку DrawGrid обычно используют для прорисовки графики, и нужда в ней возникает намного реже, чем в StringGrid.

Как видите, сетка StringGrid очень похожа на ту, что вы видели в MS Excel. Пока еще она пуста. Выделите ее и посмотрите на свойства.

BorderStyle отвечает за стиль обрамления. Может иметь только два значения – с обрамлением и без него.

ColCount – количество колонок в сетке. По умолчанию их 5.

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

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

DefaultRowHeight – высота строк по умолчанию. Установлено 24 пикселя, но этот размер великоват, поэтому строки получаются такими высокими.

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

FixedRows – количество фиксированных строк. По умолчанию тоже одна, и работает также, как и FixedCols. Как правило, эта строка служит заголовком колонок.

GridLineWidth – толщина разделительных линий. Попробуйте поставить ноль – линии исчезнут. Верните единицу.

Options – самое главное свойство компонента. Оно содержит много настроек, которые раскроются, если щелкнуть по плюсу слева от названия свойства. Эти дополнительные свойства имеют следующие назначения:

  • goFixedVertLine – рисовать ли вертикальные линии у фиксированных ячеек? По умолчанию True.
  • goFixedHorzLine – прорисовка горизонтальных линий у фиксированных ячеек.
  • goVertLine – прорисовка вертикальных линий у всех остальных (нефиксированных) ячеек.
  • goHorzLine – прорисовка горизонтальных линий у нефиксированных ячеек.
  • goRangeSelect – разрешение выделять несколько ячеек. Не работает, если включен элемент goEdit.
  • goDrawFocusSelect – разрешено выделять ячейку, которая находится в фокусе ввода.
  • goRowSizing – разрешено изменять высоту строки перетаскиванием мышью.
  • goColSizing – разрешено изменять ширину колонки перетаскиванием мышью.
  • goRowMoving – можно ли мышью перемещать строки на другое место.
  • goColMoving – можно ли мышью перемещать колонки на другое место.
  • goEditing – можно ли редактировать сетку? То есть, вводить данные с клавиатуры. Игнорируется, если включен элемент goRowSelect.
  • goTabs – можно ли переключаться на другие ячейки с помощью клавиши <Tab>.
  • goRowSelect – выделяется вся строка. Если равно False, то только одна ячейка.
  • goAlwaysShowEditor – если True, то редактировать ячейку можно сразу при выделении. Если False, то для редактирования нужно нажать <Enter> или <F2>.
  • goThumbTracking – разрешена ли прорисовка данных в ячейках при прокрутке. Если нет, то данные будут обновлены после прокрутки.

RowCount – количество строк в сетке.

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

Итак, приступим к примеру. Мы уже говорили, что по умолчанию дается слишком большая высота строк, уменьшите ее до 16 (свойство DefaultRowHeight). У нас должно быть 5 строк и 5 колонок, причем фиксированными будут по одной колонке и одной строке. Далее, пользователь должен иметь возможность вводить данные в ячейки, поэтому в разделе Options в свойстве goEditing установим True.

Теперь создаем для формы событие onShow, и вписываем следующий код:

begin
  //заполняем значениями первую колонку:
  StringGrid1.Cells[0,1]:= 'Иванов';
  StringGrid1.Cells[0,2]:= 'Петров';
  StringGrid1.Cells[0,3]:= 'Николаев';
  StringGrid1.Cells[0,4]:= 'Бонд';

  //заполняем значениями первую строку:
  StringGrid1.Cells[1,0]:= 'Год рожд.';
  StringGrid1.Cells[2,0]:= 'Место рожд.';
  StringGrid1.Cells[3,0]:= 'Прописка';
  StringGrid1.Cells[4,0]:= 'Семейное положение';

  //меняем ширину колонок
  StringGrid1.ColWidths[4]:= 120;
  StringGrid1.ColWidths[3]:= 90;
  StringGrid1.ColWidths[2]:= 90;

end;

Как видите, обращение к отдельным ячейкам здесь точно такое, как к двухмерному массиву. Первым индексом служит строка, вторым – колонка. Нумерация индексов начинается с нуля, поэтому верхняя левая ячейка будет иметь индекс [0, 0].

Свойство ColWidths[i] устанавливает ширину колонки с индексом i.

Сохраните проект, скомпилируйте его и посмотрите результат. Если ваша сетка слишком маленькая или наоборот, слишком большая, то измените ее размер, чтобы все колонки умещались в сетке.

Улучшим наш пример, добавив маску для ввода даты к столбцу “Год рождения”. Делается это совсем просто – выделяете сетку, переходите на вкладку Events и генерируете событие onGetEditMask. Это событие происходит, когда пользователь редактирует сетку. Там вписываете только одну строку:

  if ACol=1 then value := '99.99.9999 г.'

Если вы посмотрите на параметры этого события, то увидите, что в него передаются такие параметры, как ACol и ARow. Это – индекс текущей колонки и текущей строки. Параметр Value содержит текст маски. То есть, если пользователь редактирует колонку с индексом 1 – это вторая колонка, где указывается год рождения, мы устанавливаем маску ввода даты.

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

18. Image

Компонент находится на вкладке компонентов Additional и представляет собой контейнер прямоугольной формы, в который можно поместить картинку. Установите его на форму, и посмотрите на его свойства.

Свойство AutoSize заставляет компонент автоматически принимать размер изображения, если установлено True.

Свойство Picture – основное свойство компонента. Оно позволяет открыть диалоговое окно, в котором можно выбрать изображение для загрузки в контейнер. Для этого нужно нажать на кнопку с тремя точками в правой части свойства. Затем нажать кнопку Load для загрузки изображения.

Свойство Center разместит изображение по центру контейнера, если AutoSize не равно True. Иначе свойство игнорируется.

Свойство Proportional разрешает или запрещает пропорционально уменьшать высоту и ширину изображения, если оно не может целиком уместиться в контейнере.

Свойство Stretch разрешает или запрещает изображению целиком заполнять контейнер.

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

Правда, нам нужен только один инструмент – кнопка для загрузки изображений. Установите на панель кнопку, напишите на ней “Загрузить изображение”.

Свойство Align компонента Image установите в alClient, чтобы растянуть его по всей оставшейся части формы. У этого контейнера должны быть следующие настройки в Объектном инспекторе:

AutoSize = False;
Center = True;
Proportional = True;
Stretch = True;

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

Создайте обработчик событий для нажатия на кнопку, и там напишите код:

  if OpenPictureDialog1.Execute then
    Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);

Вот и весь браузер! По нажатию на кнопку программа будет выводить диалог открытия изображения. Выбрав изображение, вы загрузите его в контейнер Image. Сохраните проект, скомпилируйте и посмотрите, как работает приложение. Для просмотра подойдут любые изображения – картинки, фотографии и т.п. Если у вас на компьютере установлен пакет MS Office XP/2000 или выше, то большую коллекцию картинок вы сможете найти на:

C:Program FilesMicroSoft OfficeMediacagcat10

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

Внешний вид приложения

Рис. 24.1.  Внешний вид приложения

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

Загрузка…

Урок Delphi 1 .Windows – программа нажатием одной кнопки!

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

Итак, запустим Delphi. Для этого нужно создать ярлык на рабочем столе, если, конечно, Вам не нравится каждый раз ходить по адресу Program Files – Borland – Delphi -Bin и отыскивать файл delphi32.exe. Гораздо проще один раз найти его ярлычок в меню ПУСК – ВСЕ ПРОГРАММЫ – BORLAND DELPHI – DELPHI, перетащить его отсюда на рабочий стол и, как говорится, будет Вам счастье!
Перед нами четыре окна Delphi. Вверху во вcю ширину экрана окно управления проектом и средой разработки – главное окно Delphi.

Delphi

При его сворачивании сворачиваются и все остальные. Слева – Инспектор объектов. В нём задаются свойства составляющих нашу программу компонентов. И наконец, в центре одно над другим два окна Delphi, окно формы будущей программы и окно программной начинки.    Прямо перед нами – окно, которое в Delphi называется Форма. Именно Форма является визуальным прообразом нашей будущей программы.

Видео на тему: #1 Программирование в Delphi. “Hello World” на Delphi

Теперь посмотрите, как легко получается программа в Delphi:

  1. Наводим мышку на зелёный треугольник-стрелку на главном окне
  2. Смотрим – всплывает подсказка “Run (F9)
  3. Жмём на эту кнопку (или F9 на клавиатуре)
  4. Получаем готовую Windows-программу!

   Однако (как подсказывают в комментариях), не во всех версиях Delphi запуск программы производится кнопкой F9, для некоторых это CTRL+F9 – посмотрите сами, какую подсказку выдает Delphi при наведении на зелёную стрелку.
По умолчанию программа создаётся в папке C:Program FilesBorlandDelphi7Projects:

Delphi

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

   Мы получили программу, состоящую из одного пустого окна. Тем не менее наша программа имеет все атрибуты, присущие всем программам в Windows: заголовок, системное меню (кликните по левому краю заголовка!), кнопки свернуть, развернуть, закрыть, может менять свои размеры.

   Закройте программу-Форму. Рассмотрим полезные для нас свойства Формы:

    1. Надпись на заголовке – свойство Caption. Сейчас это Form1, и совпадает со свойством Name. В инспекторе объектов можно поменять их по своему усмотрению. Напишите в свойстве Caption, например, “Простейшая программа!”
    2. Цвет – свойство Color.
    3. Размеры – ширина и высота в пикселях, свойства Width и Height. Изменяем их мышкой, двигая края Формы, затем устанавливаем более точные значения в Инспекторе.
    4. Положение на экране – свойства Top и Left. Это расстояния в пикселях от верхней и левой границы экрана соответственно. Если необходимое положение Формы закрывает элементы управления Delphi, просто сверните её. Но есть очень полезное
    5. свойство Position, с помощью которого можно настроить автоматическое появление Формы в нужном месте. Разверните выпадающий список:
        • При значении poDesigned Форма появится в том месте, где она находилась при проектировании. Это значение по умолчанию.
        • При значениях poDesktopCenter и poScreenCenter Форма появится в центре рабочего стола или центре экрана.
           Форма может быть вызвана из другого окна-формы. Тогда при значениях

      • poMainFormCenter она появится в центре главного окна приложения,
      • poOwnerFormCenter – в центре вызывающего окна, так называемого “владельца”.
    6.    Вы можете запрограммировать появление Формы в 

нормальном, минимизированном или максимизированном состоянии. За это отвечает.

  1. 6. свойство WindowState – значения wsNormalwsMinimized и wsMaximized соответственно. 
      1. Не у всех окон в заголовке есть кнопки

    свернуть, развернуть, закрыть.

Их наличием или отсутствием управляет

7. свойство BorderIcons. В Инспекторе слева от него маленький плюсик, открывающий признак наличия или отсутствия нужной кнопки. True – кнопка будет, False – нет. Смело экспериментируйте, но изменения будут видны только в работающей программе, а не в прототипе. А вот как вы будете закрывать Форму при biSystemMenu=False, ведь крестика закрытия не будет? Запомните сочетание ALT+F4. Это команда закрытия любых окон, включая саму Windows!

       Вы можете управлять также границами Формы. Для этого служит
    1. 8. свойство

BorderStyle

    . При значении
    •  
    • bsSizeable – обычная Форма, значение по умолчанию.
    • bsNone – Форма вообще не будет иметь границ, включая строку заголовка.
    • bsSingle – Форма не может менять размеры, но может свернуться или развернуться.

    Таким образом, комбинируя свойства BorderIcons и BorderStyle можно, например, получить форму с неизменными размерами и без возможности свернуться и развернуться:

Delphi

Теперь займёмся сохранением нашего проекта. Так как по умолчанию Delphi сохраняет новые проекты в папке C:Program FilesBorlandDelphi7Projects, то если мы не будем выделять под него место сами, все файлы данного и всех будущих проектов будут свалены в кучу.

Поэтому сразу в начале работы над новым проектом командой меню File –» Save All (или соответствующей кнопкой на главном окне) сохраним проект в специально для него созданную папку. Создать её можно прямо в открывшемся окошке.

Проект в целом сохраняется в файле с именем Project1. Форма функционирует вместе с программой, описывающей её работу, так называемым модулем. Если модулей в проекте несколько, для каждого из них Delphi создаст отдельный файл, и предложит его сохранить под именем Unit1, Unit2 и так далее.

И для файла проекта, и файлов модулей можно дать и своё, более осмысленное название. Договоримся, что каждый новый проект сразу будем сохранять, и я не буду дополнительно напоминать об этом.
   Теперь выполните команду File -» Close All. Попробуйте открыть файл модуля командой Open…. Модуль откроется вместе с нашей формой, мы сможем нормально работать, но кнопка запуска программы окажется неактивной.

Поэтому сначала нужно открывать файл проекта. Для этого, кстати, есть специальная команда меню File -» Open Project…  Ctrl F11, и соответствующая кнопка, прямо над кнопкой запуска. Теперь в окне выбора будет только один файл, файл проекта. При его открытии будет открыт и первый модуль и первая форма проекта. Для нашего проекта этого достаточно. Если в проекте несколько форм, их модули и формы открываем командой Open…. Можно открывать модули других проектов, например, для копирования кода.

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

Урок Delphi 2. Компоненты Delphi – основа визуального проектирования!

В пустой форме смысла нет. Наполнить её содержанием помогут компоненты Delphi. Они располагаются на соответствующих вкладках палитры компонентов на главном окне. Все основные компоненты Delphi находятся на первых четырёх вкладках:

  • Standard,
  • Additional,
  • Win32,
  • System.

Delphi

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

В дальнейшем компоненты можно свободно перетаскивать по форме мышкой, “конструируя” нужный интерфейс. Если, щёлкнув по компоненту, вы захотите отказаться от его переноса на форму, щёлкните по стрелке, расположенной слева на вкладке. Выделение компонента снимется.

Есть соответствующие справочники, где рассматриваются все компоненты Delphi. Но самые важные свойства компонентов Delphi и работу с ними мы рассмотрим.
Рассмотрим компоненты отображения текста. Создайте новый проект (File -» New -» Application), и перенесите на форму компоненты Label, Edit, Memo и Button. Выбирая одним щелчком мышки или клавишей Tab нужный компонент, в Инспекторе Объектов мы можем получить доступ к его свойствам.
Прежде всего, у визуальных компонентов есть свойства, определяющие их положение на Форме:

  • Ширина компонента, Width
  • Высота компонента, Height
  • Расстояние до левого края формы, Left
  • Расстояние до верхнего края формы, Top

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

  • Label и Button – свойство Caption,
  • Edit – свойство Text,
  • Memo – свойство Lines.

При “конструировании” формы в Инспекторе объектов можно придать свойствам компонентов любые значения. Случайно можно задать такие размеры или координаты, что компонент “исчезнет” – сделается невидимым или спрячется за другими компонентами.

Его легко найти с помощью того же Инспектора Объектов – все компоненты, находящиеся на Форме, перечислены в его выпадающем списке. Достаточно выбрать нужный компонент, и он или его контуры (если он заслонён” другими компонентами) появятся на Форме, а в Инспекторе объектов – его свойства.

Теперь “запустите” программу (зелёная стрелка или F9). Видим, что компоненты “работают”. Label является надписью (меткой) на форме, Button – кнопка нажимается, Edit – строка ввода и Memo – многострочный текстовый редактор позволяют вводить текст!
А теперь давайте напишем маленькую программку! Она будет по нажатию кнопки отображать на форме то, что мы введём в строке ввода. Начните новый проект (File -» New -» Application).
Расположите на форме компонент Edit (строка ввода). Свойство Text очистите.

  1. Далее – компонент Button (кнопка). В свойстве Caption напишите, например, “показать”.
  2. Затем – компонент Label (метка). В свойстве Font для наглядности сделайте размер побольше, например 24, выберите шрифт и цвет. Свойство Caption также очистите.
  3. Щёлкните дважды по нашей кнопке. Произошла метаморфоза! Мы очутились в окне модуля, где система Delphi создала для нас заготовку обработчика события нажатия на кнопку!
  4. В обработчике пишите: Label1 и поставьте точку. Подождите секунду после ввода точки. Видите – выскочила подсказка!. Система Delphi предлагает нам выбрать из списка нужное свойство или метод. Нажмите “C”, и строка “Caption” станет выделенной. Delphi пытается угадать, что мы хотим ввести. Дальше писать не обязятельно, достаточно нажать Enter.
  5. В результате получим: Label1.Caption. Таким образом мы видим, что точкой разделяются в Delphi объект и его свойства. Указанием на объект служит его имя (свойство Name). Имя компонента можно посмотреть в Инспекторе Объектов, а также наведя мышку на компонент и дождавшись появления подсказки.
  6. Далее присваиваем свойству Caption объекта Label1 значение. Знакомьтесь, оператор присваивания:
       :=
    Двоеточие перед знаком равенства обязательно!!!
  7. Получаем:
      Label1.Caption:=
    Подумайте сами, что писать дальше…
  8. …а именно то, что мы хотим отобразить в метке – свойство Text объекта Edit1: Edit1.Text
  9. Далее то, чем завершается любая команда – оператор “;“. Это именно оператор, хотя и не выполняющий никаких действий, и его иногда применяют именно в этом качестве.

   Вот что у нас получилось:

Label1.Caption := Edit1.Text;

Кому лень, просто скопируйте отсюда и вставляйте между begin и end. Ну всё, сохраняем и жмём F9.

   В дальнейшем программы будут куда сложнее. Что делать, если в результате ошибки в программе она зависнет? Естественно, можно воспользоваться комбинацией Ctrl+Alt+Del, но проще, нажав OK в окне предупреждения об ошибке, выполнить команду меню главного окна Delphi Run -» Program Reset или Ctrl+F2!

Урок Delphi 3. События Delphi

Операционная система Windows – многозадачная, то есть несколько программ в ней могут функционировать одновременно. Когда, например, мы щёлкаем по кнопке в окне нашей программы, система Windows определяет, что произошло событие именно в нашей программе, и посылает ей сообщение об этом.

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

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

Как работать в Delphi: конкретные уроки

Откройте наш проект из предыдущего урока. Щелкните на компоненте Edit1. Он “появится” в Инспекторе объектов. Посмотрите: в Инспекторе объектов две вкладки: Properties (свойства) и Events (события). Перейдите на вкладку Events.

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

   Изменим нашу программу так, чтобы текст на форме появлялся прямо в момент его ввода. В момент ввода у Edit1 меняется свойство Text – в нём появляется новая буква! Значит, воспользуемся событием onChange (change – изменение (англ.)), которое и происходит в этот момент. Итак:

  1. Кликаем дважды по onChange, и оказываемся внутри только что созданного обработчика.
  2. Присваиваем свойству Caption компонента Label1 значение свойства Text компонента Edit1, то есть делаем то же, что и в прошлом уроке:

       Label1.Caption := Edit1.Text;

    Или просто копируем из обработчика нажатия кнопки.

  3. Запускаем программу, всё работает. Как видим, всё очень просто.

   Теперь рассмотрим событие onClick. Как вы догадываетесь, это событие возникает при щелчке мышкой на компоненте. Воспользуемся им, чтобы очищать строку ввода от уже введённых символов. Вы сами уже должны сообразить, что сделать. В обработчике нужно присвоить свойству Text значение пустой строки. Строка в Delphi образуется заключением текста в одинарные кавычки (находятся на кнопке Э):
    Так в Delphi образуется строка
Значит, пустая строка – это кавычки без текста: . Не должно быть даже пробела, иначе он окажется в строке ввода:

   Edit1.Text:='';

Есть другой способ, воспользоваться специально предназначенным для этого методом компонента Edit, который так и называется Clear (очистка англ.):

   Edit1.Clear;

   Но подумайте о пользователе, который будет работать с вашей программой. Ему должно быть удобно. Если при вводе текста он захочет что-то исправить, и щёлкнет мышкой в том месте текста, где нужно внести изменение?! И всё сотрётся! Поэтому лучше использовать событие onEnter, которое происходит, когда вы “входите” в него и компонент получает фокус ввода, или использовать для очистки специальную кнопку и её событие onClick.
   Конечно, у каждого компонента свой набор событий. Мы познакомились с тремя из них:

  • onChange
  • onClick
  • onEnter

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

  • onExit – возникает, когда компонент теряет фокус ввода;
  • onDblClick – возникает при двойном щелчке мышкой по компоненту;
  • onKeyDown – когда при нажатии на кнопку на клавиатуре она оказалась в нижнем положении;
  • onKeyUp – когда при отпускании клавиатурной кнопки она оказалась в верхнем положении;
  • onKeyPress – возникает при нажатии на клавиатурную кнопку. От событий onKeyDown и onKeyUp оно отличается типом используемого параметра Key ;
  • onMouseDown – когда при нажатии кнопки мышки она оказалась в нижнем положении;
  • onMouseUp – когда при отпускании кнопки мышки она оказалась в верхнем положении;
  • onMouseMove – возникает при перемещении указателя мышки над компонентом.

   В начале работы любой программы происходит очень важное событие событие нашего основного компонента – Формы, onCreate. Оно происходит перед появлением Формы на экране.

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

Если вы захотите сделать невидимую программу, можно приравнять нулю ширину Width и высоту Height Формы. На этапе проектирования сделать этого нельзя, т.к. это помешает работе, поэтому делаем это по событию onCreate:

   Form1.Width := 0;
   Form1.Height := 0;

Дополнительно нужно убрать и заголовок Формы, выбрав в Инспекторе Объектов параметр BorderStyle равным None. Теперь Форма на экране не появится. Единственным визуальным признаком останется появление её “значка” на панели задач. В дальнейшем я расскажу, как избавиться и от него.

Урок Delphi 4. Переменные, константы и их типы

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

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

    Место описания данных в программе – вне логических блоков begin / end. В модуле перед ключевым словом implementation есть блок описания:

var
  Form1: TForm1;

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

Команда объявления переменных в языке Delphi:

   var имя_переменной : тип_переменной ;

    Слово var – ключевое. Именем может быть любой идентификатор, если он не был описан ранее и не является одним из ключевых или зарезервированных слов языка Delphi. Если нужно описать несколько переменных одного типа, то их перечисляют, отделяя запятой:

    var A, B, C : Integer;

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

var A, B : Integer;
        C, D : String;

    Постоянную величину иначе называют константой. Конечно, в программе можно использовать числа и строки непосредственно: 3.1415 или ‘Это значение числа пи’, но иногда удобнее присвоить их идентификатору.

Описание констант аналогично описанию переменных, но используется ключевое слово const, за именем идентификатора следует тип, затем знак равенства и его значение. Причём тип константы допускается не указывать:

const pi=3.1415 ;
         ZnakPi : String = 'Это значение числа пи';

К слову, константа Pi встроенная в Delphi, то есть для того чтобы использовать в Delphi число 3,1415… в расчётах, нужно просто присвоить встроенную константу Pi переменной типа Real или просто использовать непосредственно в выражениях.

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

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

‘это текстовая строка’

Если текст должен содержать сам символ кавычки, то его надо повторить дважды:

‘это ” – символ одиночной кавычки’

Строка может быть и пустой, не содержащей символов. Тогда она состоит из двух идущих друг за другом без пробела кавычек. Естественно, строка может состоять и только из одних пробелов.
   Самый популярный строковый тип – String. Строка типа String может содержать переменное количество символов объёмом до 2 Гбайт.

Если нужно ограничить размер строки фиксированным значением, то после ключевого слова String в квадратных скобках указывается число, определяющее количество символов в строке: String[50]. Более полно работа со строками Delphi описывается далее.
   Одиночный символ имеет тип Char и записывается в виде знака в одиночных кавычках: ‘a’.

Есть символы, которые на экране отобразить невозможно, например, символ конца строки (равен #13), символ переноса строки (равен #10). Такие символы записываются в виде их числового кода (в кодировке ANSI), перед которым стоит знак #. Например, #0.
   Наконец, существуют так называемые нуль-терминированные строки. Отсчёт символов в таких строках начинается с нуля, а заканчивается символом с кодом 0 (#0). Такие строки имеют тип PChar.

   Числа бывают целые и дробные.
В следующей таблице перечислены стандартные типы целых чисел и соответствующие им дипазоны допустимых значений.

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

 Integer    -2147483648 .. +2147483647
   Cardinal    0 .. 4294967295
   Shortint    -128 .. +127
   Smallint    -32768 .. +32767
   Int64    -263 .. +263-1
   Byte    0 .. +255
   Word    0 .. +65535

Дробные числа имеют дробную часть, отделяемую десятичной точкой. Допускается использование символа e (или E), за которым следует число, указывающее, что левую часть нужно умножить на 10 в соответствующей степени: 5e25 – пять умножить на десять в двадцать пятой степени.
Ниже приведены стандартные типы дробных чисел и соответствующие им диапазоны допустимых значений. Для большинства типов указан диапазон положительных значений, однако допустимым является аналогичный диапазон отрицательных значений, а также число 0.

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

   Real    5*10-324 .. 1.7*10308
   Real48    2.9*10-39 .. 1.7*1038
   Singl    1.5*10-45 .. 3.4*1038
   Double    5*10-324 .. 1.7*10308
   Extended    3.6*10-4951 .. 1.1*104932-1
   Comp    -263 .. +263-1
   Currency    922337203685477.5807

Следующим типом данных является логический Boolean, состоящий всего из двух значений: True (Истина) и False (Ложь). При этом True > False.
   Теперь, используя компоненты, их свойства и события, вводя собственные переменные, можно конструировать программы, содержащие вычисления. Осталось узнать, как вычисленное значение вывести на экран.
Про консольные программы я здесь не говорю! А в нормальных оконных Windows-приложениях это значение нужно поместить в какой-нибудь компонент, имеющий свойства Text или Caption.

Это, например, такие компоненты как Label и Edit, да и сама Форма имеет свойство Caption, куда тоже можно выводить информацию. Однако, в Delphi информацию перед выводом, как правило, необходимо преобразовывать. Так как присвоение возможно только между переменными одного типа, то такая программа (не пытайтесь её исполнять):

   var A, B, C: Integer ;
  begin
   A := 5 ;
   B := 10 ;
   C := A+B ;
   Label1.Caption := C ;
  end ;

вызовет ошибку, так как свойство Caption имеет текстовый тип String, а использованные переменные – цифровой тип Integer. Значит, нужно преобразовать значение переменной C в текстовый тип. Для этого есть встроенная функция IntToStr. Строка в нашей “программе”, вызывавшая ошибку, должна выглядеть так:

   Label1.Caption := IntToStr(C) ;

   Такая программа, кроме показа числа 15, ни на что не способна. Мы должны научиться вводить в программу другие числа. Используем компоненты Edit. Введённые числа будут содержаться в свойстве Text этих компонентов. Расположим на форме два компонента Edit, один компонент Label и кнопку Button, по нажатию на которую и будем проводить вычисления.

В компоненты Edit1 и Edit2 будем вводить числа для суммирования. Чтобы переместиться в редактор кода, щёлкнем дважды по нашей кнопке Button1. Мы попадём прямо в сформированную для нас средой Delphi заготовку обработчика нажатия на кнопку, непосредственно между операторами begin и end. Напишем такой простой код:

  procedure TForm1.Button1Click(Sender: TObject);
  var A, B, C: Integer;//Не забудьте описание переменных
  begin
  //Начало кода:
   A := Edit1.Text;
   B := Edit2.Text;
   C := A+B;
   Label1.Caption := IntToStr(C);
  //Конец кода
  end ;

При попытке исполнить этот код Delphi покажет ошибки по аналогичной причине – переменные A и B имеют цифровой тип Integer, а свойство Text – текстовый тип String. Исправить ошибки поможет встроенная функция StrToInt, выполняющая обратное преобразование – текст в целое число. Операторы присвоения переменным A и B должны выглядеть так:

   A := StrToInt(Edit1.Text);
   B := StrToInt(Edit2.Text);

В данном случае переменные A, B, C использовались для наглядности. Можно обойтись одной строчкой:

   Label1.Caption:=IntToStr(StrToInt(Edit1.Text)+StrToInt(Edit2.Text));

Аналогично, имеются функции и для преобразования в строку и обратно действительных чисел c плавающей (Floating англ.) запятой, имеющих тип Real. Для преобразования в строку – FloatToStr, обратно – StrToFloat.
   Часто результаты вычислений, имеющие тип Delphi Real, имеют после запятой длинный “хвост” цифр. При выводе такой переменной в текстовом виде необходимо ограничить количество цифр после запятой. Как это можно сделать, описывается также в Уроке Delphi Работа со строками Delphi.

Урок Delphi 5. Собственные и структурные типы данных

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

Чтобы ввести в программу (описать) новый тип данных, применяется оператор с ключевым словом type:
   type название_типа = описание_типа;

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

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

   type FootballTeam = (Spartak, Dinamo, CSKA, Torpedo, Lokomotiv);
   var MyTeam: FootballTeam;
   begin
     MyTeam:=Spartak;
   end;

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

  • все целочисленные типы, для которых всегда можно указать число, следующее за числом N;
  • символьные типы (Char): за символом ‘a’ всегда следует ‘b’, за ‘0’ следует ‘1’, и так далее;
  • логические типы – тип Boolean также представляет собой перечислимый тип: type Boolean = (false, true);

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

  • массивы
  • записи
  • множества

Массив – это структура данных, доступ к элементам которой осуществляется по номеру (или индексу). Все элементы массива имеют одинаковый тип.
Описание массива имеет вид:

   type имя_типа_массива = array [диапазон] of тип_элемента;

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

   type TMyArray = array [1 .. 100] of Integer;

Теперь можно описать переменные типа TMyArray:

   var A, B: TMyArray;

Вместо присвоения типа можно явно описать переменные как массивы:

   var A, B : array [1..100] of Integer;

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

var N: Integer;
begin
   N := 65;
   A[5] := 101;
   A[N] := 165;
   A[N+3] := 200;
   B := A;
end;

Иногда требуется узнать верхнюю или нижнюю границу массива. Для этого служат встроенные функции:

   High() – вернёт число, являющееся верхней границей массива;
   Low() – вернёт число, являющееся нижней границей массива.

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

Выражение B := A означает, что каждый элемент массива B будет равен элементу с таким же индексом массива A. Такое присвоение возможно только если оба массива объявлены через некий поименованный тип, или перечислены в одном списке. И в случае:

   var A: array[1..100] of String;
           B: array[1..100] of String;

его использовать невозможно (но возможно поэлементное присвоение B[1] := A[2]; и т.д.).

Массивы могут иметь несколько измерений, перечисляемых через запятую. Например, таблицу из четырёх столбцов и трёх строк:

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

   type MyTable = array[1..4, 1..3] of Integer;
   var X : MyTable;
           Y : Integer;
   begin
       Y:=X[3, 2];   
   end;

Теперь в результате операции присвоения Y будет равен 7.
Многомерный, например, двумерный массив можно описать как массив массивов:

   type TMyArray = array [1 .. 4] of array [1 .. 3] of Integer;

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

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

   type TDinArray = array of Integer;
   var A : TDinArray;

После создания в динамическом массиве нет ни одного элемента. Необходимый размер задаётся в программе специальной процедурой SetLength. Массив из ста элементов:

   begin
    SetLength(A, 100);
   end;

Нижняя граница динамического массива всегда равна нулю. Поэтому индекс массива A может изменяться от 0 до 99.
Многомерные динамические массивы описываются именно как массивы массивов. Например, двумерный:

   type T3DinArray = array of array of Integer;
   var A : T3DinArray;

В программе сначала задаётся размер по первому измерению (количество столбцов):

   SetLength(A, 3);

Затем задаётся размер второго измерения для каждого из трёх столбцов, например:

   SetLength(A[0], 3);
   SetLength(A[1], 2);
   SetLength(A[2], 1);

   Таким образом создаётся треугольная матрица:    A00 A10 A20
A01 A12
A02

Чтобы освободить память, выделенную динамическому массиву, нужно массиву как целому присвоить значение nil:
    A:=nil;
Ключевое слово nil в Delphi означает отсутствие значения.

Записи очень важный и удобный инструмент. Даже не применяя специальные технологии, с его помощью можно создавать собственные базы данных. Записи – это структура данных, каждый элемент которой имеет собственное имя и тип данных. Элемент записи иначе называют поле. Описание записи имеет вид:
   type имя_типа_записи = record
      название_поля : тип_поля ;
      . . .
      название_поля : тип_поля ;
   end;
Названия полей, имеющих одинаковый тип, можно, как и в случае описания переменных, указывать в одну строку через запятую. Для обращения к полю записи сначала указывают имя записи, затем точку, затем имя поля. Например, данные о персонале предприятия могут быть организованы таким типом записи:

   type TPers = record
     Fam, Name, Par : String;
     Year : Integer;
     Dep : String;
   end;
   var Pers : TPers;
   begin
    Pers.Fam:='Иванов';
    Pers.Name:='Иван';
    Pers.Par:='Иванович';
    Pers.Year:=1966;
    Pers.Dep:='Цех №1';
   end;

Теперь осталось записать эти данные в файл, предварительно объявив и его тип как TPers, и база данных готова. С файлом в Delphi также ассоциируется переменная, называемая файловой переменной, которая описывается так:
   VFile : file of тип_файла;
В качестве типа может использоваться любой ограниченный тип Delphi. При этом не допускается тип String, так как он допускает переменный размер до 2 ГБайт. Его необходимо ограничивать: String[N], где N – количество символов. Тип TPers из предыдущего примера должен быть описан, например, так:

   type TPers = record
     Fam, Name, Par : String[20];
     Year : Integer;
     Dep : String[10];
   end;

Теперь переменная такого типа занимает строго определённое место в памяти, и может быть записана в файл. Как это сделать, рассказывается во 2-й части Урока №7.

   Множество – это группа элементов, объединённая под одним именем, и с которой можно сравнивать другие величины, чтобы определить, принадлежат ли они этому множеству. Количество элементов в одном множестве не может превышать 256. Множество описывается так:

   type имя_множества = set of диапазон_значений_множества ;

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

   type TMySet = set of  0 .. 255;
   type TMySet = set of  Byte;

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

   var MySet : TMySet;
   begin
    MySet:=[1, 3 .. 7, 9];
   end;

Чтобы проверить, является ли некое значение элементом множества, применяется оператор in в сочетании с условным оператором:

   var Key : Char;
           Str : String;
   begin
    if Key in ['0' .. '9', '+', '-'] then Str:='Math';
   end;

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

var Digit: set of Char=['1'..'9'];
var Math: Set of Char;
begin
  Math:=Digit+['+', '-', DecimalSeparator*];
end;
*Примечание: DecimalSeparator – встроенная в Delphi константа типа Char, имеющая значение символа-разделителя целой и дробной частей, который может быть равен точке ('.') либо запятой (','), в зависимости от текущих настроек Windows.

Урок Delphi 6. Выражения и операторы Delphi

Выражения Delphi

   В программах Delphi применяются

  • математические выражения
  • логические выражения
  • выражения со строками

ну и другие.

Математические выражения

   В математических выражениях используются операции присваивания :=, сложения +, вычитания , умножения *, деления /, целочисленного деления div, остатка от деления mod.

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

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

X:=1+2*3-4/5;

будет равен не 1, как в случае последовательного выполнения, а 6.2 .

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

X:=((1+2)*3-4)/5;

Вот теперь X будет равен 1.

   Помимо четырёх математических действий в Delphi доступно множество математических функций, таких, например, как тригонометрические, логарифмические, и так далее. Они становятся доступны в программе после добавления в секцию Interface uses модуля Math.

Их описание также можно найти в модуле Math.pas (можно найти воспользовавшись поиском Windows). Многие из них можно реализовать и самому, но встроенные функции наверняка будут работать быстрее и лучше, так далее. написаны на языке ассемблера.

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

   Логические выражения выполняются над операндами логического типа, то есть имеющими тип Boolean Delphi. Они применяются в основном в условных операторах.

Операторы Delphi

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

  • оператора присваивания
  • условного оператора
  • оператора цикла

   С оператором присваивания “:=” мы уже знакомились в уроке Delphi 2. Он работает следующим образом. Переменная, стоящая в левой части оператора, становится равной той величине, которая находится справа. Типы этих величин должны совпадать. В выражении, стоящем справа, также может использоваться переменная, стоящая слева.

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

   var A, B : Integer;
   begin
     A:=3;
     B:=4;
     A:=A*A+B*B;
   end;

В начале фрагмента переменная A равна 3, а в конце -25.

   Условный оператор позволяет изменить порядок выполнения операторов в зависимости от выполнения некоторого условия. Вот как он записывается:

   if условие then действие else альтернатива ;

Слова if (если), then (тогда), else (иначе) – зарезервированные. Действие и else альтернатива – это любые операторы Delphi, или несколько операторов, заключённых в логические скобки begin/end, или вызов подпрограммы. Если условие истинно, то выполняется действие, если ложно, то выполняется альтернатива.
   Условие представляет собой логическое выражение. В нём сравниваются значения выражений (в том числе также и логических), вызов функций, возвращающих значения типа Boolean, и комбинирование этих значений с помощью логических операций:

Знак
операции
Название операции    Логические операции могут комбинироваться с помощью связок:
   and (логическое И)
   or (логическое ИЛИ)
   xor (исключающее ИЛИ)
Для некоторых типов данных есть дополнительные операции. Например, для множеств – оператор in, которая проверяет, входит ли некоторое значение в множество. Например:
      X := [2, 4, 5, 7, 8, 10] ;
Выражение 2 in X истинно (имеет значение true);
Выражение 6 in X ложно (имеет значение false);
   =       Равно   
   <>       Не равно   
   >       Больше   
   <       Меньше   
   >=       Больше или равно   
   <=       Меньше или равно   
   not    Логическое Не – отрицание

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

  • “простой” оператор цикла
  • условный оператор цикла
  • условный оператор повторения

Простой оператор цикла применяется, когда известно количество повторений цикла. Он записывается так:
   for счётчик := выражение-1 to выражение-2
   do действие ;
Счётчик – это переменная, которая должна быть объявлена перед логическим блоком, в котором оператор цикла расположен, и её тип должен относиться к одному из перечислимых типов, обычно Integer.
Выражение-1 и выражение-2 могут быть как константой или идентификатором, так и вызовом функции.
Действие – один или несколько операторов Delphi. Если это группа операторов, то они должны быть заключены в логические скобки begin/end.
   В начале работы оператора переменная-счётчик получает значение выражения-1. Если при этом значение счётчика окажется меньше или равно значению выражения-2, то выполняются операторы, входящие в действие. Это и есть один цикл.

Затем переменная-счётчик принимает значение, следующее за текущим, и начинается новый цикл, то есть сравнение счётчика и выражения-2, выполнение действия, и так далее, до тех пор, пока значение переменной-счётчика не превысит значение выражения-2.
   Возможна работа оператора цикла, при котором переменная-счётчик будет не увеличиваться, а уменьшаться. В этом случае ключевое слово to заменяется на downto:
   for счётчик := выражение-1 downto выражение-2 do действие ;
Соответственно, выражение-1 должно быть больше или равно выражению-2.

Условный оператор цикла удобно использовать в том случае, когда количество повторений заранее не известно:
   while условие do
   тело цикла ;
Этот цикл будет выполняться до тех пор, пока истинно условие (логическое выражение, возвращающее значение типа Boolean). При этом если это выражение сразу равно false, тело цикла не будет выполнено ни разу.
   Нужно очень внимательно следить за написанием условия и контролем завершения цикла, так как в результате ошибки цикл while будет повторяться бесконечное количество раз, что приведёт к “зацикливанию” и “зависанию” программы.

Условный оператор повторения сначала выполняет тело цикла, а затем уже проверяет выполнение условия:
   repeat
   тело цикла
   until условие ;
Таким образом, этот вариант цикла гарантирует, что тело цикла будет выполнен по крайней мере один раз. И будет выполняться до тех пор, пока условие не станет истинным (то есть true). Стоит отметить, что это единственный оператор Delphi, в котором тело цикла не требуется заключать в логические скобки begin/end. Начало и конец тела цикла определяются по ключевым словам repeat и until.

   Вместе с операторами цикла используются специальные команды:

  • команда прерывания цикла
  • команда продолжения цикла

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

   Справедливости ради стоит рассказать об ещё одном операторе, позволяющем изменить последовательность выполнения программы. Это оператор перехода:
   goto метка ;
В качестве метки может использоваться любой допустимый идентификатор или число в диапазоне от 0 до 9999. Метку предварительно необходимо объявить в разделе описания переменных, но с помощью не ключевого слова var, а ключевого слова label:
   label меткa ;
или
   label список меток ;

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

   var X, Y: Integer;
   label A, B;
   begin
    A: X:=5 ;
       . . .
    операторы программы
    goto B;
       . . .
    B: Y:=25;
    goto A;
   end;

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

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

Урок Delphi 7. Работа с файлами в Delphi

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

   Для “лирического” вступления нужно упомянуть компоненты Delphi, которые умеют работать с файлами. Они читают и сохраняют своё содержимое, строки типа String, в файл текстового формата. Это компоненты ListBoxComboBox и Memo, расположенные на первой же вкладке палитры компонентов.

   Каждая строка компонентов ListBox и ComboBox является объектом Items[i], а Memo – Lines[i], где i – номер строки, который отсчитывается от нуля. Добавление строк в компоненты выполняется методами Add и Insert:

Delphi

begin
   Memo1.Lines.Add(‘Первая строка’);
   ComboBox1.Items.Add(‘Первая строка’);
   ComboBox1.Items.Add(‘Вторая строка’);
   ListBox1.Items.Add(‘Первая строка’);
   ListBox1.Items.Add(‘Вторая строка’);
  end ;

Метод Add добавляет новую строку в конец. Метод Insert имеет дополнительный параметр, указывающий, после какой строки разместить новую строку. Доступ к строкам осуществляется так:

   ComboBox1.Items[0] := ‘Первая строка изменилась‘ ;
   ListBox1.Items[1] := ‘Вторая строка изменилась‘ ;

У компонента ComboBox дополнительно есть свойство Text, где (как и у компонента Edit) находится вводимый текст:

   ComboBox1.Text := ‘ Вводимый текст ‘;

На выделенную в данный момент строку компонента ComboBox указывает свойство ItemIndex типа Integer, то есть это номер выделенной строки. Следовательно, получить саму выделенную строку компонента ComboBox можно следующей конструкцией:

   S:=ComboBox1.Items[ComboBox1.ItemIndex];

или, пользуясь оператором присоединения

   With ComboBox1 do
    S:=Items[ItemIndex];

Вот как по нажатию клавиши Enter можно заносить в этот компонент вводимую в строку информацию и удалять нажатием Escape:
Выделите на Форме ComboBox и перейдите в Инспектор объектов, на вкладку Events. Щёлкните дважды по обработчику OnKeyPress. Система Delphi создаст заготовку обработчика. Напишите:
  begin
   if Key=#13 then
      ComboBox1.Items.Add(ComboBox1.Text);
   if Key=#27 then
      ComboBox1.Items.Delete(ComboBox1.Items.Count-1);
  end ;
Key – определённая в этом обработчике переменная, содержащая код нажатой клавиши, #13 и #27 – коды клавиш Enter и Escape соответственно. Items.Count – количество содержащихся в компоненте строк. Так как отсчёт строк идёт от нуля, мы отнимаем единицу.

После очередного удаления количество строк меняется, таким образом, Items.Count-1 всегда указывает на последнюю строку. Последовательно нажимая Escape, мы можем удалить все строки. Командой
   ComboBox1.Items.Delete(0);
можно добиться того же эффекта, только удаляться будут первые строки. Впрочем, чтобы стереть всё сразу, есть метод Clear!

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

   ListBox1.Items.SaveToFile(‘ Имя_файла.txt ‘) ;

Впрочем, расширение можно поставить любое по желанию, не обязательно .txt, как и вообще без него обойтись. Но расширение .txt позволит легко открыть файл стандартным виндовским Блокнотом, что бывает очень удобно на этапе написания программы!
Для загрузки служит метод LoadFromFile:

   ListBox1.Items.LoadFromFile(‘ Имя_файла.txt ‘) ;

Что делать, если в своей программе мы не работаем с компонентами ComboboxListBox или Memo, а сохранять информацию нужно? Берём один из компонентов и делаем его невидимым, для этого в Инспекторе Объектов ставим в свойство Visible значение False. Функциональность его от этого не изменится!

Последний штрих – создадим программу, сохраняющую своё положение на экране в момент закрытия и там же открывающуюся. Нам нужно сохранить два параметра – значения свойств Формы Left и Top, это расстояние от левого и верхнего краёв экрана соответственно. Значения эти выражаются в пикселях и имеют тип Integer. Необходимо перевести эти числа в строку (тип String) с помощью оператора IntToStr. Итак, разместите на Форме невидимый ListBox, щёлкните по пустому месту Формы, чтобы её свойства появились в Инспекторе объектов, и перейдите на вкладку Events. Щёлкните по обработчику OnClose и в созданной заготовке напишите:

  begin
   ListBox1.Items.Clear;
   ListBox1.Items.Add(IntToStr(Form1.Left));
   ListBox1.Items.Add(IntToStr(Form1.Top));
   ListBox1.Items.SaveToFile(‘MyFormPos.txt’);
  end ;

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

  begin
   if FileExists(‘MyFormPos.txt’) then
    begin
     ListBox1.Items.LoadFromFile(‘MyFormPos.txt’);
     Form1.Left:=StrToInt(ListBox1.Items[0]);
     Form1.Top:=StrToInt(ListBox1.Items[1]);
    end ;
  end ;

   В первой строке происходит проверка на существование файла, ведь если его не будет, произойдёт ошибка. Впрочем, программа после выдачи предупреждения откроется в том месте, где была на этапе проектирования, а при закрытии нужный файл будет воссоздан!
   Затем в логических скобках begin / end содержится сам код, который будет выполнен только при наличии файла MyFormPos.txt в папке с программой, так как используется относительный путь. Можно указать конкретное местоположение, например, C:Program FilesMyProgMyFormPos.txt.

Урок Delphi 8. Работа с дополнительными формами Delphi

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

   Ввести новую форму в программу проще всего нажатием на кнопочку на главном окне Delphi. Также есть и соответствующая команда меню File -» New -» Form

Delphi

Форма создаётся вместе с новым модулем, описывающим её работу. Сразу же покажем, как удалить Форму из программы. Для этого также есть кнопочка, и команда меню Project -» Remove from project…. Так как Форма создаётся вместе с её модулем, то в появившемся окошке нужно выбрать модуль, который и будет удалён из проекта вместе с Формой:

Как работать в Delphi: конкретные уроки

Как работать в Delphi: конкретные уроки

Сразу возникает вопрос, а что будет, если попытаться удалить и модуль Unit1, что останется?. Выполните команду Project -» View Sourse. В редакторе кода появится новая вкладка, на которой будет отображён код Главного Окна программы (не Главной Формы, а именно Окна. В Windows ведь все объекты рассматриваются как окна.) Главное окно невидимо, но управляет всем проектом, и может работать вообще без Форм. Туда можно вставлять свой код, и писать нехилые программы, как в классическом Паскале.

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

   Во-первых, нужно отменить автосоздание форм. Выполните команду меню Project -» Options… В появившемся окошке отображаются Main form (главная Форма), Auto-create (автосоздаваемые) и Available (доступные) формы проекта. Нам нужно перевести Форму из разряда автосоздаваемых в разряд доступных Форм. Делается это нажатием кнопки ” > ” (обратная операция – нажатием кнопки ” < “):

Как работать в Delphi: конкретные уроки

Как работать в Delphi: конкретные уроки

Таким образом, главная Форма Form1 создаётся сама, а дополнительную форму Form2 мы создадим в программе при необходимости.

   Если этого ничего мы не предприняли (что вполне допустимо при малом количестве дополнительных форм), то для появления новой Формы на экране достаточно написать:

   Form2.Show; // в случае обычной Формы
   Form2.ShowModal; // в случае модальной Формы

Если же мы перевели дополнительные Формы в разряд доступных, то перед каждым вызовом такой Формы необходимо делать проверку на существование Формы (оператором Assigned) таким образом:

   if (not Assigned(Form2)) then   // проверка существования Формы (если нет, то
       Form2:=TForm2.Create(Self);    // создание Формы)
   Form2.Show; // (или Form2.ShowModal) показ Формы

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

   При попытке компилирования программы, содержащей вызов второй формы, Delphi выдаст такой запрос:

Как работать в Delphi: конкретные уроки

означающий:

Форма Form1 содержит вызов формы Form2, которая объявлена в модуле Unit2, но который отсутствует в списке используемых модулей. Вы хотите добавить его?

Нужно разрешить, и в начале модуля перед директивой
{$R *.dfm}
будет добавлена фраза
uses Unit2;
В принципе, можно добавить её туда перед компиляцией “ручками”, и тогда запроса не будет. Но смысл? Отвечаем “Yes” и снова жмём F9.

   Первым делом введём в форму операцию её закрытия! Сделать это можно несколькими способами. Возьмём кнопку, напишем “Закрыть” и в обработчике OnClick напишем:

Form2.Close; // В принципе, достаточно просто Close;

   Этот же оператор работает при вызове его из меню формы, если меню, конечно, туда ввести (компонент MainMenu на вкладке Standard), о чём в дальнейшем обязательно поговорим!

   Теперь же необходимо рассмотреть способ закрытия Формы, который относится именно к модальным формам. Он используется диалоговыми окнами с вопросом, требующим подтверждения, и в других аналогичных случаях. На Форме нужно расположить несколько кнопок, нажатие которых предполагает соответствующий ответ: “Да”, “Нет”, “Отмена”, и т.д.
   У каждой кнопки есть свойство ModalResult, среди значений которой mrYesmrNomrCansel и другие (посмотрите!). Значение ModalResult выбранной кнопки передаётся свойству ModalResult Формы. Это свойство отсутствует в списке свойств Формы, которые можно увидеть в Инспекторе Объектов, но программно оно доступно (напишите ” Form2 “, поставьте точку и поищите в появившемся списке!).
   Нажатие кнопки со значением свойства ModalResult, отличного от mrNone, приводит к закрытию Формы, даже если у кнопки отсутствует обработчик нажатия! Затем можно проанализировать свойство ModalResult Формы и выяснить, какой же ответ на поставленный вопрос дал пользователь:

procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.ShowModal;
if Form2.ModalResult=mrYes then   // Этот оператор будет доступен только после закрытия Form2
  Form1.Caption:='Пользователь ответил положительно!';
end;

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

Для этого необходимо указывать уже имя модуля. Например, для обращения к переменной X из модуля Unit2 пишем так: Unit2.X.
   Имеющейся возможности укрыть данные от использования в других модулях касаться пока не будем.

   В момент закрытия Формы часто в программе необходимо выполнить определённые операции. Делается это в обработчике события OnClose Формы. А теперь рассмотрим блокировку закрытия Формы.

Если вдруг понадобится заставить пользователя выполнить определённые действия перед закрытием Формы (это касается как дополнительных форм, так и основной Формы программы), нужно воспользоваться обработчиком события OnCloseQuery.

В этом обработчике определена переменная логического типа CanClose. Форма будет закрыта только в том случае, когда
   CanClose:=True;
Например, если создать такой обработчик OnCloseQuery основной Формы программы:

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose:=False;
end;

то пользователь просто не сможет закрыть программу иначе как через Диспетчер задач Windows!

Урок Delphi 9. Создаём и используем подпрограммы Delphi

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

   Вообще, существует методика программирования “сверху вниз”. Методика программирования “сверху вниз” разбивает задачу на несколько более простых, которые оформляются в виде подпрограмм. Те, в свою очередь, при необходимости также делятся до тех пор, пока стоящие перед программистом проблемы не достигнут приемлемого уровня сложности (то есть простоты!).

Таким образом, эта методика программирования облегчает написание программ за счёт создания так называемого скелета, состоящего из описателей подпрограмм, которые в дальнейшем наполняются конкретными алгоритмами. Пустое описание подпрограммы иначе называется “заглушкой”.

   И процедуры, и функции позволяют добиться одинаковых результатов. Но разница всё же есть.

   Процедура Delphi просто выполняет требуемые операции, но никаких результатов своих действий не возвращает. Результат – в тех изменениях, которые произошли в программе в процессе выполнения этой процедуры.

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

   Функция Delphi также позволяет выполнить всё перечисленное, но дополнительно возвращает результат в присвоенном ей самой значении. То есть вызов функции может присутствовать в выражении справа от оператора присваивания. Таким образом, функция – более универсальный объект!

   Описание подпрограммы состоит из ключевого слова procedure или function, за которым следует имя подпрограммы со списком параметров, заключённых в скобки. В случае функции далее ставится двоеточие и указывается тип возвращаемого значения.

Обычная точка с запятой далее – обязательна! Сам код подпрограммы заключается в “логические скобки” begin/end. Для функции необходимо в коде присвоить переменной с именем функции или специальной зарезервированной переменной Result (предпочтительно) возвращаемое функцией значение. Примеры:

   procedure Имя_процедуры(параметры);
   begin
    Код процедуры;
   end;

   function Имя_функции(параметры): тип_результата;
   begin
    Код функции;
    Result:=результат;
   end;

   Описанная таким образом подпрограмма должна быть размещена в основной программе до первого её вызова. Иначе при компиляции получите извещение о том, что “неизвестный идентификатор…” Следить за этим не всегда удобно. Есть выход – разместить только заголовок подпрограммы там, где размещают описания всех данных программы.

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

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

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

Место их описания – между заголовком и началом логического блока – ключевым словом begin. Имена локальных данных могут совпадать с именами глобальных. В этом случае используется локальная переменная, причём её изменение не скажется на глобальной с тем же именем.
   Совершенно аналогично локальным типам, переменным, константам могут быть введены и локальные процедуры и функции, которые могут быть описаны и использованы только внутри данной подпрограммы.

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

Delphi

var
  Form1: TForm1;
  A, B, Summa: Integer;
  procedure Sum(A, B: Integer);

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 A:=StrToInt(Edit1.Text);
 B:=StrToInt(Edit2.Text);
 Sum(A, B);
 Caption:=IntToStr(Summa);
end;

procedure Sum(A, B: Integer);
begin
 Summa:=A+B;
end;

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

var
  Form1: TForm1;
  A, B, Summa: Integer;
  function Sum(A, B: Integer): Integer;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 A:=StrToInt(Edit1.Text);
 B:=StrToInt(Edit2.Text);
 Summa:=Sum(A, B);        // На мой взгляд, сейчас более понятно, откуда что берётся
 Caption:=IntToStr(Summa);
end;

function Sum(A, B: Integer): Integer;
begin
 Result:=A+B;
end;

   Есть особенности в использовании в качестве параметров больших по объёму структур данных, например, массивов, состоящих из нескольких тысяч (и больше) элементов. При передаче в подпрограмму данных большого объёма могут быть большие расходы ресурсов и времени системы.

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

function Sum(A, B: Integer; var Arr: array[1..1000000] of Integer): Integer;

   Если взглянуть на описание нашей подпрограммы и описание обработчика нажатия кнопки (это тоже подпрограмма!), который был создан Delphi, то видим, что перед именем обработчика (Button1Click) стоит TForm1. Как мы знаем, в Delphi точкой разделяется объект и его атрибуты (свойства и методы).

Таким образом, Delphi создаёт Button1Click как метод объекта Form1. Причём, буква T перед объектом говорит о том, что Button1Click не просто метод объекта, а метод класса объекта. Не будем этим пока заморачиваться, а просто будем поступать также.

Описав свою процедуру или функцию как метод класса TForm1, мы получаем возможность использовать в ней объекты класса без указания его имени, что гораздо удобнее. То есть, если мы используем в нашей подпрограмме какие-либо компоненты, размещённые на Форме (например, Button1), то мы пишем

Button1.Width:=100;   //Ширина кнопки
   а не
Form1.Button1.Width:=100;

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

   Описав подпрограмму как метод класса, её описание мы должны поместить туда же, куда их помещает Delphi – в описание класса TForm1. Смотрите сами, где находится описание процедуры Button1Click. Для этого, поставив курсор внутрь подпрограммы Button1Click, нажмите CTRL+Shift и кнопку управления курсором “Вверх” или “Вниз” одновременно.

Произойдёт переход к описанию подпрограммы (чтобы вернуться обратно, повторите это действие ещё раз). Ставьте описание своей подпрограммы рядом, с новой строки. Обратите внимание, что TForm1 уже не пишется.

   Рекурсия – важное и мощное свойство процедур и функций в Delphi. Рекурсия это возможность подпрограммы в процессе работы обращаться к самой себе. Без использования рекурсии приходилось бы применять циклы, а это усложняет чтение программы. Рекурсивный вызов подпрограммы сразу проясняет смысл происходящего.

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

Пример. Вычисление факториала

   

Вычисление факториала – классическая в программировании задача на использование рекурсииФакториал числа N – результат перемножения всех чисел от 1 до N (обозначается N!):

N! = 1*2* ... *(N-1)*N = N*(N-1)!

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

   Удобство применения рекурсии особенно наглядно при вычислении дискриминанта матрицы. Дискриминант матрицы можно подсчитать методом Гаусса – приведением матрицы к треугольному виду, что требует использования нескольких вложенных циклов. Алгоритм получается достаточно громоздкий. Используя вместо этого рекурсию, получается очень элегантный алгоритм: вычисление дискриминанта матрицы с использованием рекурсии.

Урок Delphi 10. Исключительные ситуации в Delphi

Исключительные ситуации в Delphi встречаются постоянно. Исключительная ситуация это такая ситуация, в результате которой генерируется ошибка, и выполнение программы прерывается.

Именно потому такая ситуация и называется исключительной. Например, деление на ноль – классический пример исключительной ситуации.

   Как в такой ситуации действует человек? Если он пытается что-то сделать, и это не получается – он идёт другим путём. Так же и компьютер, следующий программе, умеющей обрабатывать исключительные ситуации.

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

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

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

   Вот как выглядит оператор контроля исключительных ситуаций:

try
   основные операторы фрагмента;
except
   альтернативный вариант фрагмента;
end;

   Вначале производится попытка выполнить операторы секции try/except, содержащие основной вариант программы. При возникновении в каком-либо операторе этой секции исключительной ситуации остальные операторы секции пропускаются, и выполняется секция except/end. Если всё “проходит штатно”, то секция except/end пропускается.

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

try
   операторы
finally
   заключительные действия
end;
   Основные операторы, находящиеся в секции try, могут пройти штатно, или вызвать исключительную ситуацию. Операторы заключительных действий, находящиеся в секции finally, будут выполнены в любом случае.

   Есть ещё один способ контроля исключительных ситуаций, касающийся ошибок операций ввода-вывода.
Перед участком программы, где возможны ошибки ввода-вывода (а это, по сути, все операторы ввода-вывода), ставится директива {$I-}, заставляющая компилятор не включать в код автоконтроль ошибок ввода-вывода.

Таким образом, в случае ошибки ввода или вывода программа не прерывается. В конце участка с операторами ввода-вывода ставится директива, включающая автоконтроль: {$I+}. Затем анализируется результат вызова функции IOResult. Если функция IOResult (вызывается без параметров) возвращает 0, значит ошибок ввода-вывода на данном участке не было.

Вот какой пример использования директив {$I} и функции IOResult содержит справка системы Delphi:

var
  F: file of Byte;
begin
  if OpenDialog1.Execute then
  begin
    AssignFile(F, OpenDialog1.FileName);
    {$I-}
    Reset(F);
    {$I+}
    if IOResult = 0 then
    begin
      MessageDlg('File size in bytes: ' + IntToStr(FileSize(F)), mtInformation, [mbOk], 0);
      CloseFile(F);
    end
    else
      MessageDlg('File access error', mtWarning, [mbOk], 0);
  end;
end;

   Функция IOResult досталась Delphi в наследство от Turbo Pascal. Тот же самый фрагмент можно составить и с использованием оператора try. На мой взгляд, это удобнее и проще.

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

Или можно отключить реакцию системы на исключительные ситуации, тем самым давая возможность отработать специально для этого написанным фрагментам программы – нашим операторам try/except/end. Для этого откроем пункт системного меню Delphi Tools -> Debugger Options....

В появившемся окошке нужно снять галку в чекбоксе Stop on Delphi Exceptions, расположенном на вкладке Language Exceptions. Теперь система Delphi будет предоставлять вашей программе возможность самостоятельно обрабатывать исключительные ситуации, среди которых могут быть и ситуации, возникновение которых прописано специально как удобный инструмент достижения необходимых результатов.

Урок Delphi 11. Обзор компонентов Delphi

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

Страница Standart

   Изучение Delphi естественным образом начинается со страницы палитры компонентов Standart. На этой странице расположены стандартные для Windows интерфейсные элементы, такие как главное и всплывающее меню, кнопка, однострочный и многострочный редакторы, переключатели, метки, списки, и некоторые другие компоненты, применяющиеся наиболее часто.

Страница Additional

   На страницу Additional помещены дополнительные компоненты, без некоторых из которых сегодня трудно представить программу для Windows: кнопки с дополнительными свойствами, таблицы, компоненты для размещения изображений…

Страница Win32

   Эта страница содержит компоненты, представляющие собой интерфейсные элементы для 32-разрядных операционных систем Windows 95/98/NT (В версии системы Delphi 2 эта страница называлась Win95). Использующие эти компоненты программы выглядят в стилистике последних версий операционных систем Windows.

Страница System

   На этой странице представлены компоненты, которые имеют различное функциональное назначение (например, Timer – очень важный в любой программе компонент), в том числе компоненты, поддерживающие стандартные для Windows технологии межпрограммного обмена данными OLE и DDE.

Урок Delphi 12. Работа со строками Delphi

Работа со строками Delphi позволяет извлечь из строки необходимую информацию и представить её в нужном виде. Система предоставляет весь спектр необходимых функций для работы со строками Delphi и преобразования строк Delphi в необходимые форматы:

  • числовой формат, целый и дробный с плавающей точкой;
  • формат времени, даты, даты-времени;
  • преобразование символов к верхнему или нижнему регистру;
  • сравнение строк, поиск в строке и копирование подстроки;
    и многие другие…

   Непосредственно сами строки Delphi поддерживают единственную операцию, так называемую операцию конкатенации, то есть присоединения. Несмотря на “научное” название, операция конкатенации выполняет очень простую процедуру. С помощью операции конкатенации одна строка присоединяется к другой:

var S, S1, S2: String;
begin
 S:=S1+S2;
end;

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

   function Length(S: String): Integer;

   Delphi работает со строками типа String, в котором длина строки записывается в начале строки, перед первым символом. Поэтому индекс первого символа в строке не 0, а 1. То есть, если:

S:='Строка типа String';

то S[1] - символ 'С', S[2] - символ 'т', последний символ в строке – S[Length(S)], равный 'g'.

   Однако часто приходится иметь дело со строками типа PChar, которые использует операционая система Windows. В строках типа PChar длина строки определяется специальным символом конца строки – #0. Поэтому для использования функций Windows тип String необходимо предварительно переводить в тип PChar. Преобразование типа String в тип PChar выполняет функция

   function PChar(S: String): PChar;

   Для полноценной работы со строками Delphi используются следующие стандартные процедуры и функции:

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

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

 функция IntToStr(N: Integer): String
 Преобразует целое число N в строку.
 функция StrToInt(S: String): Integer
 Преобразует строку S в целое число.
 функция FloatToStr(X: Extended): String
 Преобразует число с плавающей точкой X в строку.
 функция StrToFloat(S: String): Extended
 Преобразует строку S в число с плавающей точкой.

Процедуры и функции преобразования дат и времени

Сначала собственно функции, предоставляющие информацию о текущих дате и времени:

 функция Now: TDateTime
 Возвращает текущую дату и время.
 функция Date: TDateTime
 Возвращает текущую дату.
 функция Time: TDateTime
 Возвращает текущее время.

Далее, функции, работающие с составляющими даты и времени (год, месяц, число, день недели, часы, минуты, секунды и даже миллисекунды):

 функция DayOfWeek(Date: TDateTime): Integer
 Возвращает текущий номер дня недели: 1 – воскресенье, 7 – суббота.
 процедура DecodeDate(Date: TDateTime; var Year, Month, Day: Word)
 Разбивает дату Date на год – Year, месяц – Month и день – Day.
 процедура DecodeTime(Time: TDateTime; var Hour, Min, Sec, MSec: Word)
 Разбивает время Time на час – Hour, минуты – Min, секунды – Sec и миллисекунды – MSec.
 функция EncodeDate(Year, Month, Day: Word): TDateTime
 Объединяет год – Year, месяц – Month и день – Day в значение типа TDateTime.
 функция EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime
 Объединяет час – Hour, минуты – Min, секунды – Sec и миллисекунды – MSec в значение типа TDateTime.

Наконец, собственно, функции, переводящие дату и время из формата TDateTime в строчный формат:

 функция DateTimeToStr(DateTime: TDateTime): String
 Преобразует дату и время DateTime в строку.
 функция DateToStr(Date: TDateTime): String
 Преобразует дату Date в строку.
 функция TimeToStr(Time: TDateTime): String
 Преобразует время Time в строку.

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

 функция AnsiLowerCase(const S: String): String
 Возвращает строку S, преобразованную к нижнему регистру.
 функция AnsiUpperCase(const S: String): String
 Возвращает строку S, преобразованную к верхнему регистру.
 функция Length(const S: String): Integer
 Возвращает количество символов в строке S.
 функция Trim(const S: String): String
 Удаляет из строки S начальные и завершающие пробелы и управляющие символы.
 функция TrimLeft(const S: String): String
 Удаляет из строки S начальные пробелы и управляющие символы.
 функция TrimRight(const S: String): String
 Удаляет из строки S завершающие пробелы и управляющие символы.

Следующие функции сравнивают две строки между собой:

 функция AnsiCompareStr(const S1, S2: String): Integer
 Сравнивает две строки S1 и S2 с учётом регистра символов.
 Возвращает значение <0 если S1<S2, 0 если S1=S2, >0 если S1>S2
 функция AnsiCompareText(const S1, S2: String): Integer
 Сравнивает две строки S1 и S2 без учёта регистра символов.
 Возвращает значение <0 если S1<S2, 0 если S1=S2, >0 если S1>S2

Следующие функции осуществляют поиск в текущей строке подстроки, вставляют, удаляют или заменяют подстроку:

 функция Pos(Substr: String; Str: String): Integer
 Возвращает позицию (индекс) первого вхождения Substr в строке Str. Если Substr нет в Str, возвращает 0.
 функция Insert(Source: String; var S: String; Index: Integer): Integer
 Вставляет строку Source в строку S, начиная с номера символа, равного Index
 процедура Delete(var S: String; Index, Count: Integer)
 Удаляет из строки S подстроку, начинающуюся с номера символа, равного Index, и содержащую до Count символов.
 функция StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): String
 Заменяет в строке S подстроку OldPattern на строку NewPattern с учётом флага TReplaceFlags. Для работы с этой функцией нужно создать переменную типа TReplaceFlags – это множество, и включить в него одно или оба значения из следующих:
   rfReplaceAll – будут заменены все вхождения. Если это значение не будет включено во множество, то будет заменено только первое вхождение;
   rfIgnoreCase – замена будет без учёта регистра символов. Если это значение не будет включено во множество, то замена будет чувствительна к регистру символов.

Наконец, функция копирования части строки:

 функция Copy(S: String; Index, Count: Integer): String
 Возвращает подстроку строки S, начиная с номера символа, равного Index и содержащую до Count символов.

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

function RealToStr(X: Real; Count: Integer): String;//Count - количество цифр после запятой
var S: String;
    N: Integer;
begin
  S:=FloatToStr(X); //после запятой - длинная последовательность цифр
//DecimalSeparator - константа, содержащая истинный разделитель целой и дробной частей числа   N:=Pos(DecimalSeparator, S); //позиция запятой в строке
//вычисляем длину строки с нужным количеством знаков после запятой:
  if N=0//если в строке нет запятой - это целое число, и
    then N:=Length(S)//тогда просто выводим это число
    else N:=N+Count;//иначе вычисляем длину строки
  Result:=Copy(S, 1, N);//копируем часть строки в результат
end;

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

Это тоже интересно:

GO программирование: самое начало работы.

Пишем первую программу на Go.

Добавить комментарий