Как сделать листинг программы delphi
Чтобы полностью понять и почувствовать все преимущества Delphi, Вам нужно хорошо изучить язык Object Pascal. И хотя возможности визуальной части Delphi чрезвычайно богаты, хорошим программистом может стать только тот, кто хорошо разбирается в технике ручного написания кода.
По мере обсуждения темы данного раздела мы рассмотрим несколько простых примеров, которые, тем не менее, демонстрируют технику использования важных управляющих элементов Windows.
Создание методов с помощью визуальных средств
В предыдущем уроке Вы видели, что синтаксический "скелет" метода может быть сгенерирован с помощью визуальных средств. Для этого, напомним, нужно в Инспекторе Объектов дважды щелкнуть мышкой на пустой строчке напротив названия интересующего Вас события в требуемом компоненте. Заметим, если эта строчка не пуста, то двойной щелчок на ней просто переместит Вас в окне Редактора Кода в то место, где находится данный метод.
Для более глубокого понимания дальнейшего изложения кратко остановимся на концепции объектно-ориентированного программирования. Для начала определим базовое понятие объектно-ориентированного программирования - класс. Класс - это категория объектов, обладающих одинаковыми свойствами и поведением. При этом объект представляет собой просто экземпляр какого-либо класса. Например, в Delphi тип "форма" (окно) является классом, а переменная этого типа - объектом. Метод - это процедура, которая определена как часть класса и инкапсулирована (содержится) в нем. Методы манипулируют полями и свойствами классов (хотя могут работать и с любыми переменными) и имеют автоматический доступ к любым полям и методам своего класса. Доступ к полям и методам других классов зависит от уровня "защищенности" этих полей и методов. Пока же для нас важно то, что методы можно создавать как визуальными средствами, так и путем написания кода вручную.
Давайте рассмотрим процесс создания программы CONTROL1, которая поможет нам изучить технику написания методов в Delphi.
Рис. Ошибка! Текст указанного стиля в документе отсутствует.-A: Главная форма программы CONTROL1
Для создания программы CONTROL1 поместите с помощью мышки компонент Edit (находится на страничке "Standard" Палитры Компонентов) на форму. После этого ваша форма будет иметь вид, показанный на Рис. Ошибка! Текст указанного стиля в документе отсутствует.-A.
Рис. Ошибка! Текст указанного стиля в документе отсутствует.-B:Чтобы создать метод, просто дважды щелкните справа от слова OnDblClick
Теперь перейдите в Object Inspector, выберите страничку "Events" и дважды щелкните в пустой строчке напротив события OnDblClick, как показано на Рис. Ошибка! Текст указанного стиля в документе отсутствует.-B. После этого в активизировавшемся окне Редактора Вы увидите сгенерированный "скелет" метода Edit1DblClick, являющегося реакцией на событие OnDblClick:
После генерации процедуры Вы можете оставить ее имя таким, каким "установил" Delphi, или изменить его на любое другое (для этого просто введите новое имя в указанной выше строке Инспектора Объектов справа от требуемого события и нажмите Enter).
Теперь в окне Редактора Кода введите смысловую часть метода:
Сохраните программу. Во время выполнения дважды щелкните на строке редактирования. Текст в этой строке изменится в соответствии с тем, что мы написали в методе Edit1DblClick: см. Рис. Ошибка! Текст указанного стиля в документе отсутствует.-C.
Рис. Ошибка! Текст указанного стиля в документе отсутствует.-C: Содержимое управляющего элемента TEdit изменяется после двойного щелчка по нему
Листинг Ошибка! Текст указанного стиля в документе отсутствует.-A и Листинг Ошибка! Текст указанного стиля в документе отсутствует.-B предоставляют полный код программы CONTROL1.
Листинг Ошибка! Текст указанного стиля в документе отсутствует.-A: Программа CONTROL1 демонстрирует, как создавать и использовать методы в Delphi.
Листинг Ошибка! Текст указанного стиля в документе отсутствует.-B: Головной модуль программы CONTROL1.
После того, как Ваша программа загрузится в память, выполняются две строчки кода в CONTROL1.DPR, автоматически сгенерированные компилятором:
Первая строка запрашивает память у операционной системы и создает там объект Form1, являющийся экземпляром класса TForm1. Вторая строка указывает объекту Application, "по умолчанию" декларированному в Delphi, чтобы он запустил на выполнение главную форму приложения. В данном месте мы не будем подробно останавливаться на классе TApplication и на автоматически создаваемом его экземпляре - Application. Важно понять, что главное его предназначение - быть неким ядром, управляющим выполнением Вашей программы.
Как правило, у большинства примеров, которыми мы будем оперировать в наших уроках, файлы проектов .DPR практически одинаковы. Поэтому в дальнейшем там, где они не отличаются кардинально друг от друга, мы не будем приводить их текст. Более того, в файл .DPR, автоматически генерируемый Delphi, в большинстве случаев нет необходимости заглядывать, поскольку все действия, производимые им, являются стандартными.
Итак, мы видели, что большинство кода Delphi генерирует автоматически. В большинстве приложений все, что Вам остается сделать - это вставить одну или несколько строк кода, как в методе Edit1DblClick:
Хотя внешний интерфейс программы CONTROL1 достаточно прост, она (программа) имеет строгую внутреннюю структуру. Каждая программа в Delphi состоит из файла проекта, имеющего расширение .DPR и одного или нескольких модулей, имеющих расширение .PAS. Модуль, в котором содержится главная форма проекта, называется головным. Указанием компилятору о связях между модулями является предложение Uses, которое определяет зависимость модулей.
- Заголовок
- Секция Interface
- Секция Implementation
Таким образом, "скелет" модуля выглядит следующим образом:
В интерфейсной секции (interface) описывается все то, что должно быть видимо для других модулей (типы, переменные, классы, константы, процедуры, функции). В секции implementation помещается код, реализующий классы, процедуры или функции.
Передача параметров
- создавать свои собственные процедуры
- добавлять процедуру в класс, формируя метод класса
- вызывать одну процедуру из другой.
Программа PARAMS позволяет Вам вводить фразы в строки редактирования. После нажатия кнопки "Вызов процедуры WriteAll" строка из управляющего элемента EditSource скопируется в шесть управляющих элементов - строк редактирования, как показано на Рис. Ошибка! Текст указанного стиля в документе отсутствует.-D.
Далее мы не будем подробно останавливаться на том, как размещать компоненты на форме - считаем, что это Вы уже умеете. После того как Вы разместили на форме семь компонентов Edit, переименуйте с помощью Инспектора Объектов седьмой компонент (Edit7) в EditSource. Положите на форму компонент Button, и в Object Inspector измените его заголовок (свойство Caption) на "Вызов процедуры WriteAll" (естественно, Вы можете заменить его шрифт, цвет и т.д.).
Рис. Ошибка! Текст указанного стиля в документе отсутствует.-D: Программа PARAMS позволяет вызовом одной процедуры заполнить 6 строк редактирования
После завершения проектирования формы класс TForm1 будет выглядеть следующим образом:
- Перейти в Инспекторе Объектов на страничку "Events" (предварительно выбрав компонент Button1 на форме), выбрать слово OnClick и дважды щелкнуть мышкой на пустой строчке справа от него
- Просто дважды щелкнуть на компоненте Button1 на форме.
Delphi сгенерирует следующую "заготовку":
Цель программы PARAMS - научить Вас писать процедуры и передавать в них параметры. В частности, программа PARAMS реагирует на нажатие кнопки Button1 путем вызова процедуры WriteAll и передачи ей в качестве параметра содержимого строки редактирования EditSource (EditSource.Text).
Важно понять, что объект EditSource является экземпляром класса TEdit и, следовательно, имеет свойство Text, содержащее набранный в строке редактирования текст. Как Вы уже, наверное, успели заметить, по умолчанию свойство Text содержит значение, совпадающее со значением имени компонента (Name)- в данном случае "EditSource". Свойство Text Вы, естественно, можете редактировать как в режиме проектирования, так и во время выполнения.
Текст, который должен быть отображен в шести строках редактирования, передается процедуре WriteAll как параметр. Чтобы передать параметр процедуре, просто напишите имя этой процедуры и заключите передаваемый параметр (параметры) в скобки - вот так:
Заголовок этой процедуры выглядит следующим образом:
где указано, что передаваемый процедуре параметр NewString должен иметь тип String.
Вспомним, что задача процедуры WriteAll состоит в копировании содержимого строки редактирования EditSource в шесть других строк редактировани Edit1-Edit6. Поэтому процедура должна выглядеть следующим образом:
Возвратимся еще раз к заголовку процедуры. Заголовок состоит из пяти частей:
Первая часть - зарезервированное слово "procedure"; пятая часть - концевая точка с запятой ";". Обе эти части служат определенным синтаксическим целям, а именно: первая информирует компилятор о том, что определен синтаксический блок "процедура", а вторая указывает на окончание заголовка (собственно говоря, все операторы в Delphi должны заканчиваться точкой с запятой).
Вторая часть заголовка - слово "TForm1", которое квалифицирует то обстоятельство, что данная процедура является методом класса TForm1.
Третья часть заголовка - имя процедуры. Вы можете выбрать его любым, по вашему усмотрению. В данном случае мы назвали процедуру "WriteAll".
Четвертая часть заголовка - параметр. Параметр декларируется внутри скобок и, в свою очередь, состоит из двух частей. Первая часть - имя параметра, вторая - его тип. Эти части разделены двоеточием. Если Вы описываете в процедуре более чем один параметр, нужно разделить их точкой с запятой, например:
После того как Вы создали "вручную" заголовок процедуры, являющейся методом класса, Вы должны включить его в декларацию класса, например, путем копирования (еще раз напомним, что для методов, являющихся откликами на дельфийские события, данное включение производится автоматически):
В данном месте нет необходимости оставлять в заголовке метода слово "TForm1", так как оно уже присутствует в описании класса.
Листинг Ошибка! Текст указанного стиля в документе отсутствует.-C показывает полный текст головного модуля программы PARAMS. Мы не включили сюда файл проекта, поскольку, как уже упоминалось, он практически одинаков для всех программ.
Листинг Ошибка! Текст указанного стиля в документе отсутствует.-C: Исходный код головного модуля программы PARAMS показывает, как использовать строки редактирования и как передавать параметры.
При экспериментах с программой PARAMS Вы можете попробовать изменить имена процедур и параметров. Однако, следует помнить, что ряд слов в Delphi являются зарезервированными, и употреблять их в идентификаторах (именах процедур, функций, переменных, типов, констант) не разрешается - компилятор сразу же обнаружит ошибку. К ним относятся такие слова, как "procedure", "string", "begin", "end" и т.п.; полный же список их приведен в on-line справочнике Delphi.
Более сложные методы и управляющие элементы
Теперь, когда Вы освоили базовые понятия в системе программирования Delphi, можно продолжить изучение компонент и способов создания их методов.
В программе CONTROL1, рассмотренной в начале урока, был сгенерирован метод, являющийся откликом на событие OnClick строки редактирования Edit1. Аналогично, можно сгенерировать метод, являющийся реакцией на событие OnDblClick. В программе CONTROL2, имеющейся на диске, расширен список находящихся на форме компонентов и для многих из них определены события OnClick и OnDblClick. Для исследования Вы можете просто скопировать файлы проекта CONTROL1 в новую директорию CONTROL2, изменить имя проекта на CONTROL2.DPR (в этом файле после ключевого слова "program" также должно стоять название "CONTROL2") и добавить компоненты Label, GroupBox, CheckBox, RadioButton, Button на форму (эти компоненты находятся на страничке "Standard" Палитры Компонентов). Ваша форма будет иметь примерно следующий вид - Рис. Ошибка! Текст указанного стиля в документе отсутствует.-E.
Рис. Ошибка! Текст указанного стиля в документе отсутствует.-E: Внешний вид программы CONTROL2
Заметим, что Вы должны "положить" компонент GroupBox на форму до того, как Вы добавите компоненты CheckBox и RadioButton, которые, в нашем примере, должны быть "внутри" группового элемента. Иначе, объекты CheckBox1, CheckBox2, RadioButton1 и RadioButton2 будут "думать",что их родителем является форма Form1 и при перемещении GroupBox1 по форме не будут перемещаться вместе с ней. Таким образом, во избежание проблем, компонент, который должен быть "родителем" других компонент (Panel, GroupBox, Notebook, StringGrid, ScrollBox и т.д.), нужно помещать на форму до помещения на нее его "детей". Если Вы все же забыли об этом и поместили "родителя" (например, GroupBox) на форму после размещения на ней его "потомков" (например, CheckBox и RadioButton) - не отчаивайтесь! Отметьте все необходимые объекты и скопируйте (с удалением) их в буфер обмена с помощью команд меню Edit|Cut. После этого отметьте на форме нужный Вам объект (GroupBox1) и выполните команду меню Edit|Paste. После этого все выделенные Вами ранее объекты будут помещены на форму, и их "родителем" будет GroupBox1. Описанный механизм является стандартным и может быть использован для всех видимых компонент.
Выберите объект Label1. Создайте для него метод, являющийся откликом на событие OnDblClick (см. выше). Введите в метод одну строчку, например:
Запустите программу на выполнение и дважды щелкните мышкой на метке Label1. Вы увидите, что строка редактирования изменится, и в ней появится текст "Двойной щелчок на Label1".
Теперь закройте приложение и возвратитесь в режим проектирования. Добавьте обработчики событий OnClick и OnDblClick для каждого объекта, имеющегося на форме. Текст вашего головного модуля будет выглядеть следующим образом:
Листинг Ошибка! Текст указанного стиля в документе отсутствует.-D: Головной модуль программы CONTROL2.
- Она показывает, как создавать процедуры (методы) и как "наполнять" их содержательной "начинкой"
- Она демонстрирует технику работы с управляющими элементами Windows.
Информация периода выполнения. Программа CONTROL3
Как Вы, наверное, заметили, методы программы CONTROL2, являющиеся откликами на события OnClick и OnDblClick, во многом похожи друг на друга.
Открытость среды Delphi позволяет получать и оперировать информацией особого рода, называемой информацией периода выполнения (RTTI - run-time type information). Эта информация организована в виде нескольких уровней.
Верхний уровень RTTI представлен как средство проверки и приведения типов с использованием ключевых слов is и as.
Ключевое слово is дает программисту возможность определить, имеет ли данный объект требуемый тип или является одним из наследников данного типа, например, таким образом:
Имеется возможность использовать RTTI и для процесса приведения объектного типа, используя ключевое слово as:
- ClassName - возвращает имя класса, экземпляром которого является объект
- ClassInfo - возвращает указатель на таблицу с RTTI, содержащей информацию о типе объекта, типе его родителя, а также о всех его публикуемых свойствах, методах и событиях
- ClassParent - возвращает тип родителя объекта
- ClassType - возвращает тип самого объекта
- InheritsFrom - возвращает логическое значение, определяющее, является ли объект потомком указанного класса
- InstanceSize - возвращает размер объекта в байтах.
Эти методы могут использоваться в Вашем коде напрямую.
Нижний уровень RTTI определяется в дельфийском модуле TypInfo и представляет особый интерес для разработчиков компонент. Через него можно получить доступ к внутренним структурам Delphi, в том числе, к ресурсам форм, инспектору объектов и т.п.
Итак, доступ к информации периода выполнения в Delphi позволяет динамически получать как имя объекта, находящегося на форме, так и название класса, которому он принадлежит (и еще много другой полезной информации; но об этом - в дальнейших уроках). Для этого используется свойство Name, имеющееся у любого класса-наследника TComponent (а таковыми являются все компоненты, входящие в дельфийскую библиотеку VCL), и метод ClassName, доступный для любого потомка класса базового TObject. А, поскольку класс TComponent, в свою очередь, является наследником класса TObject, то он доступен для всех компонент из библиотеки VCL. vВернувшись к нашим примерам, мы можем заменить целую "кучу" методов двумя, реализующими события OnClick и OnDblClick для всех объектов сразу. Для этого можно скопировать все файлы из CONTROL2 в новый директорий CONTROL3 или использовать для работы уже имеющуюся на диске программу. Создадим стандартным образом методы ControlDblClick и ControlClick для какого-либо объекта (например, для Label1). Введем в них следующие строки:
Теперь назначим данные методы всем событиям OnClick и OnDblClick, имеющимся у расположенных на форме объектов. Мы видим, что размер программы существенно сократился, а функциональность ее значительно выросла. В режиме выполнения после, например, щелчка на объекте CheckBox1 приложение будет иметь вид, изображенный на Рис. Ошибка! Текст указанного стиля в документе отсутствует.-F.
Рис. Ошибка! Текст указанного стиля в документе отсутствует.-F: Программа CONTROL3 выводит информацию не только об имени объекта, но и о названии его класса (типа)
Итак, мы видим, что используя информацию периода выполнения, можно сделать программу очень гибкой и универсальной.
Заключение
В этом уроке мы рассмотрели, как управлять методами компонент во время выполнения программы. Кроме того, мы изучили, как что такое информация периода выполнения и научились использовать ее в целях создания гибких и универсальных приложений.
Первый раздел урока: Текстовый редактор, или Наберём и очистим
Приложения для работы с текстом (например, MS Word) играют важную роль в жизни большинства людей. С помощью таких приложений можно набирать и редактировать текстовые документы, сохранять их на диск, распечатывать и т. д.
Задачи урока
- Работа с компонентом Memo (многострочный редактор).
- Работа с компонентом CheckBox (переключатель).
- Понятие компонента-контейнера.
Выполнение упражнения
Сегодня мы создадим простой текстовый редактор с возможностью очистки содержимого рабочей области (рисунок 1). Этот редактор может пригодиться при работе с текстовыми документами.
В среде Delphi такое приложение сделать очень легко, так как имеющийся в нём компонент Memo уже умеет многое из того, что нужно для текстового редактора: работать с многострочным текстом, с буфером обмена, с диском, вставлять и удалять символы, выделять текст, изменять атрибуты шрифта.
Рисунок 1. Окно приложения
1. Дизайн приложения
Рисунок 2
Компонент Panel обладает очень важной особенностью. Он является компонентом-контейнером. Если на него поместить другие компоненты, то их перемещение будет ограничено границами компонента-контейнера. При перемещении компонента-контейнера по форме всё его содержимое будет перемещаться вместе с ним.
3. Чтобы понять принцип работы компонентов-контейнеров, посмотрите на содержимое окна Дерево объектов (Object TreeView) (если его не видно на экране, нажмите комбинацию клавиш Ctrl+Shift+F11 ). В нём хранится список всех компонентов, размещённых на форме (рисунок 3а). Из него видно, что главный контейнер — это форма (Form1). На ней расположены два компонента: Memo1 и Panel1.
4. Увеличьте размер панели до размеров, в двое больших чем многострочный редактор. Измените контейнер у компонента Memo1 с Form1 на Panel1. Для этого в окне Дерево объектов методом Drag and Drop (Перетащить и оставить) перетащите компонент Memo1 из формы (Form1) на панель (Panel1), как показано на рисунке 3б. В результате вы увидите, что панель стала обладателем многострочного редактора Memo (рисунок 3в). Теперь перемещение панели приведёт и к перемещению многострочного редактора.
5. Измените контейнер у компонента Memo1 с Panel1 на Form1.
3. В принципе, текстовый редактор уже готов. Сохраните проект под именем Editor.
4. Запустите приложение и убедитесь, что вы можете легко набирать и редактировать текст в поле Memo.
- при запуске приложения компонент Memo содержит совершенно ненужную надпись «Memo1«;
- при изменении размеров формы размер поля Memo не меняется, что выглядит некрасиво: при увеличении окна появляется много свободного места, а при уменьшении — появляются полосы прокрутки.
а) б)
Рисунок 3
7. Запустите приложение и поменяйте размер формы. Размеры компонентов динамически изменятся в зависимости от её размеров. Закройте приложение.
а) б)
Рисунок 4
10. Установите свойство AutoSize=True для панели Panel. Размер панели автоматически изменится так, чтобы вместить все находящиеся на нём компоненты (рисунок 4б).
11. Запустите приложение. У нас получился почти полноценный редактор текста. Но вот беда… Текст мы вводить можем, но ни одна кнопка не работает. Для исправления этого досадного обстоятельства необходимо написать обработку событий OnClick для каждой кнопки.
2. Выходим из приложения
3. Очистим редактор!
2. Запустите приложение. Теперь мы имеем простейший текстовый редактор с функциями:
- очистки рабочей области;
- работы с многострочным текстом;
- вставки и удаления символов;
- выделения текста;
- работы с буфером обмена через горячие клавиши или контекстное меню.
4. Коротко о главном
- Компонент Memo обладает свойствами многострочного текстового редактора.
- Свойство Align указывает, к какой стороне окна прижать компонент.
- Логическое свойство AutoSize определяет, будет ли у компонента автоматический размер, в зависимости от его содержимого.
- Компонент-контейнер – это компонент, который может содержать другие компоненты. Используется для смыслового объединения компонент.
- Окно Дерево объектов дает возможность быстрой смены контейнера для компонентов;
Второй раздел урока: Текстовый редактор, или А мы ещё файлы открывать умеем и шрифт изменять тоже…
Выполнение упражнения
Для загрузки текстовых файлов в компонент Memo и изменения параметров шрифта будем использовать стандартные диалоговые окна Windows Шрифт (рисунок 1б) и Открыть (рисунок 1в).
а) б) в)
Рисунок 1. Окно приложения
1. Открываем файл
1. Откройте проект, созданный в предыдущем разделе урока № 4 — Текстовый редактор, или Наберём и очистим!
2. Из палитры компонентов, категории Dialog, поместите на форму невизуальные компоненты: FontDialog и OpenDialog . В какое место формы мы их поместим, это неважно, потому что они видны только на этапе разработки приложения.
- Компонент FontDialog — вызывает окно стандартного диалога выбора параметров шрифта Шрифт.
- Компонент OpenDialog — вызывает окно стандартного диалога выбора файлов Открыть.
Двойной щелчок по этим компонентам открывает стандартный диалог (не событие, как это было у привычных для нас компонентов). Это диалоговое окно будет появляться при обращении к нему из работающего приложения (или, как говорят, в режиме RunTime). Это очень удобно, т. к. в режиме конструирования (или, как говорят, в режиме DesignTime) можно посмотреть, как выглядит окно диалога.
- вызывать стандартный диалог открытия файлов;
- загружать указанный пользователем файл в многострочный редактор (компонент Memo).
Запишите в обработчике следующий код:
procedure TForm1.ButtonOpenClick(Sender: TObject); begin // Вызываем диалог открытия OpenDialog1.Execute; end;
Метод Execute служит для вызова стандартного диалога Windows у всех компонентов (для каждого компонента свой диалог), находящихся на вкладке Dialogs.
5. Для того чтобы выбранный файл загружался в многострочный редактор, допишите в обработчик следующий код (выделено жёлтым):
Всегда при возникновении ошибки, в первую очередь, обращайте внимание именно на то, что написано в кавычках — это поможет понять причины ошибки (если, конечно, вы хорошо знаете английский язык).
Рисунок 3
Сделать такую проверку очень легко. Метод Execute возвращает логическое значение True (истина), если была нажата кнопка «Открыть«, и False (ложь), если была отмена. Остаётся только проверить это значение с помощью оператора условного перехода:
Обратите внимание, что в условии написано OpenDialog1.Execute , вместо OpenDialog1.Execute=True . Эти две записи полностью идентичны, но первая более простая и рекомендуется использовать именно её.
8. Запустите приложение и убедитесь, что теперь всё работает корректно.
а) б)
Рисунок 4. Фильтр выбора файлов
10. Заполните три строки фильтрами, как показано на рисунке 4б. При выборе первого поля диалог открытия файлов отобразит только текстовые файлы с расширением txt. Второе поле отображает файлы с расширением pas, и третье отобразит все файлы.
2. Форматируем текст
Рисунок 5. Диалог выбора параметров шрифта
Замечательной особенностью объектно-ориентированного программирования является возможность присвоения одинаковых значений одного компонента другому, если они принадлежат одному классу. Например, свойство Font (размер шрифта, цвет и пр.) класса TFont присутствует в объектах Memo и FontDialog, поэтому достаточно написать: FontDialog1.Font:=MemoOut.Font , чтобы передать все параметры свойства Font от объекта Memo объекту FontDialog.
2. Теперь запустите приложение и порадуйтесь, как легко изменять параметры шрифта с помощью стандартного диалога, специально для этого предназначенного.
3. Переключатель CheckBox с именем CheckBold на панели Panel предназначен для более быстрой установки жирного шрифта. Создайте обработчик события OnClick для переключателя и запишите в нём следующий код:
Изменение стиля шрифта через компоненты CheckBox осуществляется через всё то же свойство Font.Style . Синтаксис записи соответствует работе с множествами.
4. Теперь в последний раз запустите приложение. Всё работает? Отлично!
3. Коротко о главном
Выполнение заданий
Особенности задания
- Для полей ввода Edit необходимо ввести поясняющие надписи с помощью компонента Label.
- Компоненты должны иметь осмысленные имена.
- Кнопка выхода из приложения — обязательна!
- Комментируйте код программы!
- Перед размещением компонентов на форме желательно нарисовать их расположение на листе бумаги.
Задания I уровня сложности
2. Добавить к созданному текстовому редактору функцию выбора курсивного шрифта через компонент CheckBox, аналогично выбору жирного шрифта. Для этого добавьте на панель новый переключатель.
3. Добавить к созданному текстовому редактору функцию выбора цвета фона у компонента Memo через компонент ColorBox.
4. Добавить к созданному текстовому редактору функцию выбора цвета шрифта у компонента Memo через компонент ColorBox.
6. Создайте приложение, которое должно уметь открывать текстовые файлы и отображать их в многострочном редакторе. Сразу после открытия файл должен сохраниться в том же каталоге и с тем же именем, но с расширением bac.
Подсказка! Сохранение текста осуществляется вызовом метода SaveFromFile свойства Lines, компонента Memo.
Для замены расширения необходимо воспользоваться процедурами и функциями по работе со строками (см. учебное пособие по Pascal).
9. Создайте приложение, содержащее один многострочный редактор, один однострочный редактор, три компонента типа CheckBox и одну кнопку. При нажатии на кнопку в многострочном редакторе по строкам должно выводиться: содержимое однострочного редактора, состояние первого переключателя, состояние второго переключателя и состояние третьего переключателя. Для дополнительной информации смотрите свойства и методы компонента Memo.
Задания II уровня сложности
Школа программирования Delphi
Портал DelphiSchool является бесплатным проектом, обеспечивающим пользователям быстрый и легкий доступ к урокам программирования на Delphi. Сайт позволяет научиться программировать на Делфи любому, кто хочеть писать свои программы, игры, Android приложения, программы для MAC OC или IOS. Кроме уроков Delphi и статей Delphi, на сайте доступны также и видеоуроки. Практически к каждому уроку, пользователю доступен исходник, изучив который, он сможет наглядно посмотреть как работает та или иная программа, написанная на Делфи. Кроме того мы постараемся прилагать к каждому материалу (статье, уроку, видеоуроку) файлы Delphi, которые будут помогать изучить предоставленный материал.
Каждый кто решил написать свою программу, создать свое приложение, научиться программировать и т.д., найдет на DelphiSchool статьи Delphi, уроки Delphi, видеоуроки Delphi, исходники Delphi, файлы Delphi, изучит компоненты Delphi, посмотрит Delphi примеры и многое другое абсолютно бесплатно. Все о Delphi программировании теперь собрано на одном сайте.
DelphiSchool
Язык программирования Delphi достаточно прост в изучении, но при этом этот язык программирования очень эффективен и достаточно мощный. Первое, с чем стоит ознакомиться при изучении Делфи — это комментарии, так как в последующем, именно с помощью комментариев будут описываться и разъясняться приведенные примеры кода Делфи.
Комментарии — это любой текст, который абсолютно никак не влияет на код программы. Этот текст никогда не компилируется и не вставляется в исполняемый файл. Комментарии используются только для пояснения кода. Существует несколько способов оформления комментариев:
1. Все, что идет после двойного слеша, воспринимается как комментарий. Здесь следует отметить, что таким способом можно оформить только одну строку. Таким образом, все что написано до двойного слеша воспринимается как код программы, а все что после – как комментарий к коду. Например: // комментарий;
2. Все, что заключено в фигурные кавычки является комментарием. Например: < текст комментария >. Здесь следует отметить, что таким способом можно оформить как комментарий несколько строк.
3. Все что заключено в фигурные скобки со звездочкой также воспринимается как комментарий. Например: (*текст комментария*)
Давайте теперь рассмотрим на примере оформление комментария к коду Delphi
Листинг. Пример оформления комментария в Delphi.
Это не комментарий
// А это уже комментарий к коду программы
Это уже не комментарий
Это не комментарий // а вот это уже комментарий
И это комментарий
И вновь комментарий
Все это комментарий>
(*Текст комментария
И это текст комментария
Это тоже комментарий*)
Теперь, когда мы узнали как оформляются комментарии в коде Delphi, можно приступать к изучению программирования на Delphi. К каждому коду, приведенному как пример, при изучении того или иного материала, я буду добавлять комментарии, для того, чтобы вы понимали что и для чего делается в этом коде.
Итак, давайте посмотрим сам код программы создаваемой в Делфи. Для этого, либо создаем новый проект (как это делать описывалось в предыдущих статьях), либо открываем ранее созданный нами проект “Hello Delphi”.
Если мы создаем новый проект, то можем увидеть, что не написав ни единой строчки кода, в нашем проекте уже присутствует какой то код. Это своего рода заготовка нашей будущей формы, которую мы создали. Если создать еще одну форму, то появится еще один модуль с таким же кодом. Таким образом, каждое отдельное окно описывается в отдельном модуле.
Давайте теперь подробнее посмотрим, что же там написано и что означает этот код.
Листинг. Шаблон кода сгенерированный Delphi
unit Unit1; // это имя модуля
// начало объявления интерфейсов
interface
uses // после этого слова перечисляются подключенные модули
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;
Type // после этого слова идет объявление типов
TForm1 = class(TForm)
// здесь идет описание компонентов и событий
Private // после этого слова можно описывать закрытые данные объекта
< Privatedeclarations >// это подсказка которую сгенерировал сам Delphi
public // После этого слова можно описывать открытые данные объекта
< Publicdeclarations >это подсказка которую сгенерировал сам Delphi
end;
var // здесь объявляются глобальные переменные
Form1: TForm1; //Это описана переменная Form1 типа объекта TForm1
// начало реализации
implementation
//Подключение .dfm файла (это файл с данными о визуальных объектах)
end. // Если после end стоит точка, значит это конец модуля
Как вы видите, почти все строчи кода заканчиваются точкой с запятой (“;”). Этот знак означает конец оператора. Точка с запятой ставится только после операторов и никогда не ставится после ключевых слов, таких как: uses, type, begin, implementation, private, public и т. д. Эти ключевые слова в основном выделяются жирным шрифтом. В самом конце кода мы видим, что после слова end стоит точка. Это означает окончание модуля.
Понятное дело, что пока нам ничего не понятно в этом коде. Но приступив к практике программирования и начав писать собственный код, мы все подробно разберем и со временем разберемся что к чему и для чего.
Не забывайте писать свои отзывы об уроке Язык программирования Delphi. Структура кода Delphi. Часть 1. Ваша информация об уроке Язык программирования Delphi. Структура кода Delphi. Часть 1 может помочь другим людям изучить программирование на Delphi. Также не забывайте проставлять рейтинг урока, ведь от этого зависит его попадание в список лучших уроков Delphi
Каждый программист должен уметь работать с текстовыми файлами, файлами, содержащими записи, и файлами, которые не имеют определенной структуры или обрабатываются так, как если бы они не имели структуры. Вначале мы рассмотрим текстовые файлы, поскольку этот тип файлов используется наиболее часто.
Для получения доступа к текстовым файлам служат переменные типа Text:
Прежде чем можно будет приступить к работе с файлом, с помощью процедуры AssignFile его нужно присвоить переменной типа Text. Эта процедура принимает два параметра: переменную файла и имя файла.
После того как имя файла присвоено переменной файла, необходимо определить действия, которые нужно выполнять с файлом. Файл можно подготовить к чтению, записи или дополнению.
Чтобы подготовить файл к записи, необходимо использовать процедуру Rewrite, которая всегда создаст новый пустой файл. Если файл с таким же именем файла уже существует, процедура Rewrite вначале удаляет существующий файл, а затем заменяет его новым пустым файлом. Затем процедура открывает файл и устанавливает указатель позиции на начало файла.
При работе с текстовыми файлами процедуре Rewrite необходимо передавать только переменную типа Text:
Когда файл открыт и готов к записи, для записи текста в текстовый файл можно использовать стандартную процедуру WriteLn. При выполнении записи в текстовый файл первым параметром, переданным процедуре WriteLn, должна быть переменная файла:
По завершении работы с файлом его всегда следует закрывать, чтобы обеспечить корректное сохранение файла на диске и освободить любую память, занятую в процессе записи. Для закрытия файла служит процедура CloseFile, принимающая единственный параметр — файл, который нужно закрыть:
Пример программы записи строки текста в текстовый файл приведен в листинге 8.1.
Листинг 8.1. Запись текста в текстовый файл
Для подготовки файла к чтению используется процедура Reset. Эта процедура, подобно процедуре Rewrite, принимает только параметр типа файла. Ее можно считать безопасной в том смысле, что она успешно работает, если дисковод и/или каталог, указанный в имени файла, существует. В отличие от Rewrite, выполнение процедуры Reset будет невозможным, если файл, присвоенный переменной файла, не существует.
Для выполнения чтения данных из текстового файла можно использовать процедуру ReadLn. При этом первым передаваемым процедуре параметром должна быть переменная файла, а вторым — строковая переменная, которая будет временно хранить значение, считанное из файла.
Следующий пример демонстрирует считывание значений из текстового файла и их отображение на экране.
Листинг 8.2. Считывание текста из текстового файла
Этот код будет успешно работать до тех пор, пока существует файл data. txt. Если этот файл не существует, программа даст сбой. Во избежание остановки приложения при отсутствии файла необходимо выполнять проверку успешности открытия файла с помощью процедуры Reset.
Для выяснения наличия ошибок ввода-вывода необходимо непосредственно после вызова процедуры ввода-вывода, такой как Rewrite или Reset, вызвать функцию IOResult. Функция IOResult возвращает результат последней выполненной операции ввода-вывода. Если IOResult возвращает 0, это означает, что операция была выполнена успешно.
Для выполнения проверки ввода-вывода с помощью функции IOResult необходимо вначале отключить автоматическую проверку ввода-вывода. Для включения и отключения проверки ошибок ввода-вывода служит директива компилятора SI. Обычно автоматическую проверку ввода-вывода отключают перед вызовом процедуры ввода-вывода и снова включают сразу после выполнения этого вызова:
Следующий пример иллюстрирует выполнение проверки ввода-вывода и считывание текста из файла только в случае успешного его открытия.
Листинг 8.3. Проверка ошибок ввода-вывода
Помните, что после обращения к процедуре ввода-вывода функцию IOResult можно вызывать только один раз. Это обусловлено тем, что она сбрасывает результат выполнения последней операции ввода-вывода в 0. Поэтому, если вызвать функцию IOResult дважды подряд, первое обращение к ней правильно сообщит об ошибке, но второе обращение сообщит (ошибочно), что операция была выполнена успешно.
Когда нужно выполнить считывание всего текстового файла, его необходимо считывать последовательно до достижения конца файла. Для определения конца файла служит функция Eof. Эта функция принимает единственный параметр файла и возвращает булевское значение, указывающее, был ли достигнут конец файла:
Как правило, наиболее рациональный способ считывания текстового файла предусматривает использование цикла while, продолжающего итерации вплоть до достижения конца файла. Следующий пример иллюстрирует копирование содержимого одного текстового файла в другой с использованиемцикла while not Eof (результаты можно видеть на рис. 8.1).
Листинг 8.4. Копирование текстового файла
Рис. 8.1. Копирование текстового файла
Простейший способ считывания всего файла в память — его считывание в динамический массив строк. Для этого необходимо знать количество строк текста в файле. Поскольку никаких стандартных функций для выполнения этой задачи не существует, потребуется создать такую функцию. Для вычисления количества строк в текстовом файле необходимо в цикле while not Eof подсчитать количество строк в файле, а затем вызвать процедуру Reset, чтобы вернуться к начальной позиции файла.
В следующем примере цикл while not Eof в функции GetLineCount используется для получения количества строк текстового файла. Полученный результат затем используется в вызове функции SetLength для изменения размера динамического массива.
Листинг 8.5. Загрузка текстового файла в динамический массив
Как только приложение загрузило весь текстовый файл в динамический массив, файл можно закрыть и продолжить работу со строками в памяти. Конечно, со строками в массиве можно выполнять любые действия, но этот код всего лишь с помощью функции Uppercase преобразует (временно) символы строк в прописные и отображает их на экране.
Типизированные файлы представляют собой двоичные файлы, которые содержат элементы одинакового размера. Обычно типизированные файлы — это файлы, содержащие записи. Чтобы создать типизированный файл, вначале, используя следующий синтаксис, необходимо создать новый файловый тип данных:
В следующем коде продемонстрировано создание нового файлового типа, который можно использовать для считывания и записи записей в типизированном файле:
Обратите внимание, что строковые поля в объявлении записи имеют явно определенную длину. Длина строки должна быть определена явно, поскольку размер всей записи должен оставаться постоянным. Если требуется сохранить запись в файле на диске, обычные строки использовать нельзя, поскольку их длина может изменяться в любое время и компилятор не может определить их длину во время компиляции.
Существует несколько различий между текстовыми и типизированными файлами:
- При сбросе типизированного файла в нем можно выполнять считывание и запись (при сбросе текстового файла в нем можно выполнять только считывание).
- При выполнении считывания или записи из типизированного файла необходимо использовать процедуры Read и Write, а не ReadLn и WriteLn.
В листинге 8.6 демонстрируется работу с типизированными файлами.
Листинг 8.6. Работа с типизированными файлами
Еще одно существенное различие между текстовыми и типизированными файлами состоит в том, что в то время как текстовые файлы допускают только последовательный доступ, типизированные файлы допускают произвольный доступ к записям файла. Произвольный доступ возможен вследствие того, что все записи в файле имеют одинаковый размер, поэтому для считывания конкретной записи процедуре достаточно пропустить определенное, легко определяемое количество байт.
Для определения количества записей в файле можно использовать функцию FileSize. Для перехода к определенной записи в файле можно использовать процедуру Seek. Эта процедура принимает два параметра: переменную файла и целочисленное значение, указывающее номер записи (начиная с О), к которой необходимо выполнить переход.
Нетипизированные файлы — это файлы без определенной структуры. В общем случае, нетипизированные файлы — это типизированные файлы, в которых вместо записей используются байты. Объявление переменной нетипизированного файла выглядит следующим образом:
При работе с нетипизированными файлами обращения к процедурам Reset и Rewrite выглядят несколько иначе. Обычно обе эти процедуры в качестве заданного по умолчанию размера записи используют 128 байт. При работе с нетипизированными файлами этот размер должен быть установлен равным 1 байту. Это можно выполнить, передавая 1 в качестве второго параметра в обоих вызовах:
Для считывания и записи данных в нетипизированные файлы применяются процедуры BlockRead и BlockWrite. Объявления этих процедур показаны ниже:
Первый параметр — переменная нетипизированного файла, используемая для доступа к файлу на диске. Второй параметр — буфер, который процедуры используют для передачи данных в файл и из него.
Обычно этот буфер представляет собой статический массив байтов, но он может быть также и записью. Третий параметр указывает количество передаваемых байтов. Обычно это число равно размеру массива, который легко определить с помощью функции SizeOf. Необязательный параметр-переменная AmtTransferred можно использовать для отслеживания точного числа байтов, переданных в файл и из него.
Приложение, код которого представлен в листинге 8.7, использует процедуры BlockRead и BlockWrite для предоставления пользователю возможности копирования файлов. Приложение также дает пользователю возможность указывать имена исходного и целевого файлов в командной строке, как показано на рис. 8.2.
Рис. 8 .2. Передача параметров приложению
Листинг 8.7. Копирование файлов с помощью процедур BlockRead и BlockWrite
Для выяснения количества параметров, которые пользователь передал приложению, применяется функция ParamCount. Эта функция не принимает никаких параметров и возвращает значение 0. если пользователь вызвал приложение без дополнительных параметров.
Для считывания параметров, переданных приложению, служит функция ParamStr, которая принимает единственный параметр типа Integer — индекс параметра. Если передать этой функции значение О, она возвратит путь и имя файла приложения. Индексы пользовательских параметров, если они переданы, начинаются с 1.
Вначале приложение проверяет, передал ли пользователь два параметра в командной строке. Если да, то ParamStr (1) содержит путь к исходному файлу, а ParamStr (2) — путь к файлу назначения.
Копирование выполняется в процедуре BlockCopyFile.
Ее первая строка:
использует функцию LowerCase для временного преобразования имен обоих файлов в строчные буквы и проверяет, указывают ли оба имени файлов на один и тот же файл. Если файл назначения и файл-источник совпадают, никакое копирование не требуется и оператор if-then вызывает процедуру Exit для выхода из процедуры.
Основная часть процедуры BlockCopyFile — цикл while, который вызывает процедуры BlockRead и BlockWrite:
Процедура BlockRead считывает из файла 1 Кбайт данных, записывает эти данные в массив Buffer и обновляет переменную BytesRead, которая всегда содержит точное количество переданных байтов. Выполнение цикла будет повторяться до тех пор, пока процедура BlockRead продолжает считывать данные из файла. Когда эта процедура достигнет конца файла, значение переменной BytesRead будет сброшено в 0, условие цикла while станет ложным и копирование файла завершится.
Читайте также: