Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Delphi. Изучение VCL. Создание собственных компонентов.


Информационный Канал Subscribe.Ru


Изучение и создание компонентов Delphi. Выпуск №1
 
Доброе время суток, уважаемые подписчики.
Имею честь представить вам первый номер рассылки.

Цель данной рассылки - изучить тонкости и хитрости библиотеки визуальных компонентов Дельфи (VCL) и научиться самим создавать достойные и полезные компоненты.

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

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

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

На этом вводная информационная часть заканчивается и начинается собственно рассылка :).

  • Компонент
  • TObject
  • Методы TObject

    Компонент - это объект, с которым мы можем совершать различные манипуляции в режиме дизайна (design time) в среде Дельфи. Если совсем упростить, то компонент - это то, что мы можем взять с палитры компонентов (component palette) и бросить на форму, а потом в инспекторе свойств (object inspector) изменять его свойства. Все компоненты являются наследниками класса TComponent. Визуальные компоненты - те, которые появляется на экране во время выполнения программы, например TForm или TString и им подобные, называются элементами управления (controls) и наследуются от класса TControl.

    Однако, VCL Дельфи включает в себя, противореча названию :), не только визуальные компоненты, например TDatabase, TDataSource и им подобные, которые не являются визуальными, хотя мы также можем ими управлять в режиме дизайна с помощью инспектора объектов. Помимо этого в VCL входят классы вообще не являющиеся компонентами, такие как TObject, TException, TPersistent и другие.

    Все классы VCL порождены от базового класса TObject, а в предках всех компонентов стоит TComponent. Хорошо зная иерархию компонентов, мы можем свободно ориентироваться в наследуемых объектами методах, свойствах и событиях, и соответственно лучше выбирать родителей для своих компонентов. Потому давайте для начала изучим или же вспомним :) методы, свойства и события и общее назначение классов TObject, TPersistent, TComponent и TControl.

    TObject (unit system):

    Класс TObject является прародителем всех объектов и компонентов VCL. Он отвечает за базовое поведение объектов, общее для них всех, инкапсулируя методы, обеспечивающие:
    - способности создавать и уничтожать объекты, соответственно выделяя, инициализируя и освобождая память, затребованную объектом.
    - доступ к информации о типе объекта (его классе) и к таблице RTTI
    - поддержку обработки сообщений (message - handling)
    - поддержку интерфейсов, используемых объектом
    Многие из методов, введенных TObject, используются лишь оболочкой Delphi и не предназначены для непосредственного вызова. Другие, как правило, перекрываются в потомках с более сложным, чем у объектов TObject поведением.
    Формально, TObject не является абстрактным классом, однако объекты этого типа нельзя присвоить друг другу.
    Если при объявлении нового класса не указан родительский класс, то Delphi автоматически определяет TObject в качестве родительского класса.

    Методы класса TObject:

    procedure AfterConstruction; virtual; Вызывается автоматически после выполнения последнего конструктора объекта. Не стоит вызывать явно в своем приложении.
    Метод AfterConstruction, объявленный в классе TObject ничего не делает, перекрывайте этот метод, если вам необходимо произвести какие-то действия после создания объекта. Например, класс TCustomForm перекрывает AfterConstruction для генерации события OnCreate.
    procedure BeforeDestruction; virtual; Автоматически вызывается перед выполнением первого деструктора объекта. Не стоит вызывать его явно в своем приложении. Как и AfterConstruction, BeforeDestruction объявленный в TObject ничего не делает, перекрывайте этот метод, если перед уничтожением объекта вам необходимо произвести какие-то действия. Например, класс TCustomForm перекрывает BeforeDestruction для генерации события OnDestroy.
    class function ClassInfo: Pointer; ClassInfo возвращает указатель на таблицу RTTI данного объекта.
    Метод используется внутри среды Дельфы, в пользовательском приложении явно (непосредственно) вызывается редко.
    Помимо функции ClassInfo, класс TObject включает в себя и другие методы для доступа к информации RTTI.
    class function ClassName: ShortString; Возвращает строку с названием типа объекта, может использоваться как аргумент.
    Метод полезен для различения объекта, который присваивается какой-либо переменной, имеющей тип предка данного объекта. В этом случае метод возвратит строку, содержащую настоящее название типа объекта, отличного от типа переменной.
    class function ClassNameIs(const Name: string): Boolean; Возвращает True, если тип объекта имеет название Name.
    class function ClassParent: TClass; Возвращает тип непосредственного родителя данного класса.
    Используется неявно при выполнении операторов as и is и при выполнении метода InheritsFrom.
    ClassParent возвращает nil для TObject, потому что TObject не имеет родителя.
    Не стоит использовать этот метод в своем приложении явно, если можно обойтись операторами is и as.
    function ClassType: TClass;

    Возвращает указатель на RTTI для данного объекта, динамически определяет тип объекта. Используется неявно при выполнении операторов as и is, не стоит вызывать явно, если можно обойтись этими операторами.
    procedure CleanupInstance; Метод вызывается автоматически при уничтожении объекта и очищает поля объекта типов long string и variant.
    Не рекомендуется вызывать данный метод явно.
    constructor Create; Создает объект и инициализирует его данные.
    Метод Create, определенный в TObject не делает ничего особенного, в том числе не инициализирует никакие данные, однако при его вызове автоматически выделяется память, требуемая объекту. Классы-потомки, как правило, определяют конструкторы в соответствии со своими нуждами, в том числе и инициализирующие, если это нужно, какие-либо данные.
    procedure DefaultHandler (var Message); virtual; Метод DefaultHandler обеспечивает обработку всех сообщений, для которых объект не имеет определенных обработчиков. Вызывается методом Dispatch, если для данного сообщения не найден специальный обработчик.
    Классы-потомки, собирающиеся работать с какими-либо сообщениями, перекрывают этот метод в соответствии с типом обрабатываемого сообщения. Для примера, TWinControl перекрывает DefaultHandler для вызова DefWndProc
    destructor Destroy; virtual; Уничтожает объект данного класса.
    Не рекомендуется вызывать метод Destroy явно, лучше обращаться к методу Free, который сначала проверит, что объект не равен nil и только потом вызовет Destroy.
    Метод Destroy класса TObject не делает ничего специального, однако, при его вызове автоматически освобождается память, занятая объектом.
    Классы-наследники обычно определяют деструктор в соответствии со своими особенностями.
    При объявлении метода Destroy в потомках всегда добавляется директива override, а в конце перекрываемого метода вызывается метод Destroy, унаследованный от родителя.
    procedure Dispatch (var Message); virtual; Вызывает метод для обработки сообщения Message, полученного объектом.
    function FieldAddress(const Name: ShortString): Pointer; Возвращает указатель на поле объекта объявленное в секции published.
    procedure Free; Уничтожает объект и освобождает занимаемую им память.
    procedure FreeInstance; virtual; Освобождает память выделенную до этого методом NewInstance.
    Поскольку вызывается автоматически методом Destroy, то не требует явного вызова.
    При перекрытии метода NewInstance метод FreeInstance должен быть изменен соответственно изменениям NewInstance.
    function GetInterface(const IID: TGUID; out Obj): Boolean; Функция GetInterface используется неявно при выполнении оператора as для нахождения любого интерфейса, объявленного объектом.
    GetInterface используется классом TInterfaceObject при реализации метода QueryInterface. Название типа интерфейса указывается посредством параметра IDD, компилятор заменяет его на интерфейс с соответствующим GUID. Те классы VCL, которые не наследуются от класса TInterfaceObject, также способны объявлять интерфейсы. Оператор as может использоваться для приведения объектов таких классов к выбранному интерфейсу, но если в этом классе интерфейс все-таки не объявлен, то это вызовет исключение.
    В качестве выходного параметра Obj метод GetInterface возвращает ссылку на интерфейс идентифицированный по параметру IID. Если интерфейс поддерживается объектом, функция GetInterface вернет True, в обратном случае будут возвращены False в качестве результата функции и nil в параметре Obj.
    class function GetInterfaceEntry (const IID: TGUID): PInterfaceEntry; Метод GetInterfaceEntry возвращает точку входа для конкретного интерфейса, объявленного в классе.
    Используется, как правило, неявно.
    class function GetInterfaceTable: PInterfaceTable; Метод возвращает ссылку на структуру, содержащую все интерфейсы, объявленные в классе.

    Type
    PInterfaceTable = ^ TInterfaceTable;

    TInterfaceTable = packed record
       EntryCount: integer;
       Entries: array[0...9999] of TinterfaceEntry;
    End;

    GetInterfaceTable возвращает ссылку на TInterfaceTable данного класса. Чтобы получить доступ к интерфейсам объявленным в родителе этого класса, необходимо использовать методы GetParentClass и после родительский GetInterfaceTable.
    Для нахождения определенного интерфейса, используйте функцию GetInterfaceEntry.

    class function InheritsFrom(AClass: TClass): Boolean; Определяет родство двух классов.
    Используйте для определения, является ли конкретный класс предком рассматриваемого класса.
    Функция InheritsFrom возвращает True, если объектный тип, определенный параметром AClass, является предком класса, к которому принадлежит данный объект. В противном случае возвращается False.
    Операторы as и is используют InheritsFrom при обращении к ним. Однако оператор is может определить только наследственную связь объектов, тогда как классовый метод InheritsFrom используется и для определения родственности классов.
    class procedure InitInstance (Instance: Pointer): TObject; Устанавливает новому объекту нулевые значения и инициализирует таблицу указателей виртуальных методов данного класса.
    Не нужно вызывать этот метод явно. InitInstance вызывается автоматически методом NewInstance при создании нового объекта. Перекрывая NewInstance, следует вызвать в конце перекрываемого метода метод InitInstance.
    Метод InitInstance не виртуальный, поэтому его нельзя перекрыть. Вместо этого, если необходимо, инициализируйте данные объекта в конструкторе этого объекта.
    class function InstanceSize: Longint; Возвращает размер в байтах для каждого экземпляра данного класса.
    Используйте метод для определения количества занимаемой памяти данными объекта. Дельфи использует внутри себя функцию InstanceSize в методах выделяющих и возвращающих обратно память необходимую объектам.
    Метод InstanceSize не виртуальный, поэтому его нельзя перекрыть.
    class function MethodAddress (const Name: ShortString): Pointer; Возвращает адрес указанного параметром Name метода.
    class function MethodName (Address: Pointer): ShortString; Возвращает строку содержащую название метода, чей адрес передается в функцию параметром Address..
    class function NewInstance: TObject; virtual; Выделяет память для каждого экземпляра класса и возвращает указатель на созданный объект. Все конструкторы автоматически вызывают NewInstance.
    Метод NewInstance вызывает InstanceSize для определения объема требуемой объектом памяти.
    Не вызывайте функцию NewInstance явно.
    Перекрывайте NewInstance только для специальных запросов на выделение памяти. Например, когда большое количество одинаковых объектов нуждаются в памяти одновременно, можно выделить огромный блок памяти для всей группы целиком и перекрыть NewInstance для использования частей этого блока для каждого объекта.
    function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult; virtual; SafeCallException используется для поддержки управления COM-исключений.

    Таким образом мы обзорно познакомились с классом TObject и его методами, и заодно с рекомендациями help-системы Delphi по использованию некоторых из этих методов :)). В следующем выпуске будут рассмотрены классы TPersistent и TComponent.

    C уважением, RHel.


    1 - VCL
    VCL (Visual Component Library) - библиотека визуальных компонент - это иерархия классов, написанных на языке Object Pascal и взаимодействующая с интегрированной средой разработки Дельфи, обеспечивающей быструю разработку приложений.

    2 - Объект
    Под объектом мы будем понимать экземпляр какого-либо класса, а под классом, соответственно , - объектный тип данных.

    3 - RTTI
    RTTI - (Run Time Type Information) информация о типах времени выполнения (механизм, позволяющий определять тип объекта во время выполнения программы). В Дельфи это по большей части используется интегрированной средой разработки (IDE), которой требуется информация о полях, методах и свойствах компонентов, объявленных в секции published.


  • http://subscribe.ru/
    E-mail: ask@subscribe.ru
    Отписаться
    Убрать рекламу

    В избранное