Справочное руководство по 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 и удачи!

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

Code:

OpenDialog1.Options:= OpenDialog1.Options + ;

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

Code:

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

Обратите внимание: Комбинации клавиш Ctrl + Shift + стрелки вверх/вниз позволяют перемещаться между объявлением метода и его реализацией. Установка созданного компонента 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 и удачи!

{======================================================}

unit OurOpenDialog;

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

TOurOpenDialog = class(TOpenDialog)

{ Private declarations }

{ Protected declarations }

{ Public declarations }

constructor Create(AOwner: TComponent); override;

{ Published declarations }

procedure register;

procedure register;

RegisterComponents("Samples", );

{ TOurOpenDialog }

constructor TOurOpenDialog.Create(AOwner: TComponent);

inherited Create(AOwner); {Вызываем

унаследованный конструктор}

Options:= Options + ;

{Выполняем необходимые нам действия}

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

Свойства

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

TOurComponent = class(TComponent)

{ Private declarations }

FArrayProp: array of integer;

function GetArrayProp(aIndex: integer): integer;

procedure SetArrayProp(aIndex: integer; const

Value: integer);

{ Protected declarations }

{ Public declarations }

property ArrayProp: integer read

write SetArrayProp;

{ Published declarations }

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

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

Code:

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

Например:

Code:

property AutoSize nodefault ;

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

Code:

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;

Форма "О программе" используется в качестве информативных целей. Чаще всего в ней пишется наименование программы, назначение, авторы и лицензионное соглашение. Чаще всего размещается в главном меню в пункте Помощь->О программе....

Для создание формы "О программе" в Delphi (Делфи, Дельфи) нужно создать обычную форму, как на рисунке ниже:

Для создания любой формы в Delphi 7 используем следующую команду из меню File->New->Form, а при разработке проекта в более новой среде, к примеру Delphi XE2, нужно использовать немного другую команду: File->New->VCL Form - Delphi.

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

  • Выставить свойство Position. По умолчанию здесь указано значение poDesigned, которое диктует открываемой форме появляться там, где она находилась в момент создания программы. Поэтому нужно выставить, так чтобы форма появлялась по центру относительно формы, из которой она была вызвана. Для этого в свойство Position надо выставить значение poOwnerFormCenter.
  • Также можно отключить свойство AutoScroll, чтобы не появлялись полосы прокрутки.
  • Так как в форме будет краткая статическая информация, то иметь возможность изменять размеры формы во время выполнения нет никакой необходимости. Поэтому в свойстве BorderStyle выставить значение bsSingle.
  • Еще нужно настроить вложенные свойства в BorderIcons. Нужно в свойствах biMinimize и biMaximize выставить значения в false, что не позволит минимизировать и развернуть форму соответственно.

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

Также при использовании TLabel можно выставить Transparent в true. Данная опция сделает так, чтобы фон метки был прозрачен, что будет выглядеть намного красивее, если используется вспомогательный фон.

Заключение

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

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

Все компоненты, как объекты, имеют множество свойств, определяющих их работу. При установке компонента на Форму из палитры большинство этих свойств определяются системой 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);

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

  • Обзор
  • Соглашения по наименованиям
  • Выбор предка
  • Пример создания компонента
  1. Обзор
  2. Поскольку Delphi является открытой средой и позволяет не только использовать объекты из Библиотеки Визуальных Компонент (VCL) в своей программе, но и создавать новые объекты. Причем, ничего другого, кроме Delphi, для этого не требуется. Создание нового объекта в Delphi не является очень сложной задачей, хотя для этого и требуется знание Windows API, объектно-ориентированного программирования и иерархии классов в VCL.

    Может возникнуть вопрос; если в Delphi уже есть своя библиотека, то зачем еще создавать какие-то объекты? Ответ прост: нельзя создать библиотеку на все случаи жизни и на все вкусы. Новые компоненты, во-первых, позволяют расширить область применения Delphi: например, с помощью библиотек объектов третьих фирм разрабатывать приложения для работы в Internet. Во-вторых, позволяют дополнить или настроить для себя имеющиеся в VCL объекты (например, переопределить значения свойств, устанавливаемые по умолчанию).

  3. Добавление новых объектов в VCL
  4. Предположим, что у вас появился уже готовый компонент. Как его добавить в VCL? Для этого выберите пункт меню Options|Install Components… Появится диалог, как на рис.1

    Рис. 1 : Диалог установки нового компонента

    Нажмите “Add” и укажите модуль, содержащий процедуру регистрации, нажмите “OK” и после успешной перекомпиляции новый объект появится в палитре.

  5. Заготовка для нового компонента
  6. В среде Delphi есть специальный эксперт, создающий заготовку для нового компонента. Вызвать его можно в пункте меню File|New Component… (см рис.2)


    Рис. 2 : Эксперт для создания нового компонента

    В диалоге нужно указать имя нового класса (например, TMyButton), предка класса (TButton) и страницу палитры, куда поместить новый компонент (Samples). Если нажать “OK”, то эксперт создаст модуль - заготовку для нового компонента:

    unit Unit1;

    interface

    uses

    SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

    Forms, Dialogs, StdCtrls;

    type

    TMyButton = class(TButton)

    private

    { Private declarations }

    protected

    { Protected declarations }

    public

    { Public declarations }

    published

    { Published declarations }

    end;

    procedure Register;

    implementation

    procedure Register;

    begin

    RegisterComponents("Samples", );

    end;

    end.

    Модуль содержит декларацию нового класса и процедуру его регистрации в Палитре Компонент. В процедуре RegisterComponents первый параметр - имя страницы (можно указать свое имя - появится новая страница); второй параметр - множество объектов для регистрации.

    Теперь модуль нужно сохранить под новым именем (например, NEW_BTN.PAS) и приступить к дописыванию новых свойств и методов. После того, как эта работа закончена и новый компонент отлажен, можно добавить его в Палитру (см. предыдущую главу). Но перед этим желательно создать файл ресурсов, в котором будет лежать пиктограмма для представления данного объекта в Палитре Компонент. Файл ресурсов можно создать с помощью программы Resource Workshop, называться он должен точно так же, как модуль регистрации компонента и иметь расширение.DCR (т.е., если объект регистрируется в модуле NEW_B TN .PAS, то тогда имя файла ресурсов будет NEW_BTN.DCR). В файле ресурсов должен находиться ресурс типа BITMAP - картинка размером 28x28 точки (можно меньше), название картинки должно совпадать с именем класса (в нашем случае TMYBUTTON).

  7. Соглашения по наименованиям

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

Итак:

  • Все декларации типов начинаются на букву T. Еще раз, Delphi не требует этого, но это делает очевидным, что "TEdit", например, есть определение типа, а не переменная или поле класса.
  • Имена свойствам нужно давать легко читаемые и информативные. Нужно помнить, что пользователь будет их видеть в Инспекторе Объектов. И имя вроде "TextOrientation" много удобнее, нежели "TxtOr". То же самое относится к методам. Методы, доступные пользователю, должны иметь удобные названия.
  • При создании свойств типа Event, имя такого свойства должно начинаться с “On” (например, OnClick, OnCreate и т.д.).
  • Имя метода для чтения свойства должен начинаться со слова “Get”. Например, метод GetStyle должен выполнять чтение для свойства Style.
  • Имя метода для записи свойства должен начинаться со слова “Set”. Например, метод SetStyle должен выполнять запись в свойство Style.
  • Внутреннее поле для хранения данных свойства должно носить имя, начинающееся с буквы “F”. Например, свойство Handle могло бы храниться в поле FHandle.

Конечно же, есть исключения из правил. Иногда бывает удобнее их нарушить, например, класс TTable имеет свойства типа Event, которые называются BeforePost, AfterPost и т.п.

  1. Выбор предка

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

  • TObject - Можно использовать в качестве предка, если с этим компонентом не нужно работать во время дизайна. Это может быть, например, класс, содержащий значения переменных среды (environment) или класс для работы с INI файлами.
  • TComponent - Отправная точка для многих невидимых компонент. Данный класс обладает встроенной возможностью сохранять/считывать себя в потоке во время дизайна.
  • TGraphicControl - Используйте этот класс для создания видимых компонент, которым не нужен handle. Такие компоненты рисуют прямо на своей поверхности и требуют мало ресурсов Windows.
  • TWinControl - Базовый класс для компонент, которые имеют окно. Данное окно имеет свой handle, его используют при доступе к возможностям Windows через API.
  • TCustomControl - Потомок TWinControl, вводит понятие канвы (Canvas) и метод Paint() для лучшего контроля за прорисовкой компонента. Именно этот класс используется в качестве базового для построения большинства видимых компонент, имеющих оконный handle.
  • TXxxxx - Класс вроде TEdit или TButton. Используются с целью доопределения их свойств и методов или переопределения значения свойств, принимаемых по умолчанию.
  1. Пример создания компонента

Для примера создадим новый класс, мутант TButton, в котором изменим значение по умолчанию свойства ShowHint на True и добавим новое свойство - счетчик нажатий на кнопку. Заготовка модуля для создания нового компонента уже есть (см. пункт Заготовка для нового компонента ). Теперь исходный текст выглядит так:

unit New_btn;

interface

uses

SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls;

type

TMyButton = class(TButton)

private

{ Private declarations }

FClickCount: Longint;

protected

{ Protected declarations }

public

{ Public declarations }

constructor Create(AOwner: TComponent); override;

procedure Click; override;

property ClickCount: Longint read FClickCount write

  • FClickCount;
  • published

    { Published declarations }

    end;

    procedure Register;

    implementation

    constructor TMyButton.Create(AOwner: TComponent);

    begin

    inherited Create(AOwner);

    ShowHint:=True;

    FClickCount:=0;

    end;

    procedure TMyButton.Click;

    begin

    Inc(FClickCount);

    inherited Click;

    end;

    procedure Register;

    begin

    RegisterComponents("Samples", );

    end;

    end.

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

    Новое свойство для подсчета нажатий на клавишу называется ClickCount. Его внутреннее поле для сохранения значения - FClickCount имеет тип Longint, емкости поля хватит надолго.