Как правильно обрабатывать централизованные TActionLists в приложениях с поддержкой HighDPI для обеспечения правильного масштабирования изображений на разных мониторах?
Решение проблем масштабирования изображений в HighDPI приложениях Delphi с централизованными TActionList
Проблема
При использовании централизованных TActionList с TVirtualImageList на DataModule в приложениях Delphi возникает проблема: при перемещении формы на монитор с другим DPI изображения действий не масштабируются корректно. Это происходит из-за того, что TVirtualImageList не принадлежит форме и не может адаптироваться к изменениям DPI в реальном времени.
Привязка действий к элементам управления на разных формах приводит к "расплыванию" иконок на мониторах с высоким DPI.
Основное решение: TVirtualImageList на каждой форме
Почему это необходимо?
Windows API требует, чтобы HIMAGELIST содержал изображения фиксированного размера. Каждая форма может находиться на мониторе с уникальным масштабом, что делает централизованное управление изображениями невозможным.
Шаги реализации: 1. Добавьте TVirtualImageList на каждую форму. 2. Свяжите его с визуальными элементами (меню, тулбары):
// На форме
TMainForm = class(TForm)
ToolBar: TToolBar;
MainMenu: TMainMenu;
Actions: TActionList;
FormImageList: TVirtualImageList;
procedure FormCreate(Sender: TObject);
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
ToolBar.Images := FormImageList;
MainMenu.Images := FormImageList;
Actions.Images := MainDataModule.VirtualImageList; // Централизованные действия
end;
Используйте TImageCollection для хранения оригиналов изображений:
// Центральный ImageCollection на DataModule
TMainDataModule = class(TDataModule)
ImageCollection: TImageCollection;
// ...
end;
Настройте TVirtualImageList форм на использование общего TImageCollection:
<!-- DFM-файл формы -->
object FormImageList: TVirtualImageList
ImageCollection = MainDataModule.ImageCollection
Scaled = True
end
Альтернативные подходы
1. Использование DevExpress TcxImageList (SVG)
Для проектов с DevExpress компонентами:
// Пример использования SVG
var
ImageList: TcxImageList;
begin
ImageList := TcxImageList.Create(nil);
ImageList.AddSvg('SVG_DATA_HERE', clRed, 16); // 16 - базовый размер
Action.Images := ImageList;
end;
Ограничения: - Не поддерживает стандартные VCL-контролы (TTreeView, TListView) - Требует замены элементов интерфейса на DX-аналоги (TdxBarManager вместо TMainMenu)
2. Динамическое копирование изображений
Решение Dave Novo с синхронизацией изображений:
// Центральный DataModule
procedure TMainDataModule.CopyImageTo(AImageList: TCustomImageList;
const AImageName: string);
begin
ImageCollection.GetIcon(ImageCollection.GetIndexByName(AImageName), AImageList.Add);
end;
// На форме
procedure TMainForm.FormCreate(Sender: TObject);
begin
MainDataModule.CopyImageTo(FormImageList, 'ExportToExcel');
actExport.ImageIndex := 0;
end;
Лучшие практики
Единый источник изображений:
Храните SVG/PNG в TImageCollection
Используйте именованные изображения: const IMG_EXPORT = 'export_icon';
IMG_PRINT = 'print_icon';
Автоматизация при проектировании: Создайте шаблон формы с предустановленными настройками:
object
TemplateForm: TForm
object
VirtualImageList: TVirtualImageList
ImageCollection = MainDataModule.ImageCollection
AutoFill = True
end
end
Обработка DPI-изменений: procedure TMainForm.WMDpiChanged(var Message: TWMDpi);
begin
inherited;
FormImageList.SetSize(CurrentDpi); // Автоматическая перерисовка
UpdateActions; // Обновление элементов интерфейса
end;
Тестирование: // Принудительная смена DPI в IDE
procedure TTestForm.Button1Click(Sender: TObject);
begin
ChangeDpi(FormImageList, 144); // Тест для 150%
end;
Сравнение подходов
Метод
Плюсы
Минусы
Форменные ImageLists
Нативная поддержка VCL
Ручное создание компонентов
DevExpress
Векторная графика
Привязка к DX-контролам
Динамическое копир.
Гибкость
Риск рассинхронизации
Рекомендация: Для крупных проектов с mixed-DPI окружениями оптимально комбинировать подходы: использовать TVirtualImageList на формах с централизованным TImageCollection, дополняя DevExpress-компонентами для сложных интерфейсов.
Этот текст описывает проблему масштабирования изображений в HighDPI приложениях Delphi с централизованными TActionList и предлагает несколько решений для ее устранения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.