Справочное руководство по Delphi - Создание собственных компонентов. Создание, удаление и проверка на наличие папки в Delphi


Разработка собственных компонентов

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

Перед созданием своего компонента важно правильно выбрать для него предка. Кто же может быть предком для вашего компонента? Как правило, используются в виде предков TComponent, TControl, TWinControl, TGraphicControl, TCustomXXXXXX, а также все компоненты палитры компонентов. Возьмем для примера компонент TOpenDialog, который находится на странице Dialogs палитры компонентов. Он хорошо справляется со своей задачей, но у него есть одно маленькое неудобство. Каждый раз, когда его используешь необходимо каждый раз изменять значение свойства Options. И причем это, как правило, одни и те же действия.


нажатие на этой строке Ctrl + Shift + C создает шаблон для этого метода, внутри которого мы вставляем такие строки:


Установка созданного компонента Component/Install Component...

  • Install Into New Package
  • Package file name: C:\Program Files\Borland\Delphi4\Lib\OurTest.dpk
  • Package description: Our tested package

Вам не нравится, что у нашего компонента иконка такая же как у стандартного? Тогда создадим для него свою собственную. Для этого нам необходимо вызвать Tools/Image Editor. Создаем новый *.dcr файл. Вставляем в него рисунок Resource/New/Bitmap. Устанавливаем размер картинки 24x24 точек. А дальше - ваше творчество... Обратите внимание: цвет точек, совпадающий с цветом точки в левом нижнем углу рисунка, будет считаться ПРОЗРАЧНЫМ!

После того как вы создали свой рисунок, переименуйте его из Bitmap1 в TOurOpenDialog и сохраните файл с именем OurOpenDialog.dcr. Удалите компонент из пакета и установите его снова (только в этом случае добавится и ссылка на *.dcr файл).

Compile, Install и удачи!

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

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

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

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

Далее. Когда компонент создан, то есть место в памяти под него выделено, можно задавать значения параметрам этого объекта. Прежде всего, это ещё один компонент, так называемый "родитель". Компонент-родитель будет отвечать за отрисовку нашего динамически создаваемого компонента. Это значит, что новый компонент появится в границах компонента-родителя.

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

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

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

Вот общая схема "конструирования" динамически создаваемого компонента:

var Component: TComponent;//Описать переменную для компонента

begin
Component:=TComponent.Create(Owner);//Задать владельца
Component.Parent:=Parent;//Задать родителя
end ;

Естественно, для визуальных компонентов значения таких свойств по умолчанию как положение на Форме, ширина, высота "свежесозданного" динамически компонента мало кого устроят. Нужные размеры и положение компонента также придётся задать программисту.

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

Ребята, не забывайте присваивать (ассоциировать в Инспекторе Объектов) своим кнопкам предлагаемые здесь процедуры. А то потом в комментариях и появляются возгласы: "ничего не работает!"

Есть ещё свойство Name ! По умолчанию Delphi присвоит ему типовое имя с присвоением очередного порядкового номера: Memo1. Программист при создании компонента также может присвоить свойству Name нужное значение, например:

Memo.Name:="DynamicallyCreatedMemo";

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

Теперь хочу обратить ваше внимание на один нюанс. Создайте новый проект. Создайте-создайте, а то не получите того эффекта, на который я рассчитываю. В новом проекте создавать тот же компонент Memo мы будем в обработчике OnCreate Формы, чтобы Форма появлялась уже с нашим компонентом. Для пустой Формы создайте обработчик события OnCreate и наполните его вышеприведённым кодом. И что же - при попытке исполнить приложение мы получим от компилятора ошибку!

А дело вот в чём. Посмотрите в свежесозданном проекте, ещё до добавления компонентов, на список перечисленных в операторе uses стандартных модулей:

unit Unit1;

interface

uses

Dialogs;

Теперь возьмите в Палитре компонентов компонент Memo или ту же кнопку Button, положите на Форму и опять посмотрите на список модулей:

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls ;

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

