Я создал удобный компонент, инкапсулирующий обычную кнопку, но с возможностью многострочного заголовка. В *действительности* - это TBitBtn, чей Glyph *нарисован* в виде заголовка с переносом текста. Реальный заголовок невидим. Это работает! Попробуйте с этим поэкспериментировать и сообщите мне о ваших новых находках. Я был удивлен, что это свойство оказалось легко *подавить*. Тем более, что это свойство public/published, а не какой-то кот в мешке. Все это так, но вы можете перекрыть свойство другим с таким же именем и с атрибутом READ ONLY. И вы можете ссылать на свойство предка, как, например, "Inherited Glyph". ООП!
unit C_wrapb;
interfaceuses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Buttons;
type
TWrapBtn = class(TBitBtn)
private{ Private declarations }function GetGlyph: string;
function GetMargin: Integer;
function GetSpacing: Integer;
function GetKind: TBitBtnKind;
function GetLayout: TButtonLayout;
function GetNumGlyphs: TNumGlyphs;
procedure CMTextChanged(varMessage: TMessage);
message CM_TEXTCHANGED;
procedure CMFontChanged(varMessage: TMessage);
message CM_FONTCHANGED;
procedure WMSize(var Msg: TWMSize);
message WM_SIZE;
procedure CaptionGlyph;
protected{ Protected declarations }public{ Public declarations }published{ Published declarations }property Glyph: string read GetGlyph;
property Margin: Integer read GetMargin;
property Spacing: Integer read GetSpacing;
property Kind: TBitBtnKind read GetKind;
property Layout: TButtonLayout read GetLayout;
property NumGlyphs: TNumGlyphs read GetNumGlyphs;
end;
procedureRegister;
implementationprocedure TWrapBtn.CaptionGlyph;
var
GP: TBitmap;
R: TRect;
Buff: array[0..255] of Char;
begin
GP := TBitmap.Create;
trywith GP dobegin
Canvas.Font := Self.Font;
StrPCopy(Buff, Caption);
inherited Margin := 0;
inherited Spacing := GetSpacing;
Width := Self.Width - GetSpacing;
Height := Self.Height - GetSpacing;
R := Bounds(0, 0, Width, 0);
DrawText(Canvas.Handle, Buff, StrLen(Buff), R,
DT_CENTER or DT_WORDBREAK or DT_CALCRECT);
OffsetRect(R, (Width - R.Right) div 2,
(Height - R.Bottom) div 2);
DrawText(Canvas.Handle, Buff, StrLen(Buff), R,
DT_CENTER or DT_WORDBREAK);
end;
inherited Glyph := GP;
inherited NumGlyphs := 1;
finally
GP.Free;
end;
end;
function TWrapBtn.GetGlyph: string;
begin
Result := '(Н/Д)';
end;
procedure TWrapBtn.CMTextChanged(varMessage: TMessage);
begininherited;
CaptionGlyph;
end;
procedure TWrapBtn.CMFontChanged(varMessage: TMessage);
begininherited;
CaptionGlyph;
end;
procedure TWrapBtn.WMSize(var Msg: TWMSize);
begininherited;
CaptionGlyph;
end;
function TWrapBtn.GetMargin: Integer;
begin
Result := 0;
end;
function TWrapBtn.GetSpacing: Integer;
begin{$IFDEF Win32}
Result := 12;
{$ELSE}
Result := 6;
{$ENDIF}end;
function TWrapBtn.GetKind: TBitBtnKind;
begin
Result := bkCustom;
end;
function TWrapBtn.GetLayout: TButtonLayout;
begin
Result := blGlyphLeft;
end;
function TWrapBtn.GetNumGlyphs: TNumGlyphs;
begin
Result := 1;
end;
procedureRegister;
begin
RegisterComponents('FAQ', [TWrapBtn]);
end;
end.
Код, предоставленный ниже, является компонентом TWrapBtn, который наследуется от TBitBtn и добавляет функциональность для многострочного заголовка. Компонент переопределяет несколько методов и свойства родительского класса, чтобы достичь этого.
В разделе реализации есть процедура CaptionGlyph, которая создает объект TBitmap, устанавливает шрифт в тот же, что у родительской кнопки, копирует заголовок в буфер, рисует текст на битмапе с помощью DrawText и затем присваивает битмапу свойству Glyph.
Функция GetGlyph по умолчанию возвращает '(Н/Д)' (рус. 'Не реализовано').
В методах CMTextChanged, CMFontChanged и WMSize CaptionGlyph вызывается всякий раз, когда текст или шрифт кнопки изменяются, или когда размер окна изменяется.
Функции GetMargin по умолчанию возвращает 0.
Функция GetSpacing возвращает различные значения в зависимости от того, запущено ли приложение под Windows (12) или нет (6).
Функции GetKind, GetLayout и GetNumGlyphs возвращают bkCustom, blGlyphLeft и 1 соответственно.
Наконец, есть процедура Register, которая регистрирует компонент в IDE.
Идея за этим - предоставить способ для разработчиков иметь многострочный текст в своих кнопках без необходимости создавать custom control или использовать внешнюю библиотеку. Используя свойство Glyph TBitBtn, разработчик может установить текст кнопки по своему желанию и затем вызвать CaptionGlyph для перерисовки глифа с новым текстом.
Одной из возможных альтернативных решений могло бы быть создание custom control, наследующегося от TButton вместо TBitBtn, так как это позволило бы более гибкой настройке и расположению.
Автор статьи описывает созданный им компонент TWrapBtn, который позволяет использовать кнопку TBitBtn с многострочным заголовком.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS