Методические указания для проведения практических и лабораторных занятий по дисциплине "Программирование на языке высокого уровня" для студентов специальностей 220200 Автоматизированные системы обработки информации и управления
Вид материала | Методические указания |
СодержаниеКомпонент TListBox Компонент TComboBox Компонент TStringGrid |
- Рабочая программа по дисциплине Программирование на языке высокого уровня для специальности, 182.97kb.
- Соболева Наталья Владимировна методические указания, 73.26kb.
- Методические указания к проведению лабораторных работ. Специальность 23. 01. 02 «Автоматизированные, 1178.37kb.
- Рабочая программа По дисциплине «Системы искусственного интеллекта» для специальности, 86.74kb.
- Рабочая программа По дисциплине «Программирование на языке высокого уровня» По специальности, 280.81kb.
- Р. Е. Алексеева кафедра ису программирование на языке высокого уровня методические, 57.65kb.
- Рабочая программа по дисциплине «Алгоритмические языки и программирование» Для специальности, 208.45kb.
- Рабочая программа дисциплины «Объектно-ориентированное программирование» для специальности, 325.53kb.
- А. В. Яковлев Операционные системы и системное программирование Раздел Операционная, 1847.03kb.
- Рабочая программа дисциплины «Автоматизированные информационные системы» для специальности, 301.29kb.
Компонент TListBox
TObject—>TPer si stent—”TComponent—>TControl—>TWinControl—>
—>TCustomListBox—>TListBox
Модуль STDCTRLS
Страница Палитры компонентов Standard
Этот компонент соответствует списку выбора — стандартному элементу управления Windows. С его помощью пользователь может выбрать одну из строк, которые хранятся в свойстве:
(Pb) property Items: TStrings;
В списке Items. Strings хранится текст строк, а список Items.Objects пользователь может использовать для хранения связанных с ними объектов, например, картинок для нестандартно изображаемого списка.
Индекс текущего (сфокусированного) элемента списка содержится в свойстве:
property Itemlndex: Integer;
Не путайте сфокусированный элемент (стандартно он помещается в рамку из точек) и выделенный (цветным фоном), они могут не совпадать. Смысл этих понятий будет объяснен ниже. Значение индекса Itemlndex лежит в диапазоне от 0 до Items.Count-1. Он доступен для чтения и записи.
Индекс первого видимого элемента в списке представлен свойством:
property Toplndex: Integer;
Он будет ненулевым в том случае, когда все элементы не помещаются в окне списка, и была сделана прокрутка.
Список выбора имеет свою канву:
(Ro) property Canvas: TCanvas;
и на его поверхности можно рисовать.
Когда в списке нужно предусмотреть выделение одновременно более одного элемента, оперируйте свойствами:
(Pb) property MultiSelect: Boolean;
(Pb) property ExtendedSelect: Boolean;
Если MultiSelect установлено в False, то в списке одновременно не может быть выделено несколько элементов и значение ExtendedSelect не играет роли. В противном случае дело обстоит так. При ExtendedSelect = False каждый раз изменяется состояние только сфокусированного элемента. Каждый щелчок мышью или нажатие пробела меняет его состояние выделения на противоположное. Если ExtendedSelect = True, то выбор происходит при передвижении мыши с нажатой левой кнопкой, каждом щелчке мышью на новом элементе списка при нажатых
Количество выделенных элементов можно узнать из свойства:
(Ro) property SelCount: Integer;
Проверку и установку выделения для каждого элемента можно провести, используя свойство:
property Selected[Index: Integer]: Boolean;
При задании ошибочного индекса при доступе к списку возникает исключительная ситуация EList Error.
Чтобы расположить строки в алфавитном порядке, нужно установить в True свойство:
(Pb) property Sorted: Boolean;
Элементы списка могут появляться как в одном столбце — Друг под другом, так и в нескольких соседних. В этом случае список может иметь горизонтальную полосу прокрутки. Число столбцов определяется свойством:
(Pb) property Columns: Integer;
Если столбец один, то значение этого свойства равно 0. Очистить список можно при помощи метода:
procedure Clear;
Стиль обрамления компонента определяется свойством:
(Pb) property BorderStyle: TBorderStyle;
Найти индекс элемента, которьш содержит точку Pos, можно при помощи метода:
function ItemAtPos(Pos: TPoint; Existing: Boolean): Integer;
Параметр Existing определяет, что возвращается в случае неудачи (значение Items.Count либо -1).
Прямоугольник, отведенньш элементу списка с индексом Index, определяется с помощью метода:
function ItemRect(Index: Integer): TRect;
При создании и визуализации списка система обычно подгоняет его высоту таким образом, чтобы в видимое поле помещалось целое число элементов. Это соответствует значению True свойства:
(Pb) property IntegralHeight: Boolean;
Если IntegralHeight равно False, то высота списка не изменяется. Это свойство не играет роли при стиле списка IbOwnerDrawVariable.
Стиль списка может быть стандартным или определенным пользователем через свойство:
(Pi-y property Style;
TListBoxStyle = (IbStandard, IbOwnerDrawFixed,
IbOwnerDrawVariable) ;
Рассмотрим назначение этого свойства более подробно.
В стандартном варианте (IbStandard) в списке отображаются только строки из свойства Items; в двух других случаях рисуемые пользователем списки могут иметь фиксированную (IbOwnerDrawFixed) или переменную (IbOwnerDrawVariable) высоту элемента. В первом случае нужно задать свойство:
(Pb) property ItemHeight: Integer;
Для стиля IbOwnerDrawVariable высота каждого элемента определяется программистом, которьш должен предусмотреть обработку события:
(Pb) property OnMeasureItem: TMeasureItemEvent;
TMeasureItemEvent = procedure(ListBox: TListBox; Index:
Integer; var Height: Integer) of object;
Имея указатель на список, индекс измеряемого элемента и начальную высоту, необходимо переустановить Height так, чтобы в элементе поместилось все, что нужно в нем нарисовать.
Для рисования каждого элемента инициируется событие:
(Pb) property OnDrawItem: TDrawItemEvent;
TDrawItemEVent = procedure(ListBox: TListBox; Index: Integer;
Rect: TRect; State: TOwnerDrawState) of object;
Обработчик этого события получает указатель на список ListBox, индекс элемента Index, отведенньш для рисования прямоугольник Rect, и состояние элемента в параметре State:
TOwnerDrawState = set of (odSelected, odGrayed, odDisabled,
odChecked, odFocused) ;
Для списка выбора из этого множества действительны только флаги odSelected, odDisabled, odFocused.
Компонент TComboBox
TObject—>TPersistent->TComponent—”TControl—”TWinControl—>
—>TCustomCornboBox—>TComboBox
Модуль STDCTRLS
Страница Палитры компонентов Standard
Этот стандартный элемент управления Windows — комбинированный список -— имеет много общего с TListBox. Он состоит из собственно списка и помещенного рядом поля ввода редактирующего элемента. Таким образом, пользователь может выбрать одно из готовых значений какой-то величины или ввести свое. Стиль компонента в части правил взаимного сочетания списка и редактора определяется свойством:
(РЁ) 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;
(RcS) property Canvas: TCanvas;
Текст, содержащийся в редактирующем элементе списка, доступен через свойство:
(р5) property Text: TCaption;
Его максимальная длина ограничена числом символов, равным значению свойства:
(Р1э) 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 это свойство описано, но не реализовано (не играет роли).
Компонент 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;
Указатель на родительский узел определяется свойством:
(Ro) property Parent: TOutlineNode;
Если список дочерних узлов не пуст, что можно проверить при помощи свойства
(Ro) property Hasltems: Boolean;
то для получения информации о них есть метода,!:
function GetFirstChild: Longint;
function GetLastChild: Longint;
function GetNextChild(Value: Longint): Longing-function GetPrevChiId(Value: Longint): Longint;
В последних двух методах параметр Value содержит индекс предыдущего найденного потомка. Индекс — это уникальный идентификатор узла в дереве, определенный свойством:
(Ro) property Index: Longint;
Используя его, можно получить указатель на узел (см. ниже сам компонент TOutline). Узлы пронумерованы таким образом, что если родитель имеет номер N, то первый из его потомков — номер (N+1).
Можно узнать и полное имя (путь) узла, представляющее собой конкатенацию всех родительских имен и имени узла, разделенных специальным символом. Этот символ определен в свойстве ItemSeparator объекта TCustomOutline, которому принадлежат узлы. Полный путь определяется свойством:
(Ro) property FullPath: string;
Каждый узел расположен на своем иерархическом уровне. На самом верху находится узел уровня 0. Все другие являются для пего дочерними; он не виден и не доступен пользователю. Поэтому на первом доступном уровне — с номером 1 — могут находиться по вашему желанию один или несколько узлов. Уровень иерархии узла можно узнать в его свойстве:
(ro) 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 прежний узел, которьш смещается дальше по списку на том же уровне.
Индекс того из предков узла, которьш находится в списке самого высокого уровня, известен из свойства:
(Ro) property Topltem: Longint;
Для корневого узла это свойство равно 0.
Компонент TOutline не только хранит древовидную структуру, он еще и отображает ее. На экране каждый узел может находиться в двух состояниях, свер
нутом и развернутом. В свернутом состоянии потомки узла не видны, в развернутом они изображаются чуть ниже и правее друг под другом. Состояние узла может иллюстрироваться значком (плюс/минус, открытая/закрытая папка — см. описание свойства OutlineStyle компонента TOutline). В таблице приведены методы и свойства, управляющие состоянием узла на экране:
property Expanded: Boolean; | Указывает, в каком состоянии находится узел; True — развернутое состояние. |
procedure Collapse; | Сворачивает узел, пряча все дочерние узлы. |
procedure Expand; | Разворачивает узел списка, показывая дочерние узлы. |
procedure FullExpand; | Полностью разворачивает узел, показывая все дочерние узлы всех подуровней. |
Сворачивать/разворачивать узлы дерева, помимо щелчков мышью, можно нажатием клавиш:
<+> — соответствует Expand;
<-> — соответствует Collapse;
<*> — соответствует FullExpand. Свойство
(Ro) property IsVisible: Boolean;
означает, может ли быть виден узел. Это возможно только в том случае, если виднь! все его родители. При отрисовке ширина узла сообщается методом:
function GetDisplayWidth: Integer;
Теперь перейдем от описания узла к описанию самого дерева — компонента TOutline. Он представляет собой совокупность узлов типа TOutlineNode. Всего в дереве содержится число узлов, равное значению свойства:
(Ro) property ItemCount: Longint;
К каждому из них можно обратиться, используя свойство:
(Ro) 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.
3.5. Группирование компонентов
По умолчанию родителем для большинства компонентов, размещенных на форме, является она сама. В ряде случаев, однако, есть необходимость отказаться от этого правила, как визуально, так и функционально подчеркнув обособленность каких-то элементов управления. Для этого вы можете использовать специальные группирующие компоненты TGroupBox и TPanel. Мы также отнесли в эту группу компонент TScrollBox, он также обычно имеет дочерние компоненты, которые все вместе подвергаются прокрутке. Общим признаком для всех группирующих компонентов является наличие опции csAcceptsControls в свойстве ControlStyle.