Поэтому естественно, что мы получили ошибку в предыдущем варианте - не хватало нужных модулей. Теперь смело жмите Run !

Также становится понятно, почему приложение, создающее Memo через нажате кнопки, сразу заработало. Для работы компонентов Button и Memo необходим один и тот же модуль StdCtrls, описывающий компоненты, расположенные на вкладке Standart. Поэтому, когда мы положили на Форму компонент Button, Delphi добавил этот модуль, что обеспечило работу также и Memo.

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

Можно, конечно, обойтись и без добавления на Форму и последующего удаления компонентов, которые мы в программе будем создавать динамически. Посмотрите - при наведении мышки на любой компонент в Палитре Компонентов всплывает подсказка с названием модуля, в котором он описан. Добавьте это название в список uses, и всё! Но если ошибётесь в какой буковке - пеняйте тогда на себя.

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

Динамически создать кнопку мы можем в обработчике OnCreate Формы, точно так же, как и компонент Memo. Однако она не будет работать - создавать компонент Memo. Естественно, ведь обработчика OnClick для неё мы не создали! Давайте сделаем это.

Естественно, проще всего создать обработчик для динамически создаваемого компонента, воспользовавшись готовым компонентом из палитры. Создаём для него нужный обработчик, а затем этот компонент просто удаляем. А теперь достаточно присвоить имя созданного обработчика соответствующему свойству динамического компонента. Название этого свойства будет совпадать с названием соответствующего события в Инспекторе Объектов. Например, для события OnClick пишем так:

Button.OnClick:=Button1Click;

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

Теперь мы умеем создавать компоненты динамически, и можем наделать компонентов столько, сколько нам требуется. Но такие уж они, динамически создаваемые компоненты, что надобность в них как появляется, так и исчезает - динамически! Иногда нужно и уничтожить компонент. Для уничтожения компонента есть простой метод: Free.

Component.Free;

Вот и всё. Все ресурсы, выделенные для функционирования компонента, будут освобождены. Останется только созданная переменная, указывающая на уже несуществующий в памяти объект. Её тоже неплохо бы уничтожить. Это делается присвоением переменной значения nil . Есть процедура, выполняющая оба эти действия, уничтожение и объекта и переменной: FreeAndNil:

FreeAndNil(Component);

И это относится не только к динамически созданному - к любому компоненту и объекту в памяти.

В среде Delphi программист работает с проектом – набором файлов, из которых Delphi создает приложение. Один проект соответствует одному приложению. Ряд файлов проекта Delphi формирует и модифицирует автоматически. Программист может добавлять в проект и собственные файлы (Pascal -модули, графические файлы, DLL –библиотеки, библиотеки компонент, ресурсы и т.д.).

В состав проекта обязательно входят следующие элементы :

· основной файл проекта, имеющий расширение.DPR (D elphi PR oject ). В проекте может существовать только один файл с таким расширением. Это небольшой текстовый файл на языке Object Pascal , который содержит ссылки на все формы проекта и инициализирует приложение;

· файлы всех форм проекта. Для каждой формы формируется пара одноименных файлов – файл Pascal -модуля с обычным расширением.PAS и файл ресурсов формы с расширением.DFM (D elphi F orM ). Любая форма проекта всегда должна иметь свою пару файлов модуль-ресурс. Обратное не обязательно, т.е. проект может включать в себя модули и файлы ресурсов не относящиеся ни к одной из форм приложения;

· файл ресурсов приложения (*.RES). В нем содержатся ресурсы приложения, не вошедшие в формы;

файл опций проекта (*.DOF – D elphi O ptions F ile ). В этом файле сохраняются значения директив и опций компилятора, настроек компоновщика, названия рабочих каталогов, параметры командной строки запуска приложения.

Пример программы

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

Запускаем Delphi . Если загрузка прошла успешно, то на экране монитора мы увидим то, что представлено на рис.1. В строке заголовка главного окна Delphi присутствует надпись Delphi 3 – Project1 . Это название нашего проекта и программы. В строке заголовка окна формы приложения написано Form1 . Если нажать клавишу F12 или щелкнуть мышью на кнопку Toggle
Form/Unit
(панель быстрого доступа) или выбрать пункт меню View/Toggle Form/Unit , то окно редактора кода переместится на передний план и мы увидим содержимое страницы Unit1 редактора, в которой представлен Pascal -код модуля Unit1 . Добавим в окно редактора кода еще одну страницу, в которой расположится код основного программы проекта. Для этого выберем пункт меню View/Project Source . Ниже представлено содержимое двух страниц редактора кода: Pascal-код главной программы и Pascal-код модуля главной формы проекта, соответственно.

Сохраним файлы проекта в созданном директории PO_EVM . Для этого нажмем кнопку Save all на панели быстрого доступа или выберем пункт меню File/Save Project As… . В появившемся стандартном Windows- окне сохранения файлов выберем папку PO_EVM и последовательно сохраним Pascal -код модуля формы и Pascal -код программы в файлах с именами IDE_Un1.pas и IDE_Pr.dpr соответственно.

program IDE_Pr;

IDE_Un1 in ‘IDE_Un1.pas’ {Form1};

Application.Initialize;

Application.CreateForm(TForm1, Form1);

Application.Run;

unit IDE_Un1;

Windows, Messages, SysUtils,

lasses, Graphics, Controls,

TForm1 = class(TForm)

{ Private declarations }

{ Public declarations }

Если сейчас посмотреть содержимое папки PO_EVM , то в ней будут находиться следующие файлы проекта: IDE_Pr.dof – файл опций проекта; IDE_Pr.dpr – основной файл проекта; IDE_Pr.res – файл ресурсов проекта; IDE_Un1.pas – файл Pascal-кода модуля формы; IDE_Un1.dfm – файл ресурсов формы.

Желательно изменить некоторые стандартные настройки среды, в частности для того, чтобы на экране отображался процесс компиляции и компоновки программы, а также, чтобы перед каждым запуском программы на исполнение автоматически сохранялись все модифицированные файлы проекта. Сделать это можно в диалоговом окне Environment Options… , которое можно вызвать из меню Tools/ Environment Options… . На страничке Preferences в разделе Desktop contens установить переключатель в положение Desktop only , в разделе Autosave options установить выключатели в пунктах Editor files и Desktop , а в разделе Compiling and Running установить выключатель Show compiler progress .

Простейшая программа в Delphi уже готова к исполнению. Нажав кнопку Run на панели быстрого доступа или клавишу F9 , можно наблюдать процессы компиляции и компоновки программы, после которых начнет исполняться наша программа. Визуально программа представлена на экране пустым окном со стандартной Windows- строкой заголовка, содержащей пиктограмму приложения, наименование формы и три кнопки управления окном. Выход из программы и возврат в среду Delphi осуществляется стандартным для Windows способом – комбинацией клавиш Alt-F4 или нажатием на кнопку закрытия приложения. Если сейчас просмотреть содержимое папки файлов проекта PO_EVM , то можно заметить, что в ней появились еще два файла: IDE_Un1.dcu и IDE_Pr.exe – откомпилированный файл модуля формы и загрузочный (исполняемый) файл приложения. Файл IDE_Pr.exe можно запускать на исполнение автономно, т.е. вне среды Delphi . После выхода из среды Delphi , в папке образуется еще один файл IDE_Pr.dsk – файл с индивидуальными пользовательскими настройками среды.

Приведем примерную последовательность действий программиста, который создает программу “Калькулятор +/- “. Это, с позволения сказать, приложение предназначено для выполнения операций сложения и вычитания вещественных чисел. При запуске окно (форма) программы должно выглядеть как на рис. 7.

На форме расположены три строки ввода/вывода (компоненты типа TEdit ) для ввода двух операндов и вывода результата; пять кнопок (четыре компоненты типа TButton и одна – TBitBtn ) – сброс, указание типа и результата операции (C , + , , = ), выхода из программы (Close); три надписи для обозначения операндов и результата (компоненты типа TLabel ); разделительный интерфейсный элемент для выделения поля вывода результат счета (компонент TBevel ).

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

