Группа взаимоисключающих пунктов выбора (отмеченным может быть только один из группы). По виду отличаются от tCheckBox тем, что рисуются кружками. При выборе одного элемента группы в центре кружка рисуется точка, а предыдущий перестает быть отмеченным. Чтобы создать независимые группы радиокнопок, надо помещать соответствующую часть из них на другие группирующие элементы — tGroupBox или tPannel.
5.9.11. Таблица (сетка) строк (tStringGrid).
Обеспечивает вывод таблицы с текстом. Таблица состоит из ячеек (Cells). Доступ к ячейке идет через двумерное свойство Cells[i, j]. Количество столбцов в таблице задается свойством ColCount, а строк (рядов) — RowCount. Ширину и высоту ячеек в любом столбце или строке, соответственно, можно независимо задавать с помощью свойств DefaultColWidth и DefaultRowHeight.
Часть столбцов и строк в таблице могут быть "фиксированными". Число фиксированных строк задается свойством FixedRows, столбцов — свойством FixedCols. Фиксированные ячейки выполняют в таблице особую роль.
· Во-первых, они являются заголовками столбцов и строк. Они имеют другой цвет фона (по умолчанию серый, а не белый, как обычные ячейки), не захватывают фокус (хотя такие столбец или строка как единое целое могут его захватить при заданных соответствующих опциях) и не допускают редактирования находящегося в них текста, даже если свойство doEditing для компонента установлено как true во множестве свойств Options.
· Во-вторых, при установке в true свойства goRowsMoving и/или goColsMoving (также множество свойств Options) можно менять порядок строк и/или столбцов, "хватаясь" за них "мышью".
Приведем пример процедуры инициализации таблицы StringGrid, считая, что все необходимые атрибуты установлены на этапе визуального проектирования:
procedure SG_Init;
var i, j:Integer;
begin
StringGrid1.Cells[0,0]:='N'; {заголовок первого столбца - буква N}
for j:=1 to ColCount-1 do {заголовок других столбцов}
StringGrid1.Cells[0,j]:='Заголовок'+IntToStr(j);
for i:=1 to RowCount-1 do {первый столбец - номер строки}
StringGrid1.Cells[i,0]:=IntToStr(i);
end;
Эту процедуру можно вызвать, например, по событию onCreate для StringGrid1 (либо просто перенести приведенный текст внутрь обработчика события). В отличие от большинства других компонентов StringGrid, как правило, нуждается в программной инициализации подобного рода.
5.9.12. Диалоги (tOpenDialog, tSaveDialog è äðóãèå).
РАБОТА С ГРАФИКОЙ
Пример:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Image1: TImage;
Edit1: TEdit;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
close
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Image1.Canvas. Pen. Color:=clGreen;
Image1.Canvas. Lineto(StrToInt(Edit1.Text),StrToInt(Edit2.Text))
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Image1.Canvas. Pen. Color:=clRed;
Image1.Show;
end;
end.
6. Интерфейсы и множественное наследование
6.1. Общие представления об интерфейсах в Object PASCAL
Интерфейс объекта определяют методы и свойства, которые могут быть реализованы классом-наследником этого интерфейса. Они описываются аналогично абстрактным классам, так же, как абстрактные классы, но в отличие от них, не могут иметь экземпляров, не могут иметь реализации никаких своих методов (в Object PASCAL допускается реализация части методов в абстрактные классы). Реализация методов интерфейсов осуществляется в классе, поддерживающем (наследующем) данный интерфейс. Переменная типа интерфейс - это ссылка. Она дает возможность ссылаться на объект, чей класс реализует данный интерфейс. Однако с помощью такой переменной разрешается вызывать только методы, декларированные в данном интерфейсе, а не любые методы данного объекта. Интерфейсы являются альтернативой множественному наследованию, имеют практически все его достоинства и лишены его недостатков. Их использование существенно для написания ПО для распределенных систем на основе COM (the Component Object Model) и CORBA (Common Object Request Broker Architecture). Объекты, поддерживающие интерфейсы, могут взаимодействовать с COM - объектами, написанными на C++ или Java.
Интерфейсы, как и классы, могут быть описаны только в самой наружной области видимости программы или модуля, но не в процедуре или функции. Описание типа для интерфейса имеет вид:
type
interfaceName =
interface (ancestorInterface)
['{GUID}']
список полей
end;
Отличия от классов:
· Не бывает экземпляров, реализующих тип интерфейс.
· Список полей интерфейса может включать только свойства и методы. Поля данных использовать нельзя. Соответственно, спецификаторы read и write должны быть методами.
· Все поля интерфейса всегда имеют тип видимости public (без явного указания); не разрешено использовать спецификаторов видимости (но у массивов может быть использован спецификатор default).
· Не бывает конструкторов и деструкторов.
· Методы не могут быть специфицированы как виртуальные, динамические, перекрытые, абстрактные. Поскольку они не имеют реализации в экземплярах типа, эти различия не имеют значения.
· Наследование через интерфейсы множественное.
· Реализация интерфейса может быть только в классе, при этом он должен реализовать все методы интерфейса (а значит, и все свойства)
Интерфейс, как и класс, наследует все методы прародителя, однако только на уровне абстракций, без реализации методов. Однако интерфейс наследует право реализации этих методов в классе, поддерживающем этот интерфейс. В декларации интерфейса можно указать, что интерфейс наследуется от прародительского интерфейса. Если такого указания нет, то интерфейс является непосредственным потомком IUnknown, который определен в модуле System и является прародителем для всех интерфейсов. В IUnknown продекларировано 3 метода — QueryInterface, _AddRef, Release. QueryInterface предназначен для поддержки интерфейсов объектов. _AddRef, _Release обеспечивают управление ссылками на интерфейсы. Простейший путь реализовать эти методы — создать класс-наследник от tInterfacedObject, описанного в модуле System.
Пример описания интерфейса:
type
IMalloc =
interface(IUnknown)
['{00000002-0000-0000-C000-000000000046}']
function Alloc(Size: Integer): Pointer; stdcall;
functionRealloc(P:Pointer;Size:Integer):Pointer;stdcall;
procedure Free(P: Pointer); stdcall;
function GetSize(P: Pointer): Integer; stdcall;
function DidAlloc(P: Pointer): Integer; stdcall;
procedure HeapMinimize; stdcall;
end;
Перед использованием продекларированного интерфейса он должен быть реализован в классе. Реализация осуществляется с помощью декларации в списке прародителей класса:
type
className =
class (ancestorClass, interface1,...,interfaceN)
memberList
end;
Например,
type
TMemoryManager =
class(TInterfacedObject, IMalloc, IErrorInfo)
...
end;
Когда класс реализует интерфейс, он должен реализовать (или наследовать реализацию) каждого метода, декларированного в интерфейсе. Ниже приведено описание tInterfacedObject из модуля System:
type
TInterfacedObject =
class(TObject, IUnknown)
protected
FRefCount: Integer;
function QueryInterface(const IID: TGUID; out Obj): Integer; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
property RefCount: Integer read FRefCount;
end;
tInterfacedObject реализует интерфейс. Поэтому в нем описаны и реализованы все три метода IUnknown. Классы, реализующие интерфейсы, могут быть использованы как прародители. Класс tInterfacedObject реализует три метода интерфейса IUnknown и поэтому удобен как прародитель для всех классов, реализующих интерфейсы. Когда интерфейс реализован в классе, каждый из его методов реализован соответствующим методом (по умолчанию с тем же именем) и с такой же сигнатурой.
В классе-наследнике можно перекрыть методы реализуемого интерфейса. При этом соответствующий метод должен быть виртуальным или динамическим). Также возможно заново унаследовать интерфейс:
type
IWindow =
interface
['{00000115-0000-0000-C000-000000000146}']
procedure Draw;
...
end;
TWindow =
class(TInterfacedObject, IWindow) //TWindow реализует IWindow
procedure Draw;
...
end;
TFrameWindow =
class(TWindow, IWindow) //TFrameWindow переопределяет реализацию Iwindow
procedure Draw;
...
end;
При этом в классе все методы от прародительской реализации этого интерфейса запираются (не наследуются), в том числе выражения различения методов.
6.2. Реализация интерфейсов свойством
Директива implements в описании свойства класса позволяет делегировать реализацию интерфейса свойству в реализуемом классе. Например, свойство
property MyInterface: IMyInterface
read FMyInterface
implements IMyInterface;
описывает свойство, реализующее интерфейс ImyInterface. Директива implements должна быть последней в описании свойства и может иметь перечисление после нее имен нескольких интерфейсов, разделенных запятыми. Делегируемое свойство:
· может иметь тип класса или интерфейса.
· не может быть массивом или иметь спецификатор индекса.
· должно иметь спецификатор read; если имеется метод “read”, он не может быть динамическим (хотя может быть виртуальным) или описывать директиву message.
· Если свойство типа интерфейс, соответствующий интерфейс или его интерфейс-прародитель должен присутствовать в списке интерфейсов класса, где продекларировано свойство.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |


