При разработке приложений на Delphi часто возникает необходимость централизованного управления изображениями для кнопок и других элементов интерфейса. В этой статье мы рассмотрим, как создать потомок компонента TSpeedButton, в котором будет скрыто свойство Glyph, чтобы принудительно использовать централизованную коллекцию изображений.
Проблема стандартного подхода
Обычно разработчики используют свойство Glyph компонента TSpeedButton для установки изображения кнопки. Однако такой подход приводит к разрозненному хранению изображений, что усложняет их обновление и поддержку в больших проектах.
// Стандартное использование TSpeedButton
var
Button: TSpeedButton;
begin
Button := TSpeedButton.Create(Self);
Button.Glyph.LoadFromFile('image.bmp'); // Проблема: изображение хранится отдельно
end;
Решение: создание потомка TSpeedButton
Мы создадим новый компонент TCustomImageButton, который будет наследоваться от TSpeedButton, но скроет свойство Glyph, заменив его на централизованное управление изображениями.
Шаг 1: Создание нового класса компонента
unit CustomImageButton;
interface
uses
Vcl.Buttons, System.Classes, Vcl.Graphics;
type
TCustomImageButton = class(TSpeedButton)
private
FImageName: string;
procedure SetImageName(const Value: string);
protected
procedure Loaded; override;
public
constructor Create(AOwner: TComponent); override;
published
property ImageName: string read FImageName write SetImageName;
property Glyph stored False; // Скрываем свойство Glyph из инспектора объектов
end;
implementation
uses
ImageManager; // Предполагаем, что у нас есть центральный менеджер изображений
constructor TCustomImageButton.Create(AOwner: TComponent);
begin
inherited;
FImageName := '';
end;
procedure TCustomImageButton.Loaded;
begin
inherited;
if not (csDesigning in ComponentState) and (FImageName <> '') then
Glyph := ImageManager.GetImage(FImageName);
end;
procedure TCustomImageButton.SetImageName(const Value: string);
begin
if FImageName <> Value then
begin
FImageName := Value;
if not (csDesigning in ComponentState) and (FImageName <> '') then
Glyph := ImageManager.GetImage(FImageName);
end;
end;
end.
Шаг 2: Реализация менеджера изображений
Для централизованного хранения изображений создадим класс ImageManager:
unit ImageManager;
interface
uses
Vcl.Graphics, System.Generics.Collections, System.SysUtils;
type
TImageManager = class
private
FImages: TDictionary<string, TBitmap>;
public
constructor Create;
destructor Destroy; override;
procedure AddImage(const AName: string; ABitmap: TBitmap);
function GetImage(const AName: string): TBitmap;
end;
var
ImageManager: TImageManager;
implementation
constructor TImageManager.Create;
begin
inherited;
FImages := TDictionary<string, TBitmap>.Create;
end;
destructor TImageManager.Destroy;
var
Bmp: TBitmap;
begin
for Bmp in FImages.Values do
Bmp.Free;
FImages.Free;
inherited;
end;
procedure TImageManager.AddImage(const AName: string; ABitmap: TBitmap);
var
NewBmp: TBitmap;
begin
if FImages.ContainsKey(AName) then
raise Exception.Create('Image with this name already exists');
NewBmp := TBitmap.Create;
NewBmp.Assign(ABitmap);
FImages.Add(AName, NewBmp);
end;
function TImageManager.GetImage(const AName: string): TBitmap;
begin
if not FImages.TryGetValue(AName, Result) then
raise Exception.CreateFmt('Image "%s" not found', [AName]);
end;
initialization
ImageManager := TImageManager.Create;
finalization
ImageManager.Free;
end.
Шаг 3: Использование нового компонента
Теперь в вашем приложении вы можете использовать TCustomImageButton следующим образом:
// Инициализация менеджера изображений (например, при старте приложения)
procedure TForm1.FormCreate(Sender: TObject);
var
Bmp: TBitmap;
begin
Bmp := TBitmap.Create;
try
Bmp.LoadFromFile('ok_button.bmp');
ImageManager.AddImage('OK', Bmp);
Bmp.LoadFromFile('cancel_button.bmp');
ImageManager.AddImage('Cancel', Bmp);
finally
Bmp.Free;
end;
end;
// Создание кнопки с централизованным изображением
procedure TForm1.CreateButtons;
var
Button: TCustomImageButton;
begin
Button := TCustomImageButton.Create(Self);
Button.Parent := Self;
Button.ImageName := 'OK'; // Используем централизованное изображение
end;
Альтернативное решение: использование ImageList
В качестве альтернативы можно использовать стандартный компонент TImageList в сочетании со свойством ImageIndex TSpeedButton:
procedure TForm1.AlternativeSolution;
var
Button: TSpeedButton;
begin
// Настройка ImageList
ImageList1.AddImage('ok_button.bmp');
ImageList1.AddImage('cancel_button.bmp');
// Создание кнопки
Button := TSpeedButton.Create(Self);
Button.Parent := Self;
Button.Images := ImageList1;
Button.ImageIndex := 0; // Индекс изображения в ImageList
end;
Преимущества предложенного решения
Централизованное управление - все изображения хранятся в одном месте
Простота обновления - изменение изображения в одном месте обновляет все кнопки
Снижение памяти - изображения не дублируются для каждой кнопки
Более чистый код - устранение разрозненных вызовов LoadFromFile
Заключение
Предложенное решение позволяет эффективно управлять изображениями кнопок в приложениях Delphi, скрывая прямое использование свойства Glyph и обеспечивая централизованное хранение графических ресурсов. Это особенно полезно в крупных проектах, где важно поддерживать единообразие интерфейса и упрощать его модификацию.
В статье рассматривается создание кастомного компонента TCustomImageButton, наследующего TSpeedButton, для централизованного управления изображениями в приложении Delphi, скрывающего свойство Glyph и использующего общий менеджер графики.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.