Как эффективно позволить дочернему элементу управления `ParentFont = False` использовать то же имя шрифта, что и у родительского?
Большинство элементов управления VCL имеет Fonts
а также ParentFont
имущество. Это хорошая практика для установки ParentFont = True
и шрифты будут следовать его родительского шрифта Name
, Height
а также Color
, Это дает единообразное визуальное представление среди элементов управления.
Однако мы можем захотеть сделать один или два элемента управления отличными от других, установив Font.Style = fsBold
или контраст Font.Color
но используя то же самое Font.Name
как родительский шрифт. Это делает ParentFont = false
, С этого момента изменение имени или размера шрифта родителя не будет влиять на свойство шрифта этого элемента управления.
Я думаю, что это может быть дизайн VCL. Возможно, у кого-то есть лучшие методы проектирования или опыт, которыми можно поделиться по вопросу о шрифтах и ParentFont.
Рассмотрим случай, когда я позволю пользователю установить имя шрифта по умолчанию для приложения. Те ParentFont = False
управление не изменится соответственно. Ручное переопределение в кодировании возможно, но это утомительная работа, которая вводит дополнительное кодирование.
3 ответа
Это известное ограничение VCL.
Вы можете иметь ParentFont
или ваши собственные настройки шрифта, в этом случае изменение свойств шрифта в родительском не будет распространено.
Лучший способ обойти это использовать ParentFont = true
везде и установить пользовательские свойства шрифта определенных элементов управления во время выполнения в форме OnCreate
событие. Конечно, в этом случае вы проигрываете What You See Is What You Get
во время разработки, но вы получаете больший контроль над фактическим внешним видом ваших форм.
procedure TForm1.OnCreate(Sender: TObject);
begin
inherited;
Label1.Font.Style := [fsBold];
Label1.Font.Color := clRed;
end;
Для применения пользовательского выбора пользовательского шрифта вам также потребуется воссоздать формы или использовать ParentFont := true
перед применением пользовательских стилей для определенных элементов управления, чтобы они подобрали ваши новые настройки шрифта.
Одним из возможных способов было бы внедрить обработку post-parentfont
просто проверьте процедуру TControl.CMParentFontChanged
в VCL.Controls
единица измерения
Вы также должны сделать какой-то единый способ внедрения настроек шрифта в ваши элементы управления. Может быть, создание подкласса их WindowsProc или расширение стандартных элементов управления с интерфейсами, такими как EX-элементы управления в JediVCL
Основа - доказательство концепции, которую вряд ли можно воспроизвести так много, как есть - проблемы с обслуживанием - ниже.
unit xxx;
interface uses yyyy;
type
(*********** hijack start! ****)
TFontOverrideEvent = reference to procedure (const Sender: TObject; const Font: TFont);
TButton = class( VCL.StdCtrls.TButton )
protected
procedure ParentFontChanged(var m: TMessage); message CM_ParentFontChanged;
public
var FontOverrideEnabled: Boolean;
var OnFontOverride: TFontOverrideEvent;
end;
(**** hijack end! standard form declaration below ****)
TForm1 = class(TForm)
....
Button1: TButton;
...
procedure FormCreate(Sender: TObject);
...
implementation
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.OnFontOverride :=
procedure (const Sender: TObject; const LFont: TFont) begin
with LFont do Style := [fsBold] + Style;
end;
Button1.FontOverrideEnabled := true;
Button1.ParentFont := true;
PostMessage( Button1.Handle, CM_ParentFontChanged, 0, 0);
// trigger control to borrow font with customization
end;
....
(*** hijack implementation ***)
procedure TButton.ParentFontChanged(var m: TMessage);
var SilenceHim1: IChangeNotifier; SilenceHim2: TNotifyEvent;
begin
inherited;
// let VCL make standard font copying
// warning! it may also make AutoSize or other automatic re-layout!
// as we hide the fact of our font tuning from VCL - it would not
// have a chance to react to our customizations!
if FontOverrideEnabled and Assigned( OnFontOverride ) then
begin
SilenceHim2 := Font.OnChange;
SilenceHim1 := Font.FontAdapter;
try
Font.OnChange := nil;
Font.FontAdapter := nil;
OnFontOverride( Self, Font );
finally
Font.OnChange := SilenceHim2;
Font.FontAdapter := SilenceHim1;
end;
end;
end;
Затем попробуйте во время выполнения изменить From1.Font и посмотреть, как Button1
применяет изменения к себе
Я думаю, что самый простой способ достичь ваших целей - это не задавать свойства шрифта во время разработки. использование ParentFont = True
везде.
Затем во время выполнения внесите любые необходимые изменения. Это позволяет вам централизованно изменять шрифт, и в то же время остальная часть вашей программы его подбирает.