1. Свойство формы Caption в инспекторе объектов изменяем со значения Form1 на строковое значение Калькулятор +/- . Изменение значения названия формы сразу заметно в строке заголовка формы;

2. На странице Standard палитры компонентов щелкаем левой кнопкой мыши на изображении компонента Label , затем перемещаем указатель мыши в район левого верхнего угла формы и щелкаем левой кнопкой там. В этом месте на форме появится изображение компонента Label с надписью Label1 . Изображение компонента выделяется по периметру шестью черными квадратиками – маркерами изменения размеров (размерные маркеры). Выделение маркерами означает, что данный компонент сейчас является активным. С помощью мыши стандартными Windows- приемами можно изменять размеры компонента, перемещать его по форме. Для активизации другого компонента формы необходимо просто щелкнуть на нем левой кнопкой мыши. Содержимое закладок инспектора объектов всегда соответствует активному компоненту, при активизации другого компонента, состав полей инспектора объектов автоматически меняется. Изменим свойство Caption компонента Label со значения Label1 на значение 1-ый операнд . Свойству Name этого компонента придадим значение lb_1 .

3. Действуя аналогично, расположим второй компонент-метку немного ниже первой, задав, соответственно, свойствам Caption и Name значения 2-ой операнд и lb_2 .

4. На той же странице Standard палитры компонентов выберем компонент Edit (строка редактирования) и поместим его на форме правее первой метки. Свойству Name присвоим значение ed_1 , а свойство Text сделаем пустым.

5. Действуя аналогично, расположим вторую строку редактирования правее второй метки, задав, соответственно, свойствам Text и Name значения пустой строки и ed_2 .

6. На странице Additional палитры компонентов выберем компонент Bevel и поместим его так, чтобы он изображал “итоговую” черту под второй меткой и второй строкой ввода. Свойство Name, равное Bevel1 , изменять не будем.

7. Под компонентом Bevel разместим еще одну пару “метка – строка ввода” для вывода результата вычислений. Свойствам Name присвоим значения lb_3 и ed_3 , свойству lb_3.Caption – значение Результат , а свойству Text компонента ed_3 – значение пустой строки.

8. Поместим еще одну метку для изображения текущей арифметической операции: (?, +, –) - операция не определена, операция сложения, операция вычитания. Расположим эту метку между двумя первыми метками, ближе к левым границам компонентов для ввода операндов (см. рис.7). Свойству Name присвоим значение lb_oper , а свойству Caption – значение ? . Установим также подсвойство Size в свойстве Font для этой метки, равным 14 ;

9. Подравняем компоненты. Стандартным Windows- приемом выделим компоненты – метки. Для этого, держа нажатой кнопку Shift , последовательно щелкая левой кнопкой мыши по компонентам-меткам, активизируем одновременно все три метки. Если теперь щелкнуть правой кнопкой мыши, то по законам Windows 95 должно появиться контекстное меню – оно и появляется. Выберем в нем пункт A lign… (выравнивание). Теперь на экране мы видим окно Alignment . Выберем на панели Horizontal пункт Left sides и нажмем кнопку Ok . В результате этого все три компонента – метки выровняются по левой границе самой левой компоненты. Аналогичными действиями подравняем и все три строки редактирования. Строки редактирования можно выровнять и по размерам, выделив их одновременно все три и выбрав в контекстном меню пункт Size… . “Тонкую” работу по изменению размеров и перемещению компонент выполняют обычно не мышью, а клавишами управления курсором при нажатых, соответственно, сдвиговых клавишах Shift и Ctrl . Эти действия можно производить не только с одним компонентом, но и с выделенной группой компонентов.

10. Теперь расставим на форме управляющие кнопки. Их у нас пять (см. рис.7). Первые четыре кнопки – кнопка сброса, кнопки операций (сложение (+) и вычитание (–)) и кнопка результата. Пятая кнопка – кнопка завершения работы программы. На странице Standard палитры компонентов выберем компонент Button (кнопка) и поместим его правее первой строки редактирования. Свойствам Caption и Name кнопки присвоим соответственно значения C и btn_Clear . Аналогичным образом располагаем и три другие кнопки на форме, назвав (свойство Name ) их btn_sum, btn_sub и btn_rez , с наименованиями (свойство Caption ) + , и = (см. рис.7). Выделив кнопки в группу, дважды щелкнем на составном свойстве Font в инспекторе объектов. В поле Size свойства Font зададим размер шрифта 14 пунктов. После установки этого значения размер символов на кнопках увеличится.

11. Пятая кнопка – кнопка завершения программы – выбрана со страницы Additional . Это первый по порядку компонент на этой странице – кнопка типа BitBtn (командная кнопка с надписью и пиктограммой). Расположив кнопку на показано на рис.7, выберем из списка значений свойства Kind значение bkClose . Этим выбором полностью определяются визуальные атрибуты и функциональное назначение кнопки.

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

На этом заканчивается первый этап создания приложения – построения интерфейса. Необходимо отметить, что на любом этапе построения интерфейса можно в любой момент запустить программу на исполнение. В процессе выполнения вышеописанных шагов мы не написали ни одной строчки, ни одного Pascal-оператора. Все записи в тексте модуля формы приложения Delphi делает сама. К этому моменту в интерфейсной части модуля формы произошли изменения – добавились описания компонентов, помещенных нами в форму и стандартные модули Delphi – Buttons, StdCtrls, ExtCtrls.

Windows, Messages, SysUtils, Classes,

Graphics, Controls, Forms, Dialogs,

Buttons, StdCtrls, ExtCtrls;

TForm1 = class(TForm)

lb_Oper: TLabel;

btn_Clear: TButton;

btn_sum: TButton;

btn_sub: TButton;

btn_rez: TButton;

bb_Close: TBitBtn;

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

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

1. Нажатие на кнопку “Очистить” (С ) - очистить все три строки редактирования и в качестве знака операции отобразить знак вопроса (?) ;

2. Нажатие на кнопку “Сложить” (+ ) - изменить изображение знака операции на знак плюс (+) ;

3. Нажатие на кнопку “Вычесть” () - изменить изображение знака операции на знак минус (–) ;

4. Нажатие на кнопку “Вычислить” (= ) - провести проверку на правильность данных в первых двух строках редактирования. Если данные правильные (числа), то провести соответствующую арифметическую операцию и вывести результат в строку вывода. Если обнаружена ошибка в исходных данных, то следует вывести сообщение об этом с указанием места ошибки.

Теперь переведём (транслируем) на Pascal-код каждый из вышеперечисленных пунктов. Каждый компонент имеет список событий (список приводится на второй странице (Events ) инспектора объектов), на которые он может реагировать (которые он может обрабатывать). Наша задача – написать код, который будет выполняться при возникновении того или иного события. Для кнопок в Delphi определены несколько обработчиков событий, нас будет интересовать обработчик события “Однократное нажатие на кнопку” (щелчок левой кнопкой мыши в момент нахождения указателя мыши над компонентом Button ). Этот обработчик называется OnClick . Каждый обработчик события оформляется в отдельную процедуру. Название этой процедуре формирует сама среда Delphi .

Напишем обработчик события однократного нажатия на кнопку “Очистить”. Для этого выделим на форме кнопку “Очистить” (С ). Активизируем страницу Events в окне инспектора объектов. Дважды щелкнем на пустом поле правого столбца рядом с надписью OnClick . После этого Delphi автоматически отображает окно редактора кода IDE_Un1 и помещает текстовый курсор для вставки текста внутри процедуры TForm1.btn_ClearClick:

procedure TForm1.btn_ClearClick(Sender: TObject);

