Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Проблемы с AnchorDocking в Lazarus: как исправить ошибку при закрытии последнего окна

Delphi , Синтаксис , Drag and Drop

 

AnchorDocking — мощная библиотека для создания интерфейсов с докируемыми окнами в Lazarus и Delphi. Однако, как показывает практика, при работе с ней могут возникать неожиданные проблемы. В этой статье мы разберём распространённую ошибку, когда после закрытия последнего докированного окна система докинга перестаёт работать, и предложим несколько способов её решения.

Описание проблемы

Как отмечают пользователи на форумах (включая pebe и andrew_arprix), при использовании AnchorDocking возникает следующая ситуация:

  1. Пользователь создаёт докируемые окна динамически во время работы программы
  2. После закрытия последнего докированного окна (особенно через кнопку закрытия) система докинга перестаёт работать
  3. Попытки заново закрепить новые окна не дают результата — DockMaster как бы "исчезает"
// Типичный код, который может вызывать проблему
procedure TMainForm.CreateDockableForm;
var
  VForm: TForm;
begin
  VForm := TForm.Create(Self);
  DockMaster.MakeDockable(VForm, True, True); // Создаём докируемую форму
end;

Причины проблемы

Основная причина кроется в том, что при закрытии последнего докированного окна система AnchorDocking теряет "точку опоры" — контейнер, к которому можно пристыковывать новые окна. Это происходит потому, что:

  1. При закрытии последнего окна закрывается и его хост-контейнер (TAnchorDockHostSite)
  2. DockMaster не восстанавливает автоматически основной контейнер для докинга
  3. Последующие попытки докинга не имеют целевого контейнера

Решения проблемы

1. Использование AnchorDockPanel (рекомендуемое решение)

Как отметил zamtmn, использование AnchorDockPanel решает проблему. Вот как это реализовать:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  // Создаём панель для докинга
  AnchorDockPanel1 := TAnchorDockPanel.Create(Self);
  AnchorDockPanel1.Parent := Self;
  AnchorDockPanel1.Align := alClient;

  // Настраиваем DockMaster
  DockMaster.MakeDockPanel(AnchorDockPanel1, admrpChild);
end;

procedure TMainForm.CreateDockableForm;
var
  VForm: TForm;
begin
  VForm := TForm.Create(Self);
  DockMaster.MakeDockable(VForm, False); // Не создаём плавающее окно автоматически
  VForm.Show;
end;

2. Модификация AnchorDocking.pas (альтернативное решение)

andrew_arprix предложил модификацию исходного кода AnchorDocking:

procedure TAnchorDockHeader.CloseButtonClick(Sender: TObject);
var
  HeaderParent: TAnchorDockHostSite;
begin
  TWinControl(HeaderParent) := Parent;
  if HeaderParent = TWinControl(DockMaster.FOverlappingForm) then
  begin
    HeaderParent := DockMaster.FOverlappingForm.AnchorDockHostSite;
    HeaderParent.HideMinimizedControl;
  end;
  if HeaderParent is TAnchorDockHostSite then
  begin
    DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(HeaderParent), True);
    HeaderParent.Undock(); // Критичное добавление
    HeaderParent.CloseSite;
  end;
end;

Это изменение гарантирует правильное освобождение ресурсов при закрытии окна.

3. Восстановление DockMaster при закрытии последнего окна

Если вы не хотите модифицировать исходный код, можно обрабатывать закрытие окон вручную:

procedure TMainForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  if DockMaster.AnchorDockHostSiteCount = 1 then // Если это последнее окно
  begin
    CloseAction := caNone;
    // Восстанавливаем главную форму как докируемую
    DockMaster.MakeDockable(MainForm);
    // Теперь можно закрыть форму
    CloseAction := caFree;
  end;
end;

Практические рекомендации

  1. Всегда используйте AnchorDockPanel как базовый контейнер для докинга
  2. Избегайте закрытия всех докируемых окон — оставляйте хотя бы одно
  3. Обрабатывайте событие OnClose для докируемых форм
  4. Рассмотрите возможность использования TAnchorDockSplitter для более гибкого управления
// Пример настройки гибкого интерфейса
procedure TMainForm.SetupDocking;
begin
  // Главная панель докинга
  DockMaster.MakeDockPanel(AnchorDockPanel1, admrpChild);

  // Настройка разделителей
  Splitter := TAnchorDockSplitter.Create(Self);
  Splitter.Parent := Self;
  Splitter.Align := alLeft;
  Splitter.ResizeAnchor := akLeft;

  // Дополнительная панель
  DockPanel2 := TAnchorDockPanel.Create(Self);
  DockPanel2.Parent := Self;
  DockPanel2.Align := alLeft;
  DockPanel2.Width := 200;
  DockMaster.MakeDockPanel(DockPanel2, admrpChild);
end;

Заключение

Проблема с исчезновением функциональности докинга после закрытия последнего окна — известный недостаток AnchorDocking. Однако, как мы показали, существует несколько рабочих способов её решения. Наиболее стабильным вариантом является использование TAnchorDockPanel в качестве постоянного контейнера.

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

Создано по материалам из источника по ссылке.

Контекст описывает проблему сбоя системы докинга AnchorDocking в Lazarus при закрытии последнего окна и предлагает три способа её решения: использование AnchorDockPanel, модификацию исходного кода библиотеки и ручное восстановление функциональности DockM


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Drag and Drop ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-08-13 04:53:15/0.00636887550354/0