3

Delphi XE7 provides the "Bitmap Style Designer" tool ('Tools > Bitmap Style Designer') which can be used to edit and create styles for your metro themed applications. Changing graphics and colors for buttons, checkboxes and labels works and looks pretty fly. But how can I change the Font Settings? To be more precise: What can I do to let the font settings take effect on my application?

Of course there's a Fonts-Section where custom font-styles, -families, -sizes and so on can be edited, but those setting have no impact. But I can successfully change the color of a control there.

The Bitmap Style Designer also supports a Preview mode. This displays a window with the customized controls. Even there no custom fonts are used. For this window I am not able to apply any settings like ParentFont := True or StyleElements := StyleElements + [seFont].

But I can change those properties in my own application where I apply the custom style. Unfortunately the result stays the same.

best regards

Florian Grummel
  • 332
  • 3
  • 14
  • It's not clear from your question: have you only tried to address fonts in the Bitmap Style Designer, or have you created a resource with styles in and tried to apply one of those styles to a control within your application? (e.g. where such a style can be edited in a normal text editor) – Alnitak Jan 27 '15 at 12:05
  • I modified the MetropolisUIBlack.vsf Style and defined it in the project settings afterwards I recompiled the Application. The problem is that the fonts are not even considered in the Demo-Form. – Florian Grummel Jan 27 '15 at 12:29
  • Did you apply the style? (recompiling does not apply the style, though you might think it). Did you try seeing whether anything else in your .vsf style is coming through? (i.e. is it the fonts alone that are getting ignored, or is everything else in your style file getting ignored too?) – Alnitak Jan 27 '15 at 16:32
  • I apply the style by using`TStyleManager.TrySetStyle(cStyle);` in my dpr-File. And how I've mentioned before all controls are styled as I want them to be in my vsf-Style. The fonts (family, size, color) are the only things that are not applied. – Florian Grummel Jan 28 '15 at 09:08

1 Answers1

3

Vcl Styles currently do not read and apply full font data from custom style, only color.

However with some hacking you can access complete font information in custom style, but you will have to apply fonts to controls manually, or you can use ParentFont property of form.

With following code you can access fonts stored in custom styles (tested in XE4, but basic idea can be applied to other Delphi versions, if there are some differences)

unit StyleFonts;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Classes,
  System.Types,
  System.UITypes,
  System.Zlib,
  Vcl.Consts,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.ImgList,
  Vcl.GraphUtil,
  Vcl.Styles,
  Vcl.Themes;

function GetStyleFont(Font: TStyleFont): TFont;

implementation

// use files from source\vcl
{$I StyleUtils.inc}
{$I StyleAPI.inc}

var
  SystemFont: TFont;

procedure InitializeSystemFont;
var
  NonClientMetrics: TNonClientMetrics;
begin
  SystemFont := TFont.Create;
  FillChar(NonClientMetrics, SizeOf(NonClientMetrics), 0);
  // following function will fill up cbSize with correct size for XP system
  NonClientMetrics.cbSize := TNonClientMetrics.SizeOf;
  if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0) then
    SystemFont.Handle := CreateFontIndirect(NonClientMetrics.lfMessageFont)
end;

type
  TStyleHelper = class helper for TCustomStyle
  public
    function GetSource: TObject; { TseSkin }
  end;

function TStyleHelper.GetSource: TObject;
begin
  Result := Self.FSource;
end;

function GetStyleFont(Font: TStyleFont): TFont;
var
  LStyle: TCustomStyle;
  FSource: TObject;
  SeFont: TSeStyleFont;
begin
  if TStyleManager.IsCustomStyleActive then
    begin
      LStyle := TCustomStyle(TStyleManager.ActiveStyle);
      FSource := LStyle.GetSource;
      // case based on Vcl.Styles TCustomStyle.DoGetStyleFontColor
      case Font of
        sfButtonTextDisabled: Result := TSeStyle(FSource).Fonts[ktfButtonTextDisabled];
        sfButtonTextFocused: Result := TSeStyle(FSource).Fonts[ktfButtonTextFocused];
        sfButtonTextHot: Result := TSeStyle(FSource).Fonts[ktfButtonTextHot];
        sfButtonTextNormal: Result := TSeStyle(FSource).Fonts[ktfButtonTextNormal];
        sfButtonTextPressed: Result := TSeStyle(FSource).Fonts[ktfButtonTextPressed];
        sfCaptionTextInactive: Result := TSeStyle(FSource).Fonts[ktfCaptionTextInactive];
        sfCaptionTextNormal: Result := TSeStyle(FSource).Fonts[ktfCaptionTextNormal];
        sfCategoryPanelGroupHeaderHot: Result := TSeStyle(FSource).Fonts[ktfCategoryPanelGroupHeaderHot];
        sfCategoryPanelGroupHeaderNormal: Result := TSeStyle(FSource).Fonts[ktfCategoryPanelGroupHeaderNormal];
        sfCatgeoryButtonsCategoryNormal: Result := TSeStyle(FSource).Fonts[ktfCatgeoryButtonsCategoryNormal];
        sfCatgeoryButtonsCategorySelected: Result := TSeStyle(FSource).Fonts[ktfCatgeoryButtonsCategorySelected];
        sfCatgeoryButtonsHot: Result := TSeStyle(FSource).Fonts[ktfCatgeoryButtonsHot];
        sfCatgeoryButtonsNormal: Result := TSeStyle(FSource).Fonts[ktfCatgeoryButtonsNormal];
        sfCatgeoryButtonsSelected: Result := TSeStyle(FSource).Fonts[ktfCatgeoryButtonsSelected];
        sfCheckBoxTextDisabled: Result := TSeStyle(FSource).Fonts[ktfCheckBoxTextDisabled];
        sfCheckBoxTextFocused: Result := TSeStyle(FSource).Fonts[ktfCheckBoxTextFocused];
        sfCheckBoxTextHot: Result := TSeStyle(FSource).Fonts[ktfCheckBoxTextHot];
        sfCheckBoxTextNormal: Result := TSeStyle(FSource).Fonts[ktfCheckBoxTextNormal];
        sfCheckBoxTextPressed: Result := TSeStyle(FSource).Fonts[ktfCheckBoxTextPressed];
        sfComboBoxItemDisabled: Result := TSeStyle(FSource).Fonts[ktfComboBoxItemDisabled];
        sfComboBoxItemFocused: Result := TSeStyle(FSource).Fonts[ktfComboBoxItemFocused];
        sfComboBoxItemHot: Result := TSeStyle(FSource).Fonts[ktfComboBoxItemHot];
        sfComboBoxItemNormal: Result := TSeStyle(FSource).Fonts[ktfComboBoxItemNormal];
        sfComboBoxItemSelected: Result := TSeStyle(FSource).Fonts[ktfComboBoxItemSelected];
        sfEditBoxTextDisabled: Result := TSeStyle(FSource).Fonts[ktfEditBoxTextDisabled];
        sfEditBoxTextFocused: Result := TSeStyle(FSource).Fonts[ktfEditBoxTextFocused];
        sfEditBoxTextHot: Result := TSeStyle(FSource).Fonts[ktfEditBoxTextHot];
        sfEditBoxTextNormal: Result := TSeStyle(FSource).Fonts[ktfEditBoxTextNormal];
        sfEditBoxTextSelected: Result := TSeStyle(FSource).Fonts[ktfEditBoxTextSelected];
        sfGridItemFixedHot: Result := TSeStyle(FSource).Fonts[ktfGridItemFixedHot];
        sfGridItemFixedNormal: Result := TSeStyle(FSource).Fonts[ktfGridItemFixedNormal];
        sfGridItemFixedPressed: Result := TSeStyle(FSource).Fonts[ktfGridItemFixedPressed];
        sfGridItemNormal: Result := TSeStyle(FSource).Fonts[ktfGridItemNormal];
        sfGridItemSelected: Result := TSeStyle(FSource).Fonts[ktfGridItemSelected];
        sfGroupBoxTextDisabled: Result := TSeStyle(FSource).Fonts[ktfGroupBoxTextDisabled];
        sfGroupBoxTextNormal: Result := TSeStyle(FSource).Fonts[ktfGroupBoxTextNormal];
        sfHeaderSectionTextDisabled: Result := TSeStyle(FSource).Fonts[ktfHeaderSectionTextDisabled];
        sfHeaderSectionTextHot: Result := TSeStyle(FSource).Fonts[ktfHeaderSectionTextHot];
        sfHeaderSectionTextNormal: Result := TSeStyle(FSource).Fonts[ktfHeaderSectionTextNormal];
        sfHeaderSectionTextPressed: Result := TSeStyle(FSource).Fonts[ktfHeaderSectionTextPressed];
        sfListItemTextDisabled: Result := TSeStyle(FSource).Fonts[ktfListItemTextDisabled];
        sfListItemTextFocused: Result := TSeStyle(FSource).Fonts[ktfListItemTextFocused];
        sfListItemTextHot: Result := TSeStyle(FSource).Fonts[ktfListItemTextHot];
        sfListItemTextNormal: Result := TSeStyle(FSource).Fonts[ktfListItemTextNormal];
        sfListItemTextSelected: Result := TSeStyle(FSource).Fonts[ktfListItemTextSelected];
        sfMenuItemTextDisabled: Result := TSeStyle(FSource).Fonts[ktfMenuItemTextDisabled];
        sfMenuItemTextHot: Result := TSeStyle(FSource).Fonts[ktfMenuItemTextHot];
        sfMenuItemTextNormal: Result := TSeStyle(FSource).Fonts[ktfMenuItemTextNormal];
        sfMenuItemTextSelected: Result := TSeStyle(FSource).Fonts[ktfMenuItemTextSelected];
        sfPanelTextDisabled: Result := TSeStyle(FSource).Fonts[ktfPanelTextDisabled];
        sfPanelTextNormal: Result := TSeStyle(FSource).Fonts[ktfPanelTextNormal];
        sfPopupMenuItemTextDisabled: Result := TSeStyle(FSource).Fonts[ktfPopupMenuItemTextDisabled];
        sfPopupMenuItemTextHot: Result := TSeStyle(FSource).Fonts[ktfPopupMenuItemTextHot];
        sfPopupMenuItemTextNormal: Result := TSeStyle(FSource).Fonts[ktfPopupMenuItemTextNormal];
        sfPopupMenuItemTextSelected: Result := TSeStyle(FSource).Fonts[ktfPopupMenuItemTextSelected];
        sfRadioButtonTextDisabled: Result := TSeStyle(FSource).Fonts[ktfRadioButtonTextDisabled];
        sfRadioButtonTextFocused: Result := TSeStyle(FSource).Fonts[ktfRadioButtonTextFocused];
        sfRadioButtonTextHot: Result := TSeStyle(FSource).Fonts[ktfRadioButtonTextHot];
        sfRadioButtonTextNormal: Result := TSeStyle(FSource).Fonts[ktfRadioButtonTextNormal];
        sfRadioButtonTextPressed: Result := TSeStyle(FSource).Fonts[ktfRadioButtonTextPressed];
        sfSmCaptionTextInactive: Result := TSeStyle(FSource).Fonts[ktfSmCaptionTextInactive];
        sfSmCaptionTextNormal: Result := TSeStyle(FSource).Fonts[ktfSmCaptionTextNormal];
        sfStatusPanelTextDisabled: Result := TSeStyle(FSource).Fonts[ktfStatusPanelTextDisabled];
        sfStatusPanelTextNormal: Result := TSeStyle(FSource).Fonts[ktfStatusPanelTextNormal];
        sfTabTextActiveDisabled: Result := TSeStyle(FSource).Fonts[ktfTabTextActiveDisabled];
        sfTabTextActiveHot: Result := TSeStyle(FSource).Fonts[ktfTabTextActiveHot];
        sfTabTextActiveNormal: Result := TSeStyle(FSource).Fonts[ktfTabTextActiveNormal];
        sfTabTextInactiveDisabled: Result := TSeStyle(FSource).Fonts[ktfTabTextInactiveDisabled];
        sfTabTextInactiveHot: Result := TSeStyle(FSource).Fonts[ktfTabTextInactiveHot];
        sfTabTextInactiveNormal: Result := TSeStyle(FSource).Fonts[ktfTabTextInactiveNormal];
        sfTextLabelDisabled: Result := TSeStyle(FSource).Fonts[ktfStaticTextDisabled];
        sfTextLabelFocused: Result := TSeStyle(FSource).Fonts[ktfStaticTextFocused];
        sfTextLabelHot: Result := TSeStyle(FSource).Fonts[ktfStaticTextHot];
        sfTextLabelNormal: Result := TSeStyle(FSource).Fonts[ktfStaticTextNormal];
        sfToolItemTextDisabled: Result := TSeStyle(FSource).Fonts[ktfToolItemTextDisabled];
        sfToolItemTextHot: Result := TSeStyle(FSource).Fonts[ktfToolItemTextHot];
        sfToolItemTextNormal: Result := TSeStyle(FSource).Fonts[ktfToolItemTextNormal];
        sfToolItemTextSelected: Result := TSeStyle(FSource).Fonts[ktfToolItemTextSelected];
        sfTreeItemTextDisabled: Result := TSeStyle(FSource).Fonts[ktfTreeItemTextDisabled];
        sfTreeItemTextFocused: Result := TSeStyle(FSource).Fonts[ktfTreeItemTextFocused];
        sfTreeItemTextHot: Result := TSeStyle(FSource).Fonts[ktfTreeItemTextHot];
        sfTreeItemTextNormal: Result := TSeStyle(FSource).Fonts[ktfTreeItemTextNormal];
        sfTreeItemTextSelected: Result := TSeStyle(FSource).Fonts[ktfTreeItemTextSelected];
        sfWindowTextDisabled: Result := TSeStyle(FSource).Fonts[ktfWindowTextDisabled];
        sfWindowTextNormal: Result := TSeStyle(FSource).Fonts[ktfWindowTextNormal];
        else Result := SystemFont;
      end;
    end
  else Result := SystemFont;
end;

initialization

  InitializeSystemFont;

finalization

  SystemFont.Free;

end.
Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
  • Thanks for your answer, Dalija. Indeed this works pretty well to configure something like a default font for the application by defining it in MainForm and style each child control by activating the `ParentFont` property. Unfortunately the're might be no easy way to style the context or application menus of an app. – Florian Grummel Jan 28 '15 at 16:15
  • 1
    You can use `Screen` properties `HintFont`, `IconFont`, `MenuFont`, `MessageFont` and `CaptionFont` to change other app fonts appearance – Dalija Prasnikar Jan 29 '15 at 09:44
  • Thank you! This works for my TPopUpMenus. Perhaps one should additionally mention that it's necessary to set the property `OwnerDraw := True` to let the `Screen.MenuFont` property take effect. By changing the font size, the height of the MenuItems is not properly derived. This problem can be resolved by using the `OnMeasureItem`-Event of TMenuItem. – Florian Grummel Jan 30 '15 at 08:58
  • 2
    @DalijaPrasnikar I created a QC request for people to vote for if they don't like these hacks: https://quality.embarcadero.com/browse/RSP-13517 - feel free to update your answer with this link. – James Johnston Jan 21 '16 at 22:44
  • @JamesJohnston Thank you for the report, voted. I think that having link to the QP report in comment would suffice. You may also post it at [Delphi Developers G+](https://plus.google.com/communities/103113685381486591754) for more visibility. There it will attract more attention and votes than being buried here. – Dalija Prasnikar Jan 22 '16 at 09:47