как бы приглашая нас начать печатать с этого места Pascal -код этой процедуры. Обратите внимание на название процедуры, которое сформировала среда Delphi . Оно состоит из названия формы, на которой расположена компонента (кнопка), имени этой компоненты (btn_Clear) и названия обработчика события – Click . Следуя содержанию первого пункта нашего словесного алгоритма, вставим в тело процедуры следующие строки Pascal -кода:

lb_Oper.Caption:=’?’; {тип операции неопределен (метка – ?)}

ed_1.Text:=”; {очистить строку для ввода первого операнда}

ed_2.Text:=”; {очистить строку для ввода второго операнда}

ed_3.Text:=”; {очистить строку для вывода результата}

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

– для кнопки “Сложить” строка кода - lb_Oper.Caption:=’+’;

– для кнопки “Вычесть” строка кода - lb_Oper.Caption:=’-‘;

Обработчик события OnClick для кнопки “Вычислить” (= ) будет содержать следующий Pascal -код:

procedure TForm1.btn_rezClick(Sender: TObject);

Val(ed_1.Text,r1,i);

if i<>0 then begin

ShowMessage(‘Ошибка в первом операнде’);

Val(ed_2.Text,r2,i);

if i<>0 then begin

ShowMessage(‘Ошибка во втором операнде’);

case lb_oper.Caption of

‘+’ : ed_3.Text:=FloatToStr(r1+r2);

‘-‘ : ed_3.Text:=FloatToStr(r1-r2);

else ShowMessage(‘Не определен тип операции’);

В обработчике события TForm1.btn_rezClick введены две локальных вещественных переменных r1 и r2 для запоминания числовых значений двух операндов и целочисленная переменная i для использования в Pascal -процедуре Val преобразования строковой переменной в числовое представление. Этот обработчик реализует четвертый пункт словесного алгоритма работы программы. Сначала проверяется на правильность строка, введенных пользователем, символов первого операнда. Если это не число, то процедурой ShowMessage выводится соответствующее ситуации сообщение и по процедуре Exit заканчивается выполнение кода процедуры. В случае корректности данных переменная r1 примет числовое значение первого операнда. Аналогичным образом проверяется второй операнд и, если здесь все нормально, то переменная r2 примет числовое значение второго операнда.

Оператор Case реализует арифметическую операцию над переменными r1 и r2 в зависимости от того, какой символ (+ , , ? ) определяет значение свойства Caption метки lb_oper . Если знак арифметической операции не определен (у нас это символ ? ), то выдается соответствующее сообщение и операция не производится.

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

procedure btn_sumClick(Sender: TObject);

procedure btn_ClearClick(Sender: TObject);

procedure btn_subClick(Sender: TObject);

procedure btn_rezClick(Sender: TObject);

На этом можно закончить программную реализацию задачи создания простейшего калькулятора, осуществляющего операции сложения и вычитания вещественных чисел. Отметим также, что наше приложение на 99% защищено от ошибок, связанных с операциями над некорректными исходными данными (а почему не 100% ?).

Перед созданием своего компонента нужно выбрать для него предка. Кто же может быть предком для вашего компонента?

Как правило, используются в виде предков TComponent, TControl, TWinControl, TGraphicControl, TCustomXXXXXX, а также все компоненты палитры компонентов.
Возьмем для примера компонент TOpenDialog, который находится на странице Dialogs палитры компонентов. Он хорошо справляется со своей задачей, но у него есть одно маленькое неудобство. Каждый раз, когда его используешь необходимо каждый раз изменять значение свойства Options. И причем это, как правило, одни и те же действия.
OpenDialog1.Options:= OpenDialog1.Options + ;

чтобы файл, который мы пытаемся открыть с помощью этого диалогового окна, действительно существовал на диске.
Задание для себя мы уже выбрали, осталось за малым - создать компонент. Заготовку для компонента создаем, выбирая из меню команду Component/New Component... и в диалоговом окне выбираем
Ancestor type: TOpenDialog
Class Name: TOurOpenDialog
Palette Page: Our Test
Нажали Ok и у нас появился шаблон нашего будущего компонента.

Переопределяем конструктор у этого компонента, т.е. в секции public вставляем строку:

constructor Create(AOwner: TComponent); override;

нажатие на этой строке Ctrl + Shift + C создает шаблон для этого метода, внутри которого мы вставляем такие строки:

inherited Create(AOwner); {Вызываем унаследованный конструктор}
Options:= Options + ; {Выполняем необходимые нам действия}

Обратите внимание: Комбинации клавиш Ctrl + Shift + стрелки вверх/вниз позволяют перемещаться между объявлением метода и его реализацией.

Установка созданного компонента Component/Install Component...
Install Into New Package
Package file name: C:Program FilesBorlandDelphi4LibOurTest.dpk
Package description: Our tested package

Вам не нравится, что у нашего компонента иконка такая же как у стандартного? Тогда создадим для него свою собственную.
Для этого нам необходимо вызвать Tools/Image Editor. Создаем новый *.dcr файл.
Вставляем в него рисунок Resource/New/Bitmap. Устанавливаем размер картинки 24x24 точек. А дальше - ваше творчество...
Обратите внимание: цвет точек, совпадающий с цветом точки в левом нижнем углу рисунка, будет считаться ПРОЗРАЧНЫМ!
После того как вы создали свой рисунок, переименуйте его из Bitmap1 в TOurOpenDialog и сохраните файл с именем OurOpenDialog.dcr.
Удалите компонент из пакета и установите его снова (только в этом случае добавится и ссылка на *.dcr файл).
Compile, Install и удачи!

unit OurOpenDialog; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TOurOpenDialog = class (TOpenDialog) private { Private declarations } protected public { Public declarations } constructor Create(AOwner: TComponent); override ; published end ; procedure register ; implementation procedure register ; begin RegisterComponents("Samples", ); end ; { TOurOpenDialog } constructor TOurOpenDialog.Create(AOwner: TComponent); begin inherited Create(AOwner); {Вызываем унаследованный конструктор} Options:= Options + ; {Выполняем необходимые нам действия} end ; end .

Объявление компонента состоит из секций, таких как private, protected, public и published . Что они означают?
Это директивы видимости.
Все что объявлено в секции private , доступно только внутри модуля в котором объявлен класс (приватные объявления). Здесь как правило объявляются переменные, в которых хранятся значения свойств, а также методы (процедуры или функции) доступа к ним.
Все что объявлено в секции protected , доступно как и в секции private, а также наследникам данного класса (интерфейс разработчика).
Здесь можно объявить методы доступа к значениям свойств (если вы хотите позволить изменять эти методы потомкам вашего компенента),
а также свойства, методы и события (методы реакции на события) в компонентах типа TCustomXXX.
Все что объявлено в секции public , доступно любому пользователю компонента (интерфейс этапа выполнения).
Здесь объявляются, как правило методы. В секции published можно объявлять только свойства и события (они объявляются в виде свойств).
Они доступны во время проектирования приложения (интерфейс этапа проектирования).

Свойства

Свойства типа масив - обычные массива Object Pascal, но в отличии от последних могут индексироваться не только числовыми значениями но и строковыми. К сожалению этот тип свойства требует пользовательского редактора свойств (в инспекторе объектов редактор свойства имеет кнопку с тремя точками [...]), по-этому в указанном ниже примере свойство ArrayProp объявлено в секции public .

type TOurComponent = class (TComponent) private { Private declarations } FArrayProp: array of integer; function GetArrayProp(aIndex: integer): integer; procedure SetArrayProp(aIndex: integer; const Value: integer); protected { Protected declarations } public { Public declarations } property ArrayProp: integer read GetArrayProp write SetArrayProp; published { Published declarations } end ;

Спецификаторы свойств

Спецификатор default указывает сохранять значение свойства в файле формы или нет. Если значение свойства совпадает со значением default - значение в файле формы не сохраняется, если значения не равны - сохраняется. Это можно проверить, положив компонент на форму и выбрать правой кнопкой мыши пункт меню "View as Text". Default не устанавливает первоначальное значение свойства к указанному. Это необходимо сделать в конструкторе компонента.

unit OurComponent; interface uses Windows, SysUtils, Classes, Graphics, Forms, Controls; type TOurComponent = class (TComponent) private { Private declarations } FMyInteger: Integer; protected { Protected declarations } public { Public declarations } constructor Create(AOwner: TComponent); override ; published { Published declarations } property MyInteger: Integer read FMyInteger write FMyInteger default 10; end ; implementation constructor TOurComponent.Create(AOwner: TComponent); begin inherited Create(AOwner); FInteger:= 10; end ; end .

Спецификатор nodefault отменяет заданное по умолчанию значение свойства. Этот спецификатор, как правило, используется для отмены заданого по умолчанию значения унаследованного свойства.
Например: property AutoSize nodefault ;

Спецификатор stored указывает когда сохранять в файле формы значение свойства. После stored может стоять true (всегда сохранять), false (никогда не сохранять) или название функции, которая возвращает логический результат.

property OneProp: integer read FOneProp write SetOneProp stored False; property TwoProp: integer read FTwoProp write SetTwoProp stored True; property ThreeProp: integer read FThreeProp write SetThreeProp stored Fuct;

И последнее:
Чтобы добавить картинку в компонент для демонстрации в панели компонентов надо: - создать ее размером 24*24 с именем файла.dcr (в ресурсе имя картинки равно имени компонента, заглавными буками)
- картинку положить рядом с компонентом.

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

Создание папки

Создать папку в Delphi можно воспользовавшись функцией CreateDir или процедурой MkDir . Так же можно воспользоваться функцией ForceDirectories. Первые две команды корректно выполняют создание одной новой папки. Отличия же в том, как они себя ведут в случае если создать папку невозможно.

ForceDirectories(ExtractFilePath(Application.ExeName) + "/folder1/folder2/newfolder" );

Удаление папки

При удалении папки, важно учитывать есть ли в ней вложения или нет. Если папка пуста, то используется функция RemoveDir , в которой аналогично созданию, указывается путь к удаляемой папке. Функция при своем выполнении так же возвращает True, если удаление успешно и False, если удалить не удалось.

if RemoveDir("myfolder" ) then
ShowMessage("Папка успешно удалена." )
else
ShowMessage("Ошибка: папка не удалена." );

Если же папка не пуста, то можно использовать пользовательскую функцию, которая будет последовательно удалять все вложенные файлы, а затем и пустые папки. Для среды Delphi 2010, можно воспользоваться следующим методом:

TDirectory.Delete("myfolder" , True);

При этом, в разделе описаний должна быть добавлена библиотека IOUtils.

uses IOUtils;

Если же такой возможности нет, стоит использовать следующую функцию, описанную еще в DelphiWorld. В параметре указывается путь к удаляемой папке. При успешном удалении (включая все вложения), функция вернет значение True, если удаление не удалось, вернет False.

// Функция удаления директории с вложениями.
function MyDirectoryDelete(dir: string): Boolean;
var
fos: TSHFileOpStruct;
begin
ZeroMemory(@fos, SizeOf(fos));
with fos do begin
wFunc:= FO_DELETE;
fFlags:= FOF_SILENT or FOF_NOCONFIRMATION
pFrom:= PChar(dir + #0);
end ;
Result:= (0 = ShFileOperation(fos));
end ;

// Вызов функции удаление в программе.
begin if MyDirectoryDelete("myfolder" ) then
ShowMessage("Папка успешно удалена." )
else
ShowMessage("Ошибка: папка не удалена." );
end ;

В раздел описаний здесь необходимо добавить библиотеку ShellApi.

uses
ShellApi;

Проверка существования директории

Для проверки наличия директории используется функция DirectoryExists . В параметре так же указывается полный или относительный путь к папке. Если заданная папка существует, функция вернет True, в обратном случае False.

if DirectoryExists("myfolder" ) then
ShowMessage("Папка существует." )
else
ShowMessage("Такой папки нет." );



Статьи по теме