Главная » Delphi » Иерархия визуальных компонентов

0

Как уже было сказано в главе 2, “Язык программирования Object Pascal”, абстракт ный класс TОbjeсt является базовым классом,  от которого произошли все остальные классы Delphi  (см. рис. 10.1 и 10.2).

Разработчикам компонентов вовсе не обязательно создавать свои компоненты как непосредственные потомки класса  TОbjeсt. Библиотека VCL предоставляет широ кий выбор  классов потомков класса TОbjeсt, и создаваемые компоненты могут быть производными от них. Эти уже существующие  классы обеспечивают большинство функциональных  возможностей, которые могут  понадобиться новым  компонентам. Лишь  при  создании классов, не  являющихся компонентами, имеет  смысл  делать  их потомками класса TОbjeсt.

Методы  Create() и Destroy() класса TОbjeсt предназначены для выделения и

освобождения памяти для экземпляра объекта. Конструктор TОbjeсt.Create() воз

вращает  указатель  на  созданный  объект.  Класс  TОbjeсt содержит  несколько  полез

ных функций, позволяющих получить информацию об объекте.

Библиотека VCL использует в основном внутренние вызовы методов класса  TОb- jeсt, что  позволяет получить необходимую информацию о типе  класса,  его  имени, базовых классах (предках) для экземпляра любого  класса, поскольку  все они являются потомками TОbjeсt.CОВЕТ

Используйте  метод  TObject.Free() вместо  метода  TObject.Destroy().  Метод Free вызывает метод Destroy(), но перед этим проверяет, имеет ли указатель объ- екта значение nil, что позволяет избежать передачи исключения при попытке уничто- жить несуществующий объект.

Класс TPersistent

Класс  TPersistent происходит непосредственно от  класса  TОbjeсt. Особенно стью класса TPersistent является то, что экземпляры происходящих от него объек тов могут читать и записывать свои  свойства в поток.  Поскольку все компоненты яв ляются  потомками класса  TPersistent, то  все  они  обладают этой  способностью. Класс  TPersistent определяет не специальные свойства или  события, а только  не которые методы, полезные как пользователям, так и разработчикам компонентов.

Методы класса TPersistent

В табл. 10.3 приведен список наиболее интересных методов, определенных в клас

се TPersistent.

Таблица 10.3. Методы класса TPersistent

Метод                                                 Назначение

Assign()           Этот   открытый  (public)   метод   позволяет  компоненту присваивать себе данные, связанные с другим компонентом

AssignTo()         Это защищенный (protected) метод, в который производ ные   от  TPersistent классы   должны   помещать  реали зацию  собственного метода  AssignTo(), объявленного в VCL.  При   вызове  данного  метода   непосредственно  из класса  TPersistent передается исключение. С помощью такого  метода компонент может присвоить свои данные другому экземпляру класса — операция, обратная выполняе мой методом Assign()

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

Более  подробная информация о работе компонентов с потоками приведена в гла ве 12, “Работа  с файлами”, предыдущего издания —  Delphi 5 Руководство разработчика, находящегося на прилагаемом CD. А пока  достаточно знать,  что  с помощью потока компоненты могут быть сохранены и прочитаны из файла  на диске.

Класс TComponent

Этот  класс происходит непосредственно от класса  TPersistent. Отличительны ми  особенностями класса  TComponent являются возможность редактирования  его свойств в окне  инспектора объектов и способность объектов данного класса  владеть другими компонентами.

Невизуальные компоненты  также   происходят от  класса  TComponent,  наследуя возможность  их  редактирования  в  процессе  разработки.  Компонент  TTimer —  пре красный пример такого невизуального потомка класса TComponent. Не являясь визу

альным элементом управления, он, тем не менее,  доступен в палитре компонентов.

Класс TComponent определяет наиболее важные свойства и методы, описанные в следующих разделах.

Свойства класса TComponent

Свойства класса TComponent и описание их назначения приведены в табл. 10.4.

Таблица 10.4. Специальные свойства класса TComponent

Свойство                                     Назначение

Owner                Указывает владельца компонента

ComponentCount         Определяет  количество  компонентов,  принадлежащих  дан

ному компоненту

ComponentIndex         Текущая позиция в списке компонентов, принадлежащих дан

ному компоненту. Первый компонент списка имеет номер 0

Components       Массив,  содержащий список  компонентов, принадлежащих данному компоненту

ComponentState   Это  свойство содержит информацию о  текущем  состоянии компонента типа  TComponentState. Дополнительная инфо рмация о  классе  TComponentState содержится в интерак тивной справочной системе Delphi  и в главе 11, “Разработка компонентов VCL”

ComponentStyle   Управляет  поведением  компонента.  Этому  свойству   могут быть присвоены два значения — csInheritable и csCheck- PropAvail. Их назначение объясняется в интерактивной справочной системе Delphi

Name                 Содержит имя компонента

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

DesignInfo       Используется конструктором форм.  Значение этого  свойства изменять не следует

Методы класса TComponent

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

Класс  TComponent определяет конструктор компонентов Create(). Этот  конст руктор  создает  экземпляр компонента и назначает ему владельца на основе переда ваемого  ему параметра. В отличие от конструктора TObject.Create(), конструктор класса  TComponent.Create() является виртуальным. Потомки класса  TComponent, включающие реализацию этого  конструктора, обязаны заявить о конструкторе Cre-ate(), используя директиву override (переопределение). Хотя можно  использовать и другие конструкторы для класса компонента, однако  лишь конструктор VCL TCom- ponent.Create() позволяет создать  экземпляр класса  во время  разработки или  за грузить компонент из потока во время  выполнения программы.

Деструктор  TComponent.Destroy() уничтожает компонент  вместе  со  всеми  ре

сурсами, выделенными этим компонентом.

Метод  TComponent.Destroying() приводит сам  компонент и  принадлежащие ему  компоненты в  состояние,  предшествующее их  уничтожению.  Метод  TCompo- nent.DestroyComponents() уничтожает все компоненты, принадлежащие данному компоненту. Но эти методы  редко приходится использовать самостоятельно.

Метод TComponent.FindComponent() удобно использовать для получения указа теля на компонент с известным именем. Предположим, что главная  форма имеет компонент TEdit по имени Edit1. Тогда  для получения указателя  на экземпляр ком понента достаточно выполнить следующий код:

EditInstance := FindComponent.(‘Edit1′);

В этом  примере экземпляр компонента EditInstance должен  иметь  тип  TEdit. Метод  FindComponent возвратит значение nil, если  объект с указанным  именем не существует.

Метод  TComponent.GetParentComponent() позволяет найти экземпляр предка компонента. Данный метод  возвращает значение nil в случае отсутствия такого  ком понента.

Метод  TComponent.HasParent() возвращает логическое значение, определяю щее, есть ли у компонента родитель. Запомните, что этот метод не проверяет наличие владельца у заданного компонента.

Метод  TComponent.InsertComponent() позволяет добавить компонент, переходя щий во владение вызывающего компонента. Метод TComponent.RemoveComponent() удаляет  все компоненты, принадлежащие тому компоненту, который вызвал  этот  метод. В обычных случаях такие  методы  не используются, потому что они автоматически вызы ваются конструктором компонента Create() и его деструктором Destroy().

Класс TControl

Класс TControl определяет свойства, методы  и события, общие  для большинства визуальных компонентов. Например,  класс  TControl позволяет визуальным компо нентам  отображаться на экране. Класс TControl содержит такие  позиционные свой ства,  как Top и Left, свойства размеров Width и Height, значения которых опреде ляют  размеры элемента по горизонтали и вертикали. Имеются и некоторые другие свойства: ClientRect, ClientWidth и ClientHeight.

Класс  TControl содержит свойства, отвечающие за внешний вид и доступ к ком поненту:  Visible, Enabled и Color. В свойстве Font даже можно  задать  шрифт, ис пользуемый для текста, помещаемого в компонент TControl. Этот текст  выводится с помощью  свойств  Text и Caption.

В классе TControl впервые появляются некоторые стандартные события: события мыши — OnClick, OnDblClick, OnMouseDown, OnMouseMove и OnMouseUp, а также  со бытия перетаскивания с помощью мыши — OnDragOver, OnDragDrop и OnEndDrag.

Сам по себе класс TControl не очень  полезен на своем уровне  иерархии. Прямые потомки этого класса никогда не создаются.Компонент TControl может  иметь  родительский компонент. Он  обязательно должен  принадлежать классу TWinControl (в VCL) или  TWidgetControl (в CLX). Родительские элементы управления должны  быть  оконными (windowed) элементами управления. Для этого  в класс TControl введено свойство Parent.

Большинство элементов управления Delphi являются производными от прямых потомков класса TControl: классов TWinControl и TWidgetControl.

Классы TWinControl и TWidgetControl

Стандартные элементы управления происходят от класса  TWinControl (в VCL) и от класса TWidgetControl (в CLX). Объекты пользовательского интерфейса про грамм  Windows — это  и есть  стандартные элементы управления. Поля  редактирова ния  (edit   control), списки   (list  box),   раскрывающиеся  списки   (list  box)  и  кнопки (button) —  вот  примеры подобных элементов. Поскольку Delphi  сам инкапсулирует поведение стандартных элементов управления, а не  использует для этого  функции интерфейса API на уровне  Windows  или  Qt,  он  обладает возможностью непосредст венно  управлять этими  элементами.

Три  основные особенности класса  TWinControl: объекты этого  класса  имеют  де скриптор Windows,  могут получить фокус  ввода  и являться родительским элементом для других компонентов. Элементы управления CLX не имеют  дескриптора окна; вме сто него  используется указатель  на объект Qt,  который выполняет ту же самую роль. Свойства, методы  и события обеспечивают обработку изменения фокуса,  событий клавиатуры, отображение элементов и другие необходимые функции.

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

Свойства классов TWinControl и TWidgetControl

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

Свойство TWinControl.Brush используется для  отображения  элемента  управле

ния на экране. (Более подробная информация по этой теме приведена в главе 8, “GDI,

шрифты и графика”, предыдущего издания — Delphi 5 Руководство разработчика, нахо

дящегося на прилагаемом CD.)

Свойство массив   TWinControl.Controls предоставляет  доступ  к  списку   всех элементов управления, для которых вызывающий компонент TWinControl является родительским.

Свойство  TWinControl.ControlCount содержит  количество  дочерних  элемен

тов управления.

Свойство  TWinControl.Ctl3D определяет  использование  трехмерной  стилиза

ции при отображении элемента.

Свойство TWinControl.Handle содержит дескриптор объекта Windows,  инкапсу лированный классом  TWinControl. Именно этот  дескриптор следует использовать в качестве параметра функций API Win32, требующих указания дескриптора окна.

Свойство TWinControl.HelpContext содержит контекстный справочный номер, соответствующий определенному  справочному  окну  в  файле  справки. Это  свойствоприменяется для  поддержки функций контекстно зависимой справки для  отдельных элементов управления.

Свойство TWinControl.Showing содержит информацию о видимости элемента, а свойство TWinControl.TabStop —  логическое значение, определяющее поведение элемента при  использовании клавиши  <Tab>. Свойство TWinControl.TabOrder по казывает, где в списке  элементов родительского компонента, изменяющих фокус при нажатии клавиши  <Tab>, находится указанный элемент (если он там есть).

Методы класса TWinControl

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

Методы  создания окна,  его восстановления и уничтожения в основном применя ются разработчиками компонентов и рассматриваются в главе 11, “Разработка компо нентов VCL”. Это методы  класса TWinControl библиотеки VCL — CreateParams(), CreateWnd(), CreateWindowHandle(), DestroyWnd(), DestroyWindowHandle() и RecreateWnd(), а также  методы  класса  TWidgetControl библиотеки CLX — Cre- ateWidget(), DestroyWidget(), CreateHandle() и DestroyHandle().

К методам управления фокусом, позиционированием и выравнивания окна относятся:

CanFocus(), Focused(), AlignControls(), EnableAlign(), DisableAlign() и

ReAlign().

События класса TWinControl

Класс TWinControl предлагает новые  события для работы с клавиатурой и управле ния фокусом. События клавиатуры — это OnKeyDown, OnKeyPress и OnKeyUp. К событи ям управления фокусом относятся OnEnter и OnExit. Все они описаны в интерактивной справочной системе Delphi.

Класс TGraphicControl

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

Объект класса TGraphicControl способен реагировать на события мыши.  В дей ствительности сообщения мыши  обрабатываются родительским компонентом класса TGraphicControl, а затем передаются его дочерним элементам.

Класс TGraphicControl обладает способностью выводить на экран представляе

мые  им  элементы  управления, а  следовательно,  обладает свойством  Canvas типаTCanvas. Он также содержит метод Paint(), который производные классы элемен

тов обязаны переопределять.

Класс TCustomControl

Как можно  было  заметить, имена  некоторых классов,  производных от TWinCon- trol, начинаются с сочетания “TCustom”, например: TCustomComboBox, TCustom- Control, TCustomEdit и TCustomListBox.

Нестандартные, или  пользовательские  (custom),  элементы управления выполняют почти такие  же функции, как и потомки класса  TWinControl, за исключением того, что благодаря некоторым специальным визуальным особенностям и характеристикам поведения разработчик получает заготовку, на основе которой можно  создавать свои собственные пользовательские компоненты. Они  особенно полезны разработчикам компонентов, которым приходится создавать собственные визуальные элементы управления.

Другие классы

Несколько классов  не принадлежат к разряду  компонентов, но служат для про граммной поддержки существующих  компонентов. Как правило, эти классы являются свойствами других компонентов и происходят непосредственно от класса  TPersis- tent. Некоторые из них имеют типы TString, TCanvas и TCollection.

Классы TStrings и TStringsLists

Абстрактный класс  TStrings позволяет манипулировать списками строк, принад лежащих  компонентам, подобно тому, как это делается с помощью элемента управления типа  TListBox. Однако  на самом деле класс TStrings не управляет памятью для хра нения и обработки таких  строк  (этим  занимается тот элемент управления, который яв ляется владельцем класса TStrings). Класс TStrings лишь определяет методы  и свой ства, необходимые для доступа к строкам и их обработки, не используя ни функции API, ни системные сообщения.

Заметьте, что TStrings — это абстрактный класс, т.е. в нем нет реализации кода, не обходимого для работы со строками, он лишь определяет требуемые методы.  Реализа ция же методов обработки строк относится к компетенции потомков этого класса.

Чтобы внести ясность, приведем такой  пример. Допустим, имеется несколько компонентов  со  свойствами  типа   TStrings —   TListBox.Items,  TMemo.Lines и TComboBox.Items. Каждое  из этих  свойств имеет  тип TStrings. Но как вызвать ме тоды этих свойств, если они еще не воплощены в коде? Хороший вопрос. Ответ таков: хотя  все эти  свойства определены как TStrings, переменная, к которой относится, например, свойство TListBox.FItems, будет создана  как  экземпляр производного класса, методы  которого и будут вызываться. Чтобы прояснить этот момент, отметим, что переменная FItems является закрытым полем свойства Items класса TListBox:

TCustomListBox = class(TWinControl)

private

FItems: TStrings;Модуль StdCtrls.pas, являющийся частью  библиотеки VCL, определяет класс TListBoxStrings как производный от класса TStrings. Листинг 10.1 демонстрирует его определение.

Листинг 10.1. Объявление класса TListBoxStrings

TListBoxStrings = class(TStrings)

private

ListBox: TCustomListBox;

protected

procedure Put(Index: Integer; const S: string); override;

function Get(Index: Integer): string; override;

function GetCount: Integer; override;

function GetObject(Index: Integer): TObject; override;

procedure PutObject(Index: Integer;

AObject: TObject); override;

procedure SetUpdateState(Updating: Boolean); override;

public

function Add(const S: string): Integer; override;

procedure Clear; override;

procedure Delete(Index: Integer); override;

procedure Exchange(Index1, Index2: Integer); override;

function IndexOf(const S: string): Integer; override;

procedure Insert(Index: Integer; const S: string); override;

procedure Move(CurIndex, NewIndex: Integer); override;

end;

