При работе с компонентом TShellTreeView в Delphi и Pascal часто возникает необходимость автоматически прокручивать дерево, чтобы выбранная папка была видна. Проблема заключается в том, что при загрузке дерева, особенно при большом количестве элементов, выбранная папка может остаться за пределами видимой области. Это обсуждалось на форумах разработчиков, и в данной статье мы рассмотрим проблему, её решение и предоставим примеры кода.
Описание проблемы
Как было описано в исходной дискуссии, при установке свойства Path компонента TShellTreeView в обработчике события FormCreate, прокрутка до выбранной папки не происходит. Это связано с тем, что в момент вызова FormCreate не все компоненты Delphi полностью инициализированы, включая canvas и необходимые для расчета высоты узлов элементы. В результате, вызов ShellTreeView1.Selected.MakeVisible в FormCreate не приводит к желаемому результату.
Решение: Перенос кода в обработчик событий FormActivate или FormShow
Наиболее эффективным решением является перенос кода, который устанавливает путь и прокручивает дерево, в обработчик события FormActivate или FormShow. Эти события вызываются после полной инициализации формы и всех её компонентов, что гарантирует правильную работу MakeVisible.
Пример кода (FormActivate):
type
TForm1 = class(TForm)
ShellTreeView1: TShellTreeView;
Memo1: TMemo;
private
FActivated: Boolean;
protected
procedure FormActivate(Sender: TObject); override;
end;
implementation
procedure TForm1.FormActivate(Sender: TObject);
begin
if not FActivated then
begin
ShellTreeView1.Path := 'c:Windows'; // Или любой другой путь
Memo1.Append('Path = ' + ShellTreeView1.Path);
if Assigned(ShellTreeView1.Selected) then
begin
ShellTreeView1.Selected.MakeVisible;
Memo1.Append('Selected.MakeVisible');
end
else
begin
Memo1.Append('Selected = Nil');
end;
FActivated := true;
end;
end;
Альтернативное решение: Использование QueueAsyncCall
Другой подход заключается в использовании Application.QueueAsyncCall для выполнения кода, который прокручивает дерево, асинхронно после загрузки формы. Это позволяет избежать проблемы с неинициализированными компонентами, но требует аккуратного управления потоками.
Пример кода (QueueAsyncCall):
type
TForm1 = class(TForm)
ShellTreeView1: TShellTreeView;
Memo1: TMemo;
procedure ShowInfo(AData: PtrInt);
private
FActivated: Boolean;
protected
procedure FormCreate(Sender: TObject); override;
end;
implementation
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.QueueAsyncCall(@ShowInfo, 0);
end;
procedure TForm1.ShowInfo(AData: PtrInt);
begin
ShellTreeView1.Path := '/home/don/lazarus/projects/ShellTreeMkVis'; // Или любой другой путь
Memo1.Append('Path = ' + ShellTreeView1.Path);
if Assigned(ShellTreeView1.Selected) then
begin
ShellTreeView1.Selected.MakeVisible;
Memo1.Append('Selected.MakeVisible');
end
else
begin
Memo1.Append('Selected = Nil');
end;
end;
Важные замечания:
Проверка на nil: Всегда проверяйте, что ShellTreeView1.Selected не равно nil перед вызовом MakeVisible. Это предотвратит ошибку, если дерево еще не загружено или нет выбранного элемента.
Многократное выполнение: Обратите внимание, что события FormActivate и FormShow могут вызываться несколько раз. Чтобы избежать повторной установки пути и прокрутки, рекомендуется использовать флаг, как показано в примере с FActivated.
Высокое разрешение (HiDPI): В некоторых случаях, особенно на мониторах с высоким разрешением, может потребоваться дополнительная настройка масштабирования, чтобы обеспечить правильную прокрутку. Это может быть связано с неправильным расчетом высоты узлов дерева. Решение, предложенное в исходной дискуссии, заключалось в модификации UpdateDefaultItemHeight, но это может привести к другим проблемам и не рекомендуется, если нет крайней необходимости. Лучше использовать FormActivate или FormShow и убедиться, что приложение настроено правильно для HiDPI.
Вывод
Проблема с прокруткой до выбранной папки в TShellTreeView решается путем переноса кода, который устанавливает путь и вызывает MakeVisible, в обработчик событий FormActivate или FormShow. Это гарантирует, что все компоненты Delphi полностью инициализированы, и прокрутка будет работать корректно. Использование Application.QueueAsyncCall является альтернативным, но более сложным решением. Не забудьте проверить на nil выбранный узел и использовать флаг для предотвращения многократного выполнения кода.
Описание проблемы с прокруткой до выбранной папки в компоненте TShellTreeView в Delphi и Pascal, её решение и примеры кода.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.