Шаг 30.
Свойства и методы класса TWinControl

    На этом шаге мы начнем изучение некоторых событий и методов класса TWinControl. Полный перечень свойств, методов и событий приведен на шаге 17.

    Понятие окна Windows инкапсулировано в классе TWinControl, который является потомком TControl. Такой компонент получает соответствующий атрибут - дескриптор окна, определяемый свойством:

   property Handle: HWnd;       . 

    С помощью этого дескриптора можно вызывать функции API Windows, если средств VCL недостаточно для решения задачи. Компоненты-потомки TWinControl в дальнейшем будем называть оконными элементами управления, а элементы управления, не имеющие дескриптора окна, - неоконными.

    Возможны ситуации, когда компонент уже создан, но еще не имеет дескриптора как окно. Два метода управляют созданием дескриптора:

   function  HandleAllocated : Boolean;
   procedure HandleNeeded;       . 

    Первая сообщает о наличии выделенного дескриптора, а вторая при его отсутствии посылает запрос на его выделение. Такой метод должен применяться перед каждой операцией, требующей дескриптора.

    Важным свойством TWinControl является то, что он может содержать другие (дочерние) элементы управления. Они упорядочены в виде списка. Если быть точным, то списков на самом деле два - для неоконных и оконных дочерних элементов. Но "видны" они как один объединенный - сначала первый, потом второй.

    Методы и свойства для работы с этим списком приведены в таблице 1.

   
Таблица 1. Методы и свойства для работы с дочерними элементами управления
Метод (Свойство) Описание
propertyControls[Index: Integer]: TControl; Содержит список дочерних элементов.
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;       . 

    Когда компонент находится в фокусе, то при нажатии клавиши F1 загружается система контекстной помощи, и пользователь сразу получает информацию, связанную с заданным контекстом. Если контекст равен нулю, то система пытается отыскать в цепочке родительских компонентов первый, имеющий ненулевой контекст.

    Оконный компонент может управлять положением и размерами своих дочерних компонентов.

    Прокрутку (скроллинг) элементов на интервал DeltaX, DeltaY осуществляет метод:

   procedure ScrollBy(DeitaX, DeitaY: Integer);       . 

    Прибегая к вызову этой процедуры, можно, при желании, осуществить прокрутку нестандартным способом, то есть без привлечения полос прокрутки.

    Проиллюстрируем использование рассмотренных методов на конкретном примере. Расположите на форме компонент Image1 (тип TImage, вкладка Additional).


Рис.1. Внешний вид приложения

    Приведенный ниже фрагмент кода позволяет "тащить" изображение Image1 вслед за мышью с нажатой кнопкой:

unit Un_30_1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
                        Y: Integer);
    procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
                  Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMouseState = (msNonnal, msDragging);
var
  Form1: TForm1;
  OldPos, NewPos: TPoint;
  FMouseState : TMouseState;
implementation

{$R *.dfm}

procedure TForm1.Image1MouseDown(Sender: TObject; 
     Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  //"Включение" режима перетаскивания.
  FMouseState := msDragging;
  //Запоминание координат точки.
  OldPos := Point(X, Y);
  //Изменение внешнего вида курсора.
  Screen.Cursor := crDrag;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; 
Shift: TShiftState; 
                      X, Y: Integer);
begin
  if FMouseState = msDragging then //Выключен режим перетаскивания.
  begin
     //Вычисление новых координат.
     NewPos := Point(X - OldPos.X, Y - OldPos.Y);
     //Изменение местоположения компонента.
     Image1.Parent.ScrollBy(NewPos.X, NewPos.Y);
  end;
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);

begin
  FMouseState := msNonnal; //"Отключение" режима перетаскивания.
  Screen.Cursor := crDefault; //Вид курсора - по умолчанию.
end;

end.

    Текст этого примера можно взять здесь.


    Примечание. Обратите внимание, что прокрутка компонента Image1 осуществляется посредством вызова Image1.Parent.ScrollBy. Это свидетельствует о том, что конкретный родительский тип для этого безразличен. Метод ScrollBy используется также и полосами прокрутки, которые есть в классе TScrollingWinControl и его потомках, например, в TForm.

    В VCL предусмотрена возможность написания приложений, которые будут сохранять относительный размер и положение при всех разрешениях дисплея. Одним из используемых при этом методов является метод:

   procedure ScaleВу(M, D: Integer);   , 

который изменяет масштаб элемента управления в M/D раз, при этом верхний левый угол остается неподвижным. Так же изменяются и размеры всех дочерних элементов. Соответственно изменяется и масштаб шрифта (свойство Font). Флаги csFixedWidth и csFixedHeight в свойстве ControlStyle предотвращают изменение ширины или высоты.

    При изображении большинства оконных элементов управления используют эффект "трехмерности", создающий иллюзию приподнятости или вдавленности за счет подбора внешнего вида обрамления. Наличие "трехмерности" задается свойством:

   property Ctl3D: Boolean;  . 

    Нужно уточнить, что это свойство есть не у всех компонентов. Для части компонентов трехмерность реализована средствами VCL. Другая же часть (радиокнопки, флажки и др.) требует для создания трехмерного эффекта доступа к библиотеке CTL3DV2.DLL.

    Шрифт, которым выводится текст, связанный с элементом управления, определяется свойством:

   property Font: TFont;  . 

    Кисть, используемая для закрашивания рабочей области оконного элемента управления, представлена свойством:

   property Brush: TBrush;  . 

    Она имеет цвет, содержащийся в свойстве Color (по умолчанию ciWindow). На уровне TControl оно доступно только для чтения:

   property Color: TColor;  . 

    На следующем шаге мы продолжим изучение состава класса TWinControl, в частности, остановимся на способах обработки нажатий клавиш на клавиатуре и кнопок мыши.




Предыдущий шаг Содержание Следующий шаг