TBevel
TObject-TPersistent-TComponent-TControl-TGraphicControl->TBevel
Модуль EXTCTRLS
Страница Палитры компонентов: Additional
Этот элемент управления предназначен для выделения и разграничения областей на форме. Может иметь вид прямоугольника или линии. Геометрическая форма компонента
(Pb) property Shape: TBevelShape;
может быть одной из принадлежащих множеству:
TBevelShape = (bsBox, bsFrame, bsTopLine, bsBottomLine, bsLeftLine, bsRightLine) ;
Стиль элемента — утопленный (bsLowered) или приподнятый (bsRaised) — определяется свойством:
(Pb) property Style: TBevelStyle;
TBevelStyle = (bsLowered, bsRaised)
Этот компонент предназначен только для оформления — с ним не связаны никакие события.
TBitBtn
TObject—TPersistent—>TComponent->TControl—>TWinControl—>TButtonControl->TButton->TBitBtn
Модуль BUTTONS
Страница Палитры компонентов: Additional
Эта кнопка, будучи потомком TButton, может нести на себе пиктограмму и имеет рад дополнительных удобств в использовании. В Delphi уже определены стандартные виды кнопок:
(Pb) property Kind: TBitBtnKind;
TBitBtnKind = (bkCustom, bkOK, bkCancel, bkHelp, bkYes, bkNo, bkClose, bkAbort, bkRetry, bklgnore, bkAll) ;
Для каждой из них определены: передаваемый форме результат (ModalResult):
BitBtnModalResults: array[TBitBtnKind] of TModalResult =
( 0, mrOk, mrCancel, 0, mrYes, mrNo, 0, mrAbort, mrRetry, mrlgnore, inrAll);
а также название и картинки для разных состояний. Достаточно установить значение свойства Kind, и кнопка сразу приобретет нужный вид. Более того, некоторые из видов кнопок при нажатии сразу совершают определенные действия. Так, bkHelp осуществляет инициализацию системы помощи со своим (или ближайшим ненулевым родительским) контекстом. Кнопка вида bkClose закрывает форму, которой она принадлежит, вызывая ее метод Close.
Кнопка будет отнесена к виду bkCustom, если она:
• назначена Default, но при этом не принадлежит множеству [bkOk, bkYes];
• назначена Cancel, но не принадлежит множеству [bkCancel, bkNo];
• у нее изменена пиктограмма;
• модальный результат не соответствует определенному для этого вида кнопок.
За внешний вид этой кнопки отвечают свойства, рассмотренные ниже. Стиль изображения кнопок в зависимости от операционной системы задается свойством:
(Pi-) property Style: TButtonStyle;
TButtonStyle = (bsAutoDetect, bsWin31, bsNew);
Стиль bsNew соответствует Windows 95. В любом случае корректным будет применение стиля bsAutoDetect, который сам распознает версию системы. Пиктограмма кнопки, которая вместе с текстом видна на ее поверхности, определяется свойством:
(Pb) property Glyph: TBitmap;
Для создания эффекта нажатия картинка должна немного изменяться в зависимости от состояния; кроме того, отдельная картинка нужна для неактивного состояния (когда нажатие не воспринимается). В свойстве Glyph должна быть одна битовая карта, но она может содержать картинки сразу для нескольких состояний кнопки (максимум четыре). Они интерпретируются как соответствующие нормальному (отжатому), запрещенному (неактивному), нажатому и утопленному состояниям (последнее применяется только для кнопок TSpeedButton). Для этого картинки должны быть расположены подряд
вплотную по горизонтали. Например, при размере картинок 16х16 нужна объединенная битовая карта 64х16. Если каждая из картинок квадратная и ширина общей картинки нацело делится на высоту, то при присвоении ее свойству Glyph система сможет распознать их и скорректировать количество, определяемое свойством:
(pb) property NumGlyphs: TNumGlyphs ;
TNumGlyphs = 1..4;
При отрисовке в зависимости от состояния из большой битовой карты будет использована нужная часть.
Три свойства отвечают за расположение текста и картинки на поверхности кнопки:
(Pb) property Layout: TButtonLayout;
Способ выравнивания пиктограммы относительно краев кнопки. Может быть одним из четырех:
TButtonLayout = (biGlyphLeft, biGlyphRight, biGlyphTop, biGlyphBottom) ;
Расстояние от соответствующего способу выравнивания края кнопки до пиктограммы описывается свойством:
(Pb) property Margin: Integer;
Промежуток между пиктограммой и текстом равен:
(Pb) property Spacing: Integer;
Если свойства Margin, Spacing или оба не заданы (по умолчанию равны -1), значения этих промежутков выбираются системой. Кнопка также имеет метод Click и свойства Caption, ModalResult, Default и Cancel. Статус Default получают кнопки видов bkOk, bkYes, a Cancel — кнопки видов bkCancel, bkNo.
TCheckBox
TObject->TPersistent—>TConiponent->TControl->TWinControl->TButtonControl->TCustoniCheckBox->TCheckBox
Модуль STDCTRLS
Страница Палитры компонентов: Standard
Кнопка с независимой фиксацией, или флажок. Является стандартным элементом управления Windows.
Состояние кнопки отражает свойство:
(Pb) property State: TCheckBoxState;
Оно может принимать одно из трех значений:
TCheckBoxState = (cbUnchecked, cbchecked, cbGrayed) ;
Способ перехода из состояния в состояние при нажатии устанавливается свойством:
(Pb) property AllowGrayed: Boolean;
Если оно равно False, кнопка имеет два состояния и при каждом нажатии переходит из cbUnchecked в cbChecked и обратно. Если AllowGrayed = True, кнопка имеет три состояния и при нажатиях движется по циклу cbGrayed — cbChecked — cbUnchecked.
Показывает, отмечена mi кнопка (т. е. State = cbChecked), свойство:
(Pb) property Checked: Boolean;
Оно доступно для записи — с его помощью можно и отмечать кнопки. Значение False соответствует cbUnchecked.
Выравнивание текста (только по правому или левому краю) задается при помощи свойства:
(Pb) property Alignment: TLeftRight;
TLeftRight = taLeftJustify..taRightJustify;
Кнопка также имеет свойство Caption. Двойной щелчок на кнопке не предусмотрен.
TRadioButton
TObject—>TPersistent—>TComponent->TControl—>TWinControl—>TButConControl->TRadioButton
Модуль STDCTRLS
Страница Палитры компонентов: Standard
Радиокнопка (переключатель), или кнопка с зависимой фиксацией — также стандартный элемент управления Windows. Особенностью радиокнопок является механизм их переключения. Они группируются автоматически, то есть при выборе одной из них все остальные, принадлежащие тому же элементу управления или форме, освобождаются. Для того чтобы в форме можно было использовать несколько независимых групп радиокнопок, используйте специальные компоненты.
Свойство
(Pb) property Checked: Boolean;
определяет, нажата ли данная радиокнопка. При изменении этого свойства генерируется событие OnClick.
У радиокнопки имеется свойство Caption, содержащее связанньш с ней текст. Выравнивание текста радиокнопки определяется свойством
(Pb) property Alignment: TLeftRight;
и может проводиться только по левому или по правому краю. У этого компонента предусмотрено также событие:
(Pb) property OnDblClick;
Такое событие посылается только уже нажатой радиокнопке, в то время как OnClick — только ненажатой.
TColorDialog
TObject->TPersistent—>TCoinponent-^TCommonDialog->TColorDialog
Модуль DIALOGS
Страница Палитры компонентов Dialogs
Предназначен для определения цвета пользователем. Настройка диалога осуществляется через свойство:
(Pb) property Options: TColorDialogOptions;
TColorDialogOption = (cdFullOpen, cdPreventFullOpen, cdShowHelp);
TColorDialogOptions = set of TColorDialogOption;
Данные опции определяют:
cdFullOpen — полный показ диалога. В этом случае пользователь может выбрать не только один из цветов системной палитры, но и задать собственный;
cdPreventFullOpen — запрещение полного показа диалога;
cdShowHelp — показ кнопки Help.
В диалоге пользователь может определить несколько (до 16) собственных цветов, которые доступны в свойстве:
(Рb) property CustomColors: TStrings;
Каждый из этих цветов представлен в свойстве CustomColors строкой вида
ColorA = SOffaO
где ColorA — условное название цвета (могут быть определены цвета с названиями от ColorA до ColorP), а справа от знака равенства стоит его шестнадцатиричное значение в формате RGB.
В случае нажатия кнопки ОК возвращаемое значение цвета содержится в свойстве:
(РЬ) property Color: TColor;
TComboBox
TObject—>TPersistent->TComponent—>TControl—>TWinControl—>TCustomCornboBox—>TComboBox
Модуль STDCTRLS
Страница Палитры компонентов Standard
Этот стандартный элемент управления Windows — комбинированный список - имеет много общего с TListBox. Он состоит из собственно списка и помещенного рядом поля ввода редактирующего элемента. Таким образом, пользователь может выбрать одно из готовых значений какой-то величины или ввести свое. Стиль компонента в части правил взаимного сочетания списка и редактора определяется свойством:
(Рb) property Style: TComboBoxStyle;
TComboBoxStyle = (csDropDown, csSimple, csDropDownList,
csOwnerDrawPixed, csOv'nerDrawVariable) ;
Его значения имеют следующий смысл:
csSimple — весь список виден все время. Текущий выбор отображается в редакторе, его можно изменить;
csDropDown — список открывается (выпадает) и скрывается при нажатии кнопки, расположенной справа от текста. Такой список будем называть вьша дающим;
csDropDownList — список вьшадающий, но редактирующий элемент заменен статическим текстом и вводить свои данные пользователь не может;
csOwnerDrawFixed — определяемьш пользователем стиль списка с постоянной высотой элемента;
csOwnerDrawVariable — определяемьш пользователем стиль списка с переменной высотой элемента.
Принципы пользовательской отрисовки списка для csOwnerDrawFixed и csOwnerDrawVariable, а также связанные с этим методы и события остались такими же, как в TListBox. По умолчанию устанавливается сталь csDropDown.
Организация списка также сходна с предыдущей. Приведенные свойства и методы имеют то же назначение:
(Pb) property Items: TStrings;
property Itemlndex: Integer;
procedure Clear;
(Pb) property Sorted: Boolean;
(RS) property Canvas: TCanvas;
Текст, содержащийся в редактирующем элементе списка, доступен через свойство:
(рs) property Text: TCaption;
Его максимальная длина ограничена числом символов, равным значению свойства:
property MaxLength: Integer;
Если MaxLength равно 0, то ограничений на длину строки нет (до 255 символов).
При изменеюш текста (а также при смене выбранного элемента) возникает событие OnChange.
Часть текста может быть выделена. Три свойства содержат выделенный текст, его положение и длину:
property SelText: strings-property SelStart: Integers-property SelLength: Integer;
Метод
procedure SelectAll;
выделяет весь текст. Значение свойства
property DroppedDown: Boolean;
соответствует состоянию списка: True соответствует открытому ("выпавшему") списку. С его помощью можно показывать или скрывать список из программы. При изменении состояния списка возникает событие:
property OnDropDown: TNotifyEvent ;
Максимальное число элементов, которые показываются при выпадении списка:
(Pb) property DropDownCount: integer;
По умолчанию оно равно 8. В первой версии VCL это свойство описано, но не реализовано (не играет роли).
TDrawGrid
TObject->TPersistent->TComponent->TControl—>TWinControl—>TCusto:mControl—>TCustomGrid—>TDrawGrid
Модуль GRIDS
Страница Палитры компонентов Additional
Использование этого компонента дает универсальный способ организовать представление информации в виде таблицы. TDrawGrid берет на себя разбивку области на прямоугольные ячейки, добавление и удаление строк и столбцов, прокрутку, управление вводом данных и обработку всех поступающих сообщений. Единственное, что должен сделать программист — это нарисовать или написать то, что ему нужно, в каждой ячейке.
Таблица делится на две области — фиксированную и подвижную. Фиксированную область обычно составляют часть строк и столбцов в верхней части таблицы. Такие ячейки необходимы, например, для вертикальных и горизонтальных заголовков. Они выделяются другим цветом, всегда видимы и в прок-. рутке не участвуют, оставаясь на своих местах. Их нельзя сфокусировать и выделить. Кроме того, изменять ширину и высоту ячеек таблицы мышью во время исполнения можно только передвигая границы ячеек в фиксированной области. По умолчанию для этой области отведены один столбец и одна строка, но эти числа могут быть изменены. Все остальные ячейки перемещаются при прокрутке таблицы и составляют подвижную область.
Значение текста ячейки может редактироваться — для этого есть собственный встроенный редактор, являющийся потомком TMaskEdit.
Свойства TDrawGrid:
(pb) property ColCount: Longint; (Pb) property RowCount: Longint;
Содержат количество строк и столбцов в таблице. Обратите внимание, что координаты ячеек в таблице имеют тип Longint, т. е. в принципе число строк и(или) столбцов может превышать 65535.
property Col:Longint; property Row :Longint;
Содержат номера столбца и строки, содержащих сфокусированную ячейку.
property ColWidths[Index: Longint]: Integer; property RowHeights[Index: Longint]: Integer;
Свойства-массивы, содержащие ширину каждого столбца и высоту каждой строки. (Ширина и высота ячеек могут быть индивидуальными, см. свойство Options.)
property DefaultColWidth: Integer; property DefaultRowHeight: Integer;
Содержат ширину столбца и высоту строки, принимаемые по умолчанию. Они применяются при начальной инициализации таблицы и при добавлении в нее ячеек.
property GridHeight: Integer; (Ro) property GridWidth: Integer;
Содержат высоту и ширину всей таблицы. Эти свойства доступны только для чтения, так как являются производными от числа ячеек и их размеров.
(Pb) property ScrollBars: TScrollStyle; TScrollStyle = (ssNone, ssHorizontal, ssVerticai, ssBoth) ;
Задает полосу прокрутки. Если все ячейки не помещаются в область, отведенную компоненту, появляются полосы прокрутки в нужном направлении. По умолчанию предусмотрены обе полосы прокрутки.
property FixedCols: Integer; property FixedRows: Integer;
Содержат соответственно число строк и столбцов в фиксированной области.
(Pb) property FixedColor: TColor;
Содержит цвет, которым происходит закрашивание ячеек фиксированной области.
property TopRow: Longint; property LeftCol: Longint;
Содержат номера верхней строки и левого столбца, видимых в подвижной области. Первоначально это первая ячейка за фиксированной областью (TopRow = FixedRows, LeftCol = FixedCols), однако при прокрутке и других перемещениях сфокусированной ячейки эти значения могут изменяться. Свойства доступны только во время исполнения.
(Pb) property OnTopLeftChanged: TNotifyEvent;
Событие вызывается, когда изменяются TopRow или LeftCol.
property VisibleColCount: Integer; property VisibleRowCount: Integer;
Содержат соответственно число полностью видимых столбцов и строк в подвижной области. Могут быть не полностью видны еще один столбец и одна строка.
Рассматриваемый компонент имеет множество вариантов настройки под конкретное применение. Изменить его функционирование вы можете, настроив соответствующим образом опции:
(Pb) property Options: TGridOptions;
TGridOption = (goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goDrawFocusSelected, goRowSizing, goColSizing, goRowMoving, goColMoving, goEditing, goTabs, goRowSelect, goAlwaysShowEditor, goThumbTracking) ;
TGridOptions = set of TGridOption;
В множестве допускаются сочетания следующих опций:
goFixedVertLine — ячейки в фиксированной области разделяются вертикальными линиями;
goFixedHorzLine — ячейки в фиксированной области разделяются горизонтальными линиями;
goVertLine — ячейки разделяются вертикальными линиями;
goHorzLine — ячейки разделяются горизонтальными линиями;
goRangeSelect — может быть выделено множество ячеек;
goDrawFocusSelected — при наличии опции ячейка, имеющая фокус, рисуется тем же цветом, что и выделенная. В противном случае — имеет цвет обычных ячеек (но выделяется, как всегда, рамкой из отдельных точек);
goRowSizing — высота строк может изменяться индивидуально;
goColSizing — ширина столбцов может изменяться индивидуально;
goRowMoving — строки могут быть перемещены мышью;
goColMoving — столбцы могут быть перемещены мышью;
goEditing — ячейки таблицы могут редактироваться;
goAlwaysShowEditor — содержимое активной (сфокусированной) ячейки всегда загружается в редактор (в противном случае требуется нажатие или щелчок мышью);
goTabs — переход между столбцами возможен при помощи табуляции (<ТаЬ> или +
goRowSelect — если эта опция присутствует, в таблице нельзя выделить единственную ячейку (кроме левой нижней из видимых). Выделяется всегда текущий столбец или область ячеек от левой нижней до текущей;
goThumbTracking — задает поведение ячейки при передвижении мышью бегунка полосы прокрутки. Если эта опция отсутствует, содержимое ячеек не обновляется, пока пользователь не отпустит кнопку мыши; иначе — перерисовка происходит при каждом изменении.
Толщина линий, разделяющих ячейки таблицы, задается свойством:
(Pb) property GridLineWidth: Integer;
Линии в вертикальном и горизонтальном направлениях рисуются в случае наличия опций [goFixedVertLine, goVertLine] и [goFixedHorzLine, goHorzLine] соответственно.
Метод
function CellRect(ACol, ARow: Longint): TRect;
возвращает прямоугольник, соответствующий ячейке с индексами ACol, ARow в системе координат клиентской области таблицы. Метод MouseToCell превращает координаты точки нажатия кнопки мыши в индексы строки и столбца, где оно произошло:
procedure MouseToCell (X, Y: Integer; var ACol, ARow: Longint);
Вообще говоря, мышь ни при чем и преобразуются любые координаты, заданные относительно начала клиентской области.
В сфокусированной ячейке редактор ячеек таблицы можно вызвать вводом любого символа ASCII или . Указывает, активен ли редактор, свойство:
property EditorMode: boolean;
Оно не имеет смысла, если редактор активен постоянно (установлена опция goAlwaysShowEditor).
Если установлен режим goTabs, то между столбцами таблицы можно передвигаться, нажимая <ТаЬ> или +. По умолчанию фокус будет останавливаться на всех столбцах. Чтобы исключить остановку на некоторых столбцах, нужно присвоить значение False элементу массива TabStops с нужным индексом:
(Pb) property TabStops[Index: Longint]: Boolean;
He путайте это свойство с TabStop, которое касается всего компонента. Событие, возникающее при смене сфокусированной ячейки:
(Pb) property OnSelectCell: TSelectCellEvent;
TSelectCellEvent = procedure (Sender: TObject; Col, Row:
Longint; var CanSelect: Boolean) of object;
Фокус должен переместиться в ячейку (Col, Row). Изменяя значение параметра CanSelect, можно запретить перемещение фокуса в некоторые ячейки.
Прямоугольник, соответствующий диапазону выделенных ячеек, содержится в свойстве:
property Selection: TGridRect;
TGridRect = record
case Integer of
0: (Left, 'I'op, Right, Bottom: Longint);
1: (TopLeft, BottomRight: TGridCoord);
end;
TGridCoord = record
X: Longint;
Y: Longint;
end;
Стиль обрамления всей таблицы задается:
(Pb) property BorderStyle: TBorderStyle;
При bsSingle компонент окаймляется черной линией.
Перейдем к тому, как помещать и отображать информацию в ячейки TDrawGrid.
Если вы вводите текст, то он виден в редакторе, возникшем в текущей ячейке. Но как только ввод завершен, текст исчезает. Почему? TDrawGrid возлагает на программиста обязанность нарисовать содержимое каждой ячейки. Если свойство
(Pb) property DefaultDrawing: Boolean;
установлено 6 True, для всех состояний ячеек предусматривается отрисовка по умолчанию, а именно заливка ячейки определенным для данного состояния цветом. Только установив его в False, программист получает доступ к обра
ботке событий OnDrawCell и может изобразить каждую ячейку таблицы так, как ему требуется. Для этого таблица имеет свою канву:
property Canvas: TCanvas ;
Обработчик события OnDrawCell должен иметь тип:
(Pb) property OnDrawCell: TDrawCellEvent;
TDrawCellEvent = procedure (Sender: TObject; Col, Row: Longint;
Rect: TRect; State: TGridDrawState) of object;
Параметры:
Col, Row — координаты (номера столбца и строки) ячейки;
Rect — отведенный ей прямоугольник;
State — состояние ячейки. Описывается флагами из множества:
TGridDrawState = set of (gdSelected, gdFocused, gdFixed) ;
Флаги соответствуют выбранной, сфокусированной ячейкам и ячейке из фиксированной области. Приведенный ниже фрагмент кода закрашивает ячейки таблицы разным цветом в зависимости от значений во внешнем массиве Field:
procedure TForm1.DrawGridlDrawCell(Sender: TObject;
Col, Row: Longint;
Rect: TRect; State: TGridDrawState);
begin
with DrawGridI.Canvas do begin if Field[Col,Row] then
Brush.Color := clAqua else
Brush.Color := clBackground;
FillRect(Rect) ,-end;
end ;
При установленных опциях goColMoving/goRowMoving можно захватить мьппью ячейку заголовка (в фиксированной области) и перенести всю строку или столбец на другое место. В этом случае после нажатия левой кнопки мыши появляется вертикальная или горизонтальная линия, показывающая, куда будет вставлена перемещаемая информация: при движении к началу таблицы — за линией, к концу — перед ней. При этом корректируются размеры выделенной области. Строки и столбцы заголовков, полностью лежащие в фиксированной области, переносить нельзя.
По окончании переноса происходят события, которые информируют о перемещении столбца или строки из положения Fromlndex в положение Tolndex:
(pb) property OnColumnMoved: TMovedEvent ;
(Pb) property OnRowMoved: TMovedEvent;
TMovedEvent = procedure (Sender: TObject; Fromlndex,
Tolndex: Longint) of object;
В редактируемой таблице (при установленном goEditing) есть возможность реагировать на связанные с изменением текста события. В начале (при вызове редактора) можно задать маску для редактирования ячейки, вернув ее в
параметре Value обработчика события OnGetEditMask. Напомним, что редактор ячейки таблицы является потомком TMaskEdit:
(Pb) property OnGetEditMask: TGetEdiCEvent;
TGetEditEvent = procedure (Sender: TObject; ACol, ARow:
Longint; var Value: string) of object;
Далее редактор извлекает текст, связанный с ячейкой. При этом вызывается событие:
(Pb) property OnGetEditText: TGetEditEvent;
Загружаемый текст доступен в параметре Value, и его можно изменить до появления в редакторе.
При каждом изменении текста в редакторе инициируется событие:
(Pb) property OnSetEditText: TSetEditEvent;
TSetEditEvent = procedure (Sender: TObject'; ACol, ARow: Longint;
const Value: string) of object;
Иллюстрирует применение TDrawGrid пример LIFE. Это классическая игра "жизнь" (автор — X. Конвей), имитирующая законы выживания. Каждая ячейка таблицы здесь соответствует одному "существу". Его состояние изменяется через некоторые интервалы времени (для этого используется компонент TTimer). Существо "живет" нормально, если у него двое или трое соседей. Если их меньше, оно умирает от одиночества, если больше — от перенаселения. Новая жизнь появляется в пустой ячейке, если у нее ровно трое соседей. Начальное состояние ячеек может быть случайным, а может быть задано вами:
щелчок по ячейке означает изменение ее состояния. Запустив игру, вы увидите, как постепенно положение на игровом поле стабилизируется, и на нем образуется несколько разновидностей устойчивых конфигураций групп ячеек.
TStringGrid
TObject->TPersistent—>TComponent->TControl->TWinControl->TCustomControl->TCustomGrid-TDrawGrid->TStringGrid
Модуль GRIDS
Страница Палитры компонентов Additional
Этот компонент реализует возможности своего предка TDrawGrid применительно к таблице строк.
В состав компонента добавлен объект класса TStrings, в котором хранится содержимое ячеек. Он доступен как векторное свойство — двумерный массив текстовых строк (размерностью ColCount x RowCount), соответствующих ячейкам таблицы:
property Cells[ACol, ARow: Integer]: string;
Доступен и двумерньш массив объектов, соответствующих ячейкам:
property Objects[ACol, ARow: Integer]: TObject;
Необходимо помнить, что самих объектов в таблице нет, и программист должен создавать, а по окончании использования таблицы удалять объекты самостоятельно.
Можно работать отдельно как со строками, так и со столбцами таблицы. Свойства
property Cols[Index: Integer]: TStrings;
property Rows[Index: Integer]: TStrings;
описывают наборы строк (также в виде TStrings), содержащие текст и объекты столбцов и строк таблицы.
При значении True свойства DefaultDrawing для этого компонента происходит вывод строки в соответствующей ячейке. Так что если кроме текста ничего отображать не требуется, то менять значение DefaultDrawing и определять обработчик события OnDrawCell не нужно.
Отметим, что перенос строк и столбцов таблицы (при установленных опциях goColMoving или goRowMoving) осуществляется вместе с их текстовыми строками.
TOutline
TObject->TPersistent—>TCoinponent—>TControl—>TWinControl->TCustomControl->TCustomGrid->TCustomOutline->TOutline
Модуль OUTLINE
Страница Палитры компонентов Additional
TOutline создан для ведения и отображения иерархических структур данных — деревьев. Это один из наиболее сложных и интересных компонентов. В этот раздел он попал потому, что является потомком таблицы (TCustomGrid), хотя и мало чем ее напоминает.
Типичным примером применения TOutline можно назвать отображение структуры файловой системы (для этого даже есть отдельный компонент TDirectory Outline). В описанном ниже примере OBJTREE этот компонент используется для отображения дерева классов библиотеки VCL.
Дерево состоит из элементов (будем называть их узлами), упорядоченных по уровням. Каждый из них имеет родительский узел (на более высоком уровне) и список дочерних узлов-потомков. Исключением являются корневой узел (нулевого уровня) — он не имеет предка, и узлы последнего уровня, не имеющие потомков.
Каждый узел является объектом класса TOutlineNode:
TOutlineNode = class(TPersistent)
Рассмотрим сначала методы и свойства этого объекта. С каждым узлом можно связать информацию — имя и произвольные данные:
property Text: string;
property Data: Pointer;
Указатель на родительский узел определяется свойством:
property Parent: TOutlineNode;
Если список дочерних узлов не пуст, что можно проверить при помощи свойства
property Hasltems: Boolean;
то для получения информации о них есть методы:
function GetFirstChild: Longint;
function GetLastChild: Longint;
function GetNextChild(Value: Longint): Longing-function GetPrevChiId(Value: Longint): Longint;
В последних двух методах параметр Value содержит индекс предыдущего найденного потомка. Индекс — это уникальный идентификатор узла в дереве, определенный свойством:
property Index: Longint;
Используя его, можно получить указатель на узел (см. ниже сам компонент TOutline). Узлы пронумерованы таким образом, что если родитель имеет номер N, то первый из его потомков — номер (N+1).
Можно узнать и полное имя (путь) узла, представляющее собой конкатенацию всех родительских имен и имени узла, разделенных специальным символом. Этот символ определен в свойстве ItemSeparator объекта TCustomOutline, которому принадлежат узлы. Полный путь определяется свойством:
property FullPath: string;
Каждый узел расположен на своем иерархическом уровне. На самом верху находится узел уровня 0. Все другие являются для пего дочерними; он не виден и не доступен пользователю. Поэтому на первом доступном уровне — с номером 1 — могут находиться по вашему желанию один или несколько узлов. Уровень иерархии узла можно узнать в его свойстве:
property Level: Cardinal;
Чтобы изменить уровень, надо вызвать метод:
procedure ChangeLevelBy(Value: TChangeRange);
которьш перемещает узел в список другого уровня. Диапазон перемещения TChangeRange ограничен:
TChangeRange = -1..1;
Чтобы переместить узел в дереве, нужно вызвать следующий метод
procedure MoveTo(Destination: Longint; AttachMode: TAttachMode);
TAttachMode = (oaAdd, oaAddChild, oalnsert) ;
Он перемещает узел (вместе со всеми потомками) в положение с индексом Destination. Родительский узел не может переместиться на место любого из своих потомков. Режим перемещения AttachMode означает:
oaAdd — добавить последним на том же уровне, что и Destination;
oaAddChild — добавить последним к потомкам узла Destination;
oalnsert — заменить в положении Destination прежний узел, которьш смещается дальше по списку на том же уровне.
Индекс того из предков узла, которьш находится в списке самого высокого уровня, известен из свойства:
property Topltem: Longint;
Для корневого узла это свойство равно 0.
Компонент TOutline не только хранит древовидную структуру, он еще и отображает ее. На экране каждый узел может находиться в двух состояниях, свер
нутом и развернутом. В свернутом состоянии потомки узла не видны, в развернутом они изображаются чуть ниже и правее друг под другом. Состояние узла может иллюстрироваться значком (плюс/минус, открытая/закрытая папка — см. описание свойства OutlineStyle компонента TOutline). Методы и свойства, управляющие состоянием узла на экране:
property Expanded: Boolean;
Указывает, в каком состоянии находится узел; True — развернутое состояние.
procedure Collapse;
Сворачивает узел, пряча все дочерние узлы.
procedure Expand;
Разворачивает узел списка, показывая дочерние узлы.
procedure FullExpand;
Полностью разворачивает узел, показывая все дочерние узлы всех подуровней.
Сворачивать/разворачивать узлы дерева, помимо щелчков мышью, можно нажатием клавиш:
<+> — соответствует Expand;
<-> — соответствует Collapse;
<*> — соответствует FullExpand. Свойство
property IsVisible: Boolean;
означает, может ли быть виден узел. Это возможно только в том случае, если виднь! все его родители. При отрисовке ширина узла сообщается методом:
function GetDisplayWidth: Integer;
Теперь перейдем от описания узла к описанию самого дерева — компонента TOutline. Он представляет собой совокупность узлов типа TOutlineNode. Всего в дереве содержится число узлов, равное значению свойства:
property ItemCount: Longint
;
К каждому из них можно обратиться, используя свойство:
property Items[Index: Longint]: TOutlineNode;
На текущий (выделенный) узел можно сослаться через свойство:
property Selectedltem: Longint;
Например, выполнение оператора
Items[Items[Selectedltem].Topltem].FullExpand;
приведет в развернутое состояние ту часть дерева, в которой находится выделенный узел (начиная от его самого далекого предка Topltem). Свойство
property Row: Longint;
показывает, какая строка дерева в данный момент имеет фокус. Зная "содержимое" узла, то есть его имя или данные, можно найти его в дереве и узнать индекс. Для этого нужно вызвать один из методов, возвращающих его:
function GetDataItem(Value: Pointer): Longint;
function GetTextItem(const Value: string): Longint;
Можно найти узел и по координатам точки в клиентской области компонента (на самом деле играет роль только координата Y) с помощью следующего метода:
function GetItemfX, Y: Integer): LongInC;
Целых три пары методов добавляют новый узел в дерево. Его имя инициализируется параметром Text. Различие между первым и вторым методами в парах в том, что второй позволяет связать с узлом данные (параметр Data), а в первом вместо них записывается nil.
function Add(Index: Longint; const Text: string): Longint;
function AddObject(Index: Longint; const Text: string;
const Data: Pointer): Longint;
— добавляют новый узел в качестве последнего в тот же список, где находится узел Index. Поскольку на самом верху иерархии может быть только один узел, то в случае задания Index = 0 он добавляется в список верхнего уровня. Соответствуют режиму oaAdd;
function AddChild(Index: Longint; const Text: string): Longint;
function AddChildObject(Index: Longint; const To" : string;
const Data: Pointer): Longint;
— добавляют новый узел в качестве последнего потомка узла Index. Соответствуют режиму oaAddChild;
function Insert(Index: Longint; const Text: string): Longint;
function InsertObject(Index: Longint; const Text: string;
const Data: Pointer): Longint;
— вставляют узел в положение Index. При этом прежний узел с таким индексом и все другие на этом уровне сдвигаются вниз. Единственное исключение — задание в качестве параметра нулевого индекса. В этом случае узел добавляется последним в список самого верхнего уровня. Соответствуют режиму oalnsert. Все методы вызывают переиндексирование дерева и возвращают уже новый индекс для вставленного узла. Если нужно удалить узел, то метод procedure Delete(Index: Longint);
удаляет узел с индексом Index, а метод
procedure Clear;
очищает все дерево.
Если нужно вставить или удалить сразу много узлов и при этом избежать трудоемких операций переиндексации и перерисовки дерева, то соответствующий код надо заключить между вызовами методов:
procedure BeginUpdate;
procedure EndUpdate;
Первый устанавливает специальное состояние обновления и на время запрещает все пересчеты и перерисовки, а второй сбрасывает его и обновляет дерево. Это состояние можно изменить и при помощи метода:
procedure SetUpdateSCate(Value: Boolean);
Дерево можно полностью свернуть или полностью развернуть вызовом методов:
procedure FullExpand;
procedure FullCollapse;
Каждый узел, изменяя свое состояние, предупреждает об этом родительское дерево. В зависимости от того, свернулся он или развернулся, вызываются обработчики событий
(pb) property OnExpand: EOutlineChange;
(РЬ) property OnCollapse: EOutlineChange;
EOutlineChange = procedure (Sender: TObject; Index: Longint) of object;
где параметр Index означает индекс узла, измешшшего состояние. Метод
function GetNodeDisplayWidth(Node: TOutlineNode): Integer;
возвращает ширину, занимаемую изображением узла (если установленньш стиль не osOwnerDraw, см. ниже).
Дерево может быть загружено и выгружено в поток и файл при помощи методов:
procedure LoadFromFile(const FileName: strings-procedure LoadFromStream(Stream: TStream);
procedure SaveToFile(const FileName: strings-procedure SaveToStream(Stream: TStream) ;
Для прокрутки информации TOutline по умолчанию имеет обе полосы, определяемые свойством:
(Pb) property ScrollBars: TScrollStyle;
TScrollStyle = (ssNone, ssHorizontal, ssVertical, ssBoth);
Строка (символ), разделяющий имена узлов при составлении полного имени узла, содержится в свойстве:
(Pb) property ItemSeparator: string;
На стадии разработки можно набрать строки, соответствующие будущим узлам дерева, в специальном редакторе. При этом узел попадет на уровень, соответствующий количеству пробелов или знаков табуляции перед его названием. Набранные строки текста содержит свойство:
(Pb) property Lines: TStrings;
Это свойство предназначено для использования именно на этапе разработки, так как свойство Items в это время недоступно. Во время исполнения с информацией об узлах нужно работать, используя свойство Items. При рисовании дерева, помимо собственно текста, вместе с ним может изображаться одна из пиктограмм:
property PicturePlus: TBitmap;
Соответствует свернутому узлу. По умолчанию — "плюс".
(Pb) property PictureMinus: TBitmap;
Соответствует развернутому узлу. По умолчанию — "минус".
(Pb) property PictureOpen: TBitmap;
Соответствует развернутому узлу. По умолчанию — "открытая папка".
(Pb) property PictureClosed: TBitmap;
Соответствует свернутому узлу. По умолчанию — "закрытая папка".
(Pb) property PictureLeaf: TBitmap;
Соответствует "листу" — узлу без потомков. По умолчанию — "документ".
Желательно, чтобы картинки имели "прозрачный" фон, то есть чтобы их свойство TransparentColor соответствовало цвету рабочей области компонента. Эти пиктограммы можно переопределить в случае необходимости.
Свойство OutlineStyle определяет, в частности, когда и какие пиктограммы будут показаны:
(Pb) property OutlineStyle: TOutlineStyle;
TOutlineStyle = (osText, osPlusMinusText, osPictureText, osPlusMinusPictureText, osTreeText, osTreePictureText);
В зависимости от значения этого свойства изображаются:
osText — только текст;
osPlusMinusText — текст и пиктограммы PicturePlus и PictureMinus в зависимости от состояния узла. "Лист" не имеет значка;
osPictureText — текст и пиктограммы PictureOpen, PictureClosed и PictureLeaf в зависимости от состояния узла;
osPlusMinusPictureText — объединяет в себе два предыдущих стиля;
osTreeText — текст и специальные линии, иллюстрирующие связь между родительским и дочерними узлами;
osTreePictureText — объединяет в себе стили osTreeText и osPictureText. По умолчанию установлен стиль osTreePictureText;
На внешний вид дерева влияют и опции, содержащиеся в свойстве:
(Pb) property Options: TOutlineOptions;
TOutlineOption =- (ooDrawTreeRoot, ooDrawFocusRect, ooSCretchBitmaps) ;
TOutlineOptions =- set of TOutlineOption;
Это множество может содержать элементы:
ooDrawTreeRoot — задает соединение линией всех узлов верхнего уровня. В случае отсутствия опции каждый из них выглядит как вершина отдельного дерева. Эта опция играет роль только для стилей osTreeText, osTreePictureText;
ooDrawFocusRect — задает выделение сфокусированного узла рамкой из точек;
ooStretchBitmaps — задает приведение размеров пиктограмм к размерам шрифта текста путем масштабирования. В противном случае либо из пиктограммы вырезается часть (если она больше), либо остается свободное место (если меньше).
Рисование дерева по умолчанию осуществляется системой, но может быть возложено и на программиста. Определяется это свойством:
property Style: TOutlineType;
TOutlineType = (otStandard, otOwnerDraw) ;
Стиль osStandard подразумевает, что дта каждого узла будет изображено то, что предусмотрено стилем OutlineStyle. Для реализации стиля otOwnerDraw нужно нарисовать содержимое узла в обработчике события:
(Pb) property OnDrawItern: TDrawItemEvent;
TDrawItemEvent = procedure(ListBox: TListBox; Index: Integer;
Rect: TRect; State: TOwnerDrawState) of object;
Параметры:
Index — индекс узла;
Rect — отведенный ему прямоугольник;
State — множество, в которое могут входить состояния odSelected, odFocused.
Высота каждого узла постоянна и в этом случае определяется свойством:
(Pb) property ItemHeight: Integer;
Для рисования у компонента есть своя канва:
property Canvas: TCanvas ;
Установить ее можно только для объекта стиля osOwnerDraw; при osStandard канва игнорируется.
Обрамление компонента задается свойством:
(Pb) property BorderStyle: TBorderStyle;
Разобраться с применением этого компонента поможет пример OBJTREE. В нем по заранее заданному массиву компонентов ClassesSet выстраивается иерархическое дерево, в которое добавляются и все объекты-предки. Для примера были выбраны только 32 компонента, при желании можно включить и все остальные. Не забывайте при этом добавить содержащие их модули к тем, что содержатся в операторе uses. Когда вы перемещаете фокус по дереву, отображается имя объекта и имя модуля, в котором он описан. Для этого используется информация, возвращаемая недокументированным (пока?) методом класса TObject.ClassInfo. Возвращаемая им структура описана в исходных текстах VCL
|