скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Установка границ для вновь создаваемых элементов управления



Если вы создаете в среде Delphi новый элемент управления, и вам нужно контролировать или ограничить свойства Left, Top, Width и Height, то спешу вас обрадовать: есть одно простое решение сделать это. Тем не менее, в документации по Delphi я не увидел ни малейшего намека на данный способ (включая CWG).

Ключевой момент кроется в изменении Left, Top, Width, Height и каждого BoundsRect в Delphi методом SetBounds() (доступного в TControl и во всех его потомках). SetBounds() - виртуальная фунция, делающее установление позиции и размера элемента управления делом легким и приятным. Тем не менее, о чем умалчивается в документации, что TControl.SetBounds() вызывает методы TControl SetLeft(), SetTop(), SetWidth() и SetHeight() при каждом изменении значений свойств Left, Top, Width, Height и BoundsRect.

Таким образом, для того, чтобы ловить изменения этих свойств, просто перекройте метод SetBounds(), сделайте все, что вам нужно с новыми значениями, после чего передайте их унаследованному методу SetBounds().

В следующем примере мы имеем управление, которое автоматически изменяет свои пользовательские свойства X & Y, с той целью, чтобы они ссылались на центр элемента управления при изменении значений Left, Top, Width, Height или BoundsRect. И наоборот, Left и Top будут изменяться всякий раз при изменении свойств X & Y:


type
  TMyControl = class(TControl)
  private
    FX, FY: integer;
    {методы доступа к свойствам}
    procedure SetX(value: integer);
    procedure SetY(value: integer);
    ...
    public
    procedure SetBounds(aLeft, aTop, aWidth, aHeight: integer); override;
    ...
      property X: integer read FX write SetX;
    property Y: integer read FY write SetY;
  end;
  ...

procedure TMyControl.SetX(value: integer);
begin
  if FX <> value then
    SetBounds(value - Width div 2, Top, Width, Height);
end;

procedure TMyControl.SetY(value: integer);
begin
  if FY <> value then
    SetBounds(Left, value - Height div 2, Width, Height);
end;

procedure TMyControl.SetBounds(aLeft, aTop, aWidth, aHeight: integer);
begin
  {Продолжаем, и позволяем SetBounds() сделать свое дело...}
  inherited SetBounds(aLeft, aTop, aWidth, aHeight);
  {Теперь "регулируем" FX и FY согласно нашим новым границам.}
  FX := Width div 2;
  FY := Height div 2;
end;

Также в документации не упоминается о том факте, что частные поля FLeft, FTop, FWidth и FHeight, которые TControl использует для хранения внутренних значений, используются в методах SetLeft(), SetTop() и пр. для сравнения с текущими границами прямоугольника, при совпадении которых он не обновляется. Фактически, эти переменные нигде, кроме как в методе TControl SetBounds(), не корректируются (как в случае с FX и FY в приведенном выше примере).

Так, чтобы ограничить изменения размеров вашего элемента управления, вы должны перекрыть SetBounds(), и проверять/изменять любые свойства перед передачей значений унаследованному методу SetBounds().

В следующем примере мы имеем управление, которое ограничивает свою ширину и высоту в 100 пикселей:


type
  TMyControl = class(TControl)
    ...
    public
    procedure SetBounds(aLeft, aTop, aWidth, aHeight: integer); override;
    ...
  end;

...

procedure TMyControl.SetBounds(aLeft, aTop, aWidth, aHeight: integer);
begin
  if aWidth > 100 then
    aWidth := 100;
  if aHeight > 100 then
    aHeight := 100;
  inherited SetBounds(aLeft, aTop, aWidth, aHeight);
end;






Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook