Как эффективно позволить дочернему элементу управления `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 везде.

Затем во время выполнения внесите любые необходимые изменения. Это позволяет вам централизованно изменять шрифт, и в то же время остальная часть вашей программы его подбирает.

Другие вопросы по тегам