Справочник по компонентам Delphi. Часть 1 - Оконные элементы управления
ОГЛАВЛЕНИЕ
Оконные элементы управления
Понятие окна Windows инкапсулировано в потомке TControl — классе TWinControl. Такой компонент получает соответствующий атрибут _ дескриптор окна, определяемый свойством:
(Ro) property Handle: HWnd;
С помощью этого дескриптора вы можете вызывать функции API Windows, если средств VCL вам недостаточно для решения задачи. Компоненты-потомки TWinControl — в дальнейшем будем называть оконными элементами управления, а элементы управления, не имеющие дескриптора окна, — неоконными.
Возможны ситуации, когда компонент уже создан, но еще не имеет дескриптора как окно. Два метода управляют созданием дескриптора:
function HandleAllocated:Boolean; procedure HandleNeeded;
Первая сообщает о наличии выделенного дескриптора, а вторая при его отсутствии посылает запрос на его выделение. Такой метод должен применяться перед каждой операцией, требующей дескриптора.
Важным свойством TWinControl является то, что он может содержать другие — дочерние — элементы управления. Они упорядочены в виде списка. Если быть точным, то списков на самом деле два — для неоконных и оконных дочерних элементов. Но "видны" они как один объединенный — сначала первый, потом второй. Методы и свойства для работы с этим списком приведены в таблице:
(Ro) property Controls[Index: Integer]: TControl; | Содержит список дочерних элементов. |
(Ro) property ControlCount: Integer; | Содержит число элементов в списке. |
function ContainsControl(Control: TControl): Boolean; | Проверяет наличие элемента в списке. |
function ControlAtPos(const Pos: TPoint; AllowDisabled: Boolean): TControl ; | Отыскивает в списке элемент, которому принадлежит заданная точка (в системе координат собственной клиентской области). Флаг AllowDisabled показывает, разрешен ли поиск среди пассивных (свойство Enabled которых равно False) элементов. |
procedure InsertControl(AControl: TControl) ; | Вставляет элемент в конец списка. |
procedure RemoveControl(AControl: TControl); | Удаляет элемент из списка. |
procedure Broadcast(var Message); | Рассылает всем дочерним элементам из списка сообщение Message. |
С каждым оконным компонентом можно связать контекстную помощь. Контекст помощи — это индекс, указывающий на определенную информацию в файле справочной системы, связанном с приложением:
property HelpContext: THelpContext;
Когда компонент находится в фокусе, то при нажатии клавиши загружается система контекстной помощи, и пользователь сразу получает информацию, связанную с заданным контекстом. Если контекст равен нулю, то система пытается отыскать в цепочке родительских компонентов первый, имеющий ненулевой контекст.
Оконный компонент может управлять положением и размерами своих дочерних компонентов.
Прокрутку (скроллинг) элементов на интервал DeltaX, DeltaY осуществляет метод:
procedure ScrollBy(DeltaX, DeltaY: Integer);
Прибегая к вызову этой процедуры, можно при желании осуществить прокрутку нестандартным способом, т. е. без привлечения полос прокрутки. Приведенный ниже фрагмент кода — составная часть примера IMGSCROL на дискете— позволяет "тащить" изображение Imagel вслед за мышью с нажатой кнопкой:
type
TMouseState = (msNormal, msDragging);
var
OldPos, NewPos, MaxShift: TPoint;
PMouseState : TMouseState;
procedure TFormI.ScrollMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
MaxShift.X := Imagel.Parent.Width - Imagel.Width;
MaxShift.Y := Imagel.Parent.Height - Imagel.Height;
if (MaxShift.X > 0) and (MaxShift.Y > 0) then Exit;
FMouseState := msDragging; OldPos := Point(X, Y);
Screen.Cursor := crDrag;
end;
procedure TFormI.ScrollMouseMove(Sender : TObject; Shift: TShiftState; X, Y: Integer);
begin
if FMouseState = msDragging then
begin
NewPos := Point(X - OldPos.X, Y - OldPos.Y);
if Imagel.Left + NewPos.X > 0 then NewPos.X := - Imagel.Left;
if Imagel.Left + NewPos.X < MaxShift.X then NewPos.X := MaxShift.X - Imagel.Left;
if Imagel.Top + NewPos.Y > 0 then NewPos.Y := - Imagel.Top;
if Imagel.Top + NewPos.Y < MaxShift.Y then NewPos.Y := MaxShift.Y - Imagel.Top;
Imagel.Parent.ScrollBy(NewPos.X, NewPos. Y);
end;
end;
procedure TFormI.ScrollMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FMouseState := msNormal;
Screen.Cursor := crDefault;
end;
Обратите внимание, что прокрутка неоконного компонента Imagel осуществляется посредством вызова Image l.Parent.ScrollBy. Это свидетельствует о том, что конкретный родительский тип для этого безразличен. В примере изображение помещено на панель (TPanel). Впрочем, метод ScrollBy используется также и полосами прокрутки, которые есть в компоненте TScrollingWinControl и его потомках, например, в TForm.
В VCL предусмотрена возможность написания приложений, которые будут сохранять относительный размер и положение при всех разрешениях дисплея. Более подробно эти механизмы описаны в разделе, посвященном формам; для TWinControl упомянем лишь метод
procedure ScaleBy(M, D: Integer);
который изменяет масштаб элемента управления в M/D раз, при этом верхний левый угол остается неподвижным. Так же изменяются и размеры всех дочерних элементов. Соответственно изменяется и масштаб шрифта (свойство Font). Флаги csFixedWidth и csFixedHeight в свойстве ControlStyle предотвращают изменение ширины или высоты.
При изображении большинства оконных элементов управления используют эффект "трехмерности", создающий иллюзию приподнятости или вдавленное™ за счет подбора внешнего вида обрамления. Наличие "трехмерности" задается свойством:
(Рb) property Ctl3D: Boolean;
Нужно уточнить, что это свойство есть не у всех компонентов. Для части компонентов трехмерность реализована средствами VCL; другая же часть (радиокнопки, флажки и др.) требует для создания трехмерного эффекта доступа к библиотеке CTL3DV2.DLL.
Шрифт, которым выводится текст, связанный с элементом управления:
property Font: TFont;
Кисть, используемая для закрашивания рабочей области оконного элемента управления, представлена свойством:
(Ro) property Brush: TBrush;
Она имеет цвет, содержащийся в свойстве Color (по умолчанию clWindow). На уровне TControl оно доступно только по чтению:
property Color: TColor;
Подробно о последних двух типах см. в разделе "Графическая подсистема".