Как удержать элементы управления в Scroll Box от перехода в фокус?

У меня есть TScrollBox который прокручивается вертикально, а горизонтальная полоса прокрутки отключена. Внутри этого поля прокрутки находится одна большая панель, выровненная по верху, а ее высота динамически рассчитывается на основе ее содержимого. Его содержимое состоит из двух панелей, одна выровнена по левому краю, а другая выровнена по клиенту, с разделителем между ними. Внутри каждой из этих двух панелей находится ряд выбранных пользователем панелей, выровненных по верху, которые также могут динамически изменять размеры, таким образом, увеличивая / уменьшая высоту основной панели внутри поля прокрутки.

procedure TfrmDashboard.ResizePanels;
var
  X: Integer;
  H1, H2: Integer;
  H: Integer;
begin
  H1:= 0;
  H2:= 0;
  //Calculate height of left panel
  for X := 0 to p1.ControlCount-1 do
    H1:= H1 + p1.Controls[X].Height;
  //Calculate height of right panel
  for X := 0 to p2.ControlCount-1 do
    H2:= H2 + p2.Controls[X].Height;
  //Check which panel is larger
  H:= H1;
  if H2 > H then
    H:= H2;
  //Adjust scrolling height
  pMain.Height:= H + 10;
  SB.VertScrollBar.Range:= pMain.Height;
  SB.VertScrollBar.Size:= pMain.Height;
end;

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

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

Это похоже на "функцию", но функцию, которую я хотел бы отключить. Это довольно раздражает в этой ситуации. Как предотвратить прокрутку поля прокрутки, когда один из его детей получает фокус?

1 ответ

Решение

Это поведение по умолчанию для TScrollBox, и нет свойства, чтобы отключить эту функцию.
Но вы можете изменить это поведение, создав подкласс TScrollBox и использовать вместо этого этот новый класс:

TModifiedScrollBox=class(TScrollBox)
protected
    procedure AutoScrollInView(AControl:TControl); override;
end;

procedure TModifiedScrollBox.AutoScrollInView(AControl:TControl);
begin
  // empty body
end;

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

TModifiedScrollBox=class(TScrollBox)
protected
    procedure AutoScrollInView(AControl:TControl); override;
    procedure AutoScrollInViewSave(AControl:TControl);
end;

procedure TModifiedScrollBox.AutoScrollInViewSave(AControl:TControl);
begin
  // forward to base implementation
  inherited AutoScrollInView(AControl);
end;

И затем в вашем коде вы должны заменить все вызовы AutoScrollInView на AutoScrollInViewSave для этого нового класса.

PS При каждом обращении к новому элементу управления TCustomForm вызывает AutoScrollInView для всех родителей этого целевого элемента управления.

Другие вопросы по тегам