Страница 18 из 39 Оконные элементы управления Понятие окна 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: Integers-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: Integers-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 предотвращают изменение ширины или высоты. При изображении большинства оконных элементов управления используют эффект "трехмерности", создающий иллюзию приподнятости или вдавленное™ за счет подбора внешнего вида обрамления. Наличие "трехмерности" задается свойством: (РЙ property Ctl3D: Boolean; Нужно уточнить, что это свойство есть не у всех компонентов. Для части компонентов трехмерность реализована средствами VCL; другая же часть (радиокнопки, флажки и др.) требует для создания трехмерного эффекта доступа к библиотеке CTL3DV2.DLL. Шрифт, которым выводится текст, связанный с элементом управления: property Font: TFont; Кисть, используемая для закрашивания рабочей области оконного элемента управления, представлена свойством: (Ro) property Brush: TBrush; Она имеет цвет, содержащийся в свойстве Color (по умолчанию clWindow). На уровне TControl оно доступно только по чтению: property Color: TColor; Подробно о последних двух типах см. в разделе "Графическая подсистема". |