Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
9 Разработка компонентов в среде Delphi.doc
Скачиваний:
15
Добавлен:
20.08.2019
Размер:
948.74 Кб
Скачать

9.3.1. Простые свойства

Простые свойства — это числовые, строковые и символьные свойства. Они могут непосредственно редактироваться в Инс­пекторе объектов и не требуют специальных методов доступа.

Рассмотрим создание простого свойства Color, описанного в классе TContol (модуль controls.pas):

Type

TControl = class (TComponent)

private

FColor: TColor;

function IsColorStored: Boolean;

procedure SetColor(Value: TColor);

protected

property Color: TColor read FColor write SetColor stored IsColorStored default clWindow;

end;

function TControl.IsColorStored: Boolean;

begin

Result := not ParentColor;

end;

procedure TControl.SetColor (Value: TColor);

begin

if FColor <> Value then

begin

FColor := Value;

FParentColor := False;

Perform(CM_COLORCHANGED, 0, 0) ;

{вызов Perform позволяет обойти очередь сообщений Windows и послать сообщение, в данном случае — изменить цвет, элементу управления}

end;

end;

9.3.2. Свойства перечислимого типа

Определенные пользователем перечислимые и логические свойства можно редактировать в окне инспектора объектов, вы­бирая подходящее значение свойства в раскрывающемся списке. Рассмотрим создание свойства перечислимого типа на при­мере компонента Shape (модуль extctrls.pas).

Туре

TShapeType = (stRectangle, stSquare, stRoundRect, stRoundSquare, stEllipse, stCircle);

{вначале необходимо определить новый тип — перечислить возможные значения}

Туре

TShape = class(TGraphicControl)

private

FShape: TShapeType;

procedure SetShape(Value: TShapeType);

published

property Shape: TShapeType read FShape write SetShape

default stRectangle;

end;

procedure TShape.SetShape{Value: TShapeType);

begin

if FShape <> Value then

begin

FShape := Value;

Inva 1 idate; {гарантирует перерисовку компонента}

end;

end;

9.3.3. Свойства типа множества

Свойство типа множества при редактировании в окне Инспек­тора объектов выглядит так же, как множество, определенное синтаксисом языка Pascal. Простейший способ его отредактиро­вать — развернуть свойство в Инспекторе объектов, в результате каждый его элемент станет отдельным логическим значением.

При создании свойства типа множества нужно создать соот­ветствующий тип, описать методы доступа, после чего описать само свойство. В модуле Controls.pas свойсво Align описано сле­дующим образом:

Туре

TAlign = (alNone, alTop, alBottom, alLeft, alRight, alClient);

TAlignSet = set of TAlign; TControl = class(TComponent)

private

FAlign: TAlign;

procedure SetAlign(Value: TAlign);

public

property Align: TAlign read FAlign write SetAlign default alNone;

end;

procedure TControl.SetAlign(Value: TAlign);

var OldAlign: TAlign;

begin

if FAlign <> Value then

begin

OldAlign := FAlign;

FAlign := Value;

Anchors := AnchorAlign[Value];

if not (csLoading in ComponentState) and

(not (csDesigning in ComponentState) or (Parent <> NIL))

then

if ((OldAlign in [alTop, alBottom])=(Value in [alRight, alLeft])) and not (OldAlign in [alNone, alClient]) and not (Value in [alNone, alClient]) then SetBounds(Left, Top, Height, Width)

{изменение границ компонента}

else AdjustSize; {устанавливает заданные размеры компонента}

end;

Request Align; {нструктирует «родителя» переставить компонент

в соответствии со значением свойства Align }

end;

9.3.4. Свойство-объект

Свойства могут являться объектами или другими компонен­тами. Например, у компонента Shape есть свойства-объекты Brush и Реп. Когда свойство является объектом, то оно может быть развернуто в окне инспектора так, чтобы его собственные свойства также могли быть модифицированы. Свойства-объек­ты должны быть потомками класса TPersistent, чтобы их свой­ства, объявленные в разделе published, могли быть записаны в поток данных и отображены в инспекторе объектов.

Для определения объектного свойства компонента необходимо сначала определить объект, который будет использоваться в каче­стве типа свойства. В модуле graphics.pas описан класс TBrush:

TBrush = class(TGraphicsObject)

private

procedure GetData(var BrushData: TBrushData);

procedure SetData(const BrushData: TBrushData);

protected

function GetBitmap: TBitmap;

procedure SetBitmap(Value: TBitmap);

function GetColor: TColor;

procedure SetColor(Value: TColor);

function GetHandle: HBrush.;

procedure SetHandle(Value: HBrush);

function GetStyle: TBrushStyle;

procedure SetStyle(Value: TBrushStyle);

public

constructor Create; destructor Destroy; override;

procedure Assign(Source: TPersistent); override;

property Bitmap: TBitmap read GetBitmap write SetBitmap;

property Handle: HBrush read GetHandle write SetHandle;

published

property Color: TColor read GetColor write SetColor

default clWhite;

property Style: TBrushStyle read GetStyle write SetStyle

default bsSolid;

end;

Метод Assign предназначен для копирования значения свойств экземпляра TBrush:

procedure TBrush.Assign (Source: TPersistent);

begin

if Source is TBrush then

begin

Lock; {блокирует использование объекта}

try

TBrush(Source).Lock;

try

BrushManager.AssignResource(Self, TBrush(Source).FResource);

finally TBrush(Source).Unlock;

end;

finally Unlock; {завершает секцию кода, начатую методом Lock,

снимая блокировку объекта}

end;

exit:

end;

inherited Assign(Source);

end;

Чтобы определить свойство-объект, нужно определить внут­реннее поле. Так как свойство представляет объект, его нужно создать, а по завершении — уничтожить, поэтому в код включены конструктор Create и деструктор Destroy. Кроме того, объявлен метод доступа SetBrush, предназначенный для записи свойства Brush.

TShape = class(TGraphicControl)

private

FBrush: TBrush;

procedure SetBrush(Value: TBrush);

public

constructor Create (AOwner: TComponent) ; overrider;

destructor Destroy; overrider;

published

property Brush: TBrush read FBrush write SetBrush;

end;

constructor TShape.Create(AOwner: TComponent);

begin

inherited Create(AOwner);

FBrush := TBrush.Create;

FBrush.OnChange := StyleChanged;

end;

destructor TShape.Destroy;

begin

FBrush. Freer-inherited Destroy;

end;

procedure TShape.SetBrush (Value: TBrush);

begin

FBrush.Assign(Value);

end;

9.3.5. Свойство-массив

Примерами свойств-массивов могут служить такие свойства, как TMemo.Lines, TScreen.Fonts, TStringGrid.Cells.

Особенности свойства-массива заключаются в следующем:

свойства-массивы объявляются с помощью индексных па­раметров, цель которых — указать количество и тип ин­дексов, которые будут использоваться свойством;

спецификации методов чтения и записи должны ссылать­ся на методы доступа. Методом для определителя read должна быть функция, список параметров которой совпа­дает со списком параметров, описывающих индекс свойст­ва, и возвращающей значение того же типа, что и свойст­во. В свою очередь, методом в определителе write должна быть процедура, список параметров которой совпадает со списком параметров, описывающих индекс свойства. Спи­сок параметров такой процедуры может содержать и до­полнительные свойства.

TCanvas = class (TPersistent)

private

FHandle: HDC; {ссылка на контекст устройства, используется для отображения графической информации}

function GetPixel (X, Y: Integer) : TColor; {метод чтения}

procedure SetPixel (X, Y: Integer; Value: TColor);

{метод записи}

protected

public

constructor Create;

destructor Destroy; override;

property Pixels[X, Y: Integer]: TColor read GetPixel write SetPixel;

end;

constructor TCanvas.Create;

begin

inherited Create;

CanvasList. Add (Self) ; {добавляет в список ссылки на объекты}

end;

destructor TCanvas.Destroy;

begin

CanvasList .Remove (Self) ; {удаляет из списка ссылки на объекты}

inherited Destroy; end;

function TCanvas.GetPixel (X, Y: Integer): TColor;

begin

RequiredState([csHandleValid]);

GetPixel := Windows.GetPixel(FHandle, X, Y) ; end;

procedure TCanvas.SetPixel(X, Y: Integer; Value: TColor);

begin

Changing;

RequiredState([csHandleValid, csPenValid]);

Windows.SetPixel(FHandle, X, Y, ColorToRGB(Value));

Changed;

end;

Доступ к такому свойству-массиву осуществляется следую­щим образом:

Canvas.Pixels [10, 20] :=clRed; что означает:

Canvas.SetPixel (10, 20, clRed);

За описанием свойства-массива может следовать директива default. В данном случае это будет означать, что это свойство становится свойством по умолчанию для данного класса. На­пример:

type

TStringArray = class public property Strings[Index: Integer]: string . . . ; default;

end;

Если у класса есть свойство по умолчанию, то доступ к это­му свойству может быть осуществлен оператором

<имя компонента>[Index], который эквивалентен оператору

<имя компонента>.<имя свойства>[Index].

Класс может иметь только одно свойство по умолчанию. В связи с тем, что компилятор статически определяет свойство по умолчанию у объекта, то смена свойства по умолчанию или его скрытие в наследниках класса может привести к непредсказуе­мым последствиям.