Затем  StdCtrls.pas определяет реализацию каждого  метода  этого  производного класса. Когда класс TListBox создает  экземпляры для своей  переменной FItems, на самом деле создается экземпляр его производного класса, к свойству FItems которого и происходит обращение:

constructor TCustomListBox.Create(AOwner: TComponent);

begin

inherited Create(AOwner);

// Создается экземпляр TListBoxStrings

FItems := TListBoxStrings.Create;

end;

Следует четко  уяснить,  что класс TStrings лишь определяет свои методы, но не со держит их  реализацию —  ее  осуществляют производные  классы.  Всем  разработчикам компонентов полезно изучить  данную технологию. Когда возникают какие либо вопро сы или сомнения по этому поводу, всегда можно обратиться к исходному коду библиотек VCL или CLX, чтобы увидеть, как именно Borland реализовала такие методы.

Если речь  не идет  о разработке компонента, то при  необходимости манипулиро вания  списком  строк  следует  воспользоваться другим  потомком класса  TStrings — вполне самодостаточным классом  TStringList. Он обрабатывает список  строк, раз мещаемых  вне  компонента. Его  главным   достоинством является полная совмести мость  с классом  TStrings. Это означает, что  экземпляр класса  TStringList можноприсвоить непосредственно  соответствующему свойству  элемента управления класса TStrings. В следующем фрагменте кода показано, как можно  создать  экземпляр клас са TStringList:

var

MyStringList: TStringList;

begin

MyStringList := TStringList.Create;

Чтобы  добавить  строки  во  вновь  созданный  экземпляр  класса  TStringList,  по

ступите следующим образом:

MyStringList.Add(‘Red’); MyStringList.Add(‘White’); MyStringList.Add(‘Blue’);

Если   необходимо  добавить  одинаковые  строки  одновременно  в  компоненты TMemo и TListBox, можно  воспользоваться совместимостью свойств TStrings, при надлежащих различным компонентам, и выполнить присвоение одной строкой кода:

Memo1.Lines.Assign(MyStringList); ListBox1.Items.Assign(MyStringList);

Вместо непосредственного присвоения, подобного Memo1.Lines := MyStringList, можно скопировать экземпляр класса TStrings с помощью метода Assign(). В табл. 10.5 приведены наиболее часто используемые методы классов типа TStrings.

Таблица 10.5. Наиболее популярные методы класса TStrings

Метод                                                                             Описание

Add(const S: String): Integer Добавляет строку  S в список  и возвращает ее позицию в нем

AddObject(const S: string; Aobject: TObject): Integer

Добавляет строку  и объект в строку  или  в объект списка строк

AddStrings(Strings: TStrings)  Копирует  строки  из   указанного  объекта TStrings в конец  существующего  списка строк

Assign(Source: TPersistent)    Замещает существующие  строки строками, заданными параметром SourceМетод          Описание

Clear                             Удаляет все строки из списка

Delete(Index: Integer)            Удаляет   строку,   находящуюся  в  позиции

Index

Exchange(Index1, Index2: Integer)

IndexOf(const S: String): Integer

I nsert(Index: Integer;

const S: String)

Move(CurIndex, NewIndex: Integer)

LoadFromFile(const FileName: String)

SaveToFile(const FileName:

string)

Класс TCanvas

Меняет   местами     строки   с    позициями

Index1 и Index2

Возвращает позицию строки S в списке

Вставляет строку S в позицию Index

Перемещает строку с позицией CurIndex в позицию NewIndex

Считывает текстовый файл  по имени File- Name и помещает его строки в список

Сохраняет список  в текстовом файле

FileName

Свойство Canvas типа  TCanvas применяется в оконных элементах управления и представляет собой  его поверхность, используемую  для прорисовки содержимого ок на.   Класс   TCanvas инкапсулирует  так   называемый  контекст  устройства (device context) окна. Этот класс содержит множество функций и объектов, необходимых для прорисовки поверхности окна.  Более  подробная информация по данной теме  приве дена в главе 8, “GDI, шрифты и графика”, предыдущего издания — Delphi 5 Руководство разработчика, находящегося на прилагаемом CD.

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии