FontControl - harborsiem/WinForms-Ribbon GitHub Wiki

FontControl

The result of this post is a yet another sample, “12-FontControl”, found on the project site.

FontControl1

FontControl Control FontControl is another special control provided by the Windows Ribbon Framework. It allows you to choose font family, size, colors and related effects. It has three types, each exposing a little more functionality then the other:

  • Font Only

  • Font with Color

  • Rich Font

FontControl2

Check Font Control on MSDN for full details on the differences between the types.

FontControl Properties (with internal details) Following is the list of properties which are unique for FontControl control. The rest of the properties have been reviewed in previous posts.

  • FontProperties – This property is of type IPropertyStore and holds all the font specific properties, like Size, Bold, Underline, etc. In the FontControl helper class I use this property internally to access the other properties but do not expose it to the user, since it has no use other than being an access point to the other properties. Property Identifier: UI_PKEY_FontProperties

  • ChangedProperties – This property contains all the recently changed properties. The FontControl doesn’t expose it but provides it as one of the parameters in the FontChanged / Preview / CancelPreview events. For example, if you click on the “Bold” button, the FontChanged event will be called and the “this” property will contain only the Bold property. Property Identifier: UI_PKEY_FontProperties_ChangedProperties

  • Family – The selected font family name. Property Identifier: UI_PKEY_FontProperties_Family

  • Size – The size of the font. Property Identifier: UI_PKEY_FontProperties_Size

  • Bold – Flag that indicates whether bold is selected. Property Identifier: UI_PKEY_FontProperties_Bold

  • Italic – Flag that indicates whether italic is selected. Property Identifier: UI_PKEY_FontProperties_Italic

  • Underline – Flag that indicates whether underline is selected. Property Identifier: UI_PKEY_FontProperties_Underline

  • Strikethrough – Flag that indicates whether strikethrough is selected (sometimes called Strikeout). Property Identifier: UI_PKEY_FontProperties_Strikethrough

  • VerticalPositioning – Flag that indicates which one of the Subscript and Superscript buttons are selected, if any. Property Identifier: UI_PKEY_FontProperties_VerticalPositioning

  • ForegroundColor – Contains the text color if ForegroundColorType is set to RGB. The FontControl helper class expose this property as a .NET Color and handles internally the conversion to and from COLORREF structure. Property Identifier: UI_PKEY_FontProperties_ForegroundColor

  • ForegroundColorType – The text color type. Valid values are RGB and Automatic. If RGB is selected, the user should get the color from the ForegroundColor property. If Automatic is selected the user should use SystemColors.WindowText. The FontControl helper class doesn’t expose the ForegroundColorType property. Instead it implements the color selection algorithm internally (i.e. return correct color according to the type property). Property Identifier: UI_PKEY_FontProperties_ForegroundColorType

  • BackgroundColor – Contains the background color if BackgroundColorType is set to RGB. The FontControl helper class expose this property as a .NET Color and handles internally the conversion to and from COLORREF structure. Property Identifier: UI_PKEY_FontProperties_BackgroundColor

  • BackgroundColorType – The background color type. Valid values are RGB and NoColor. If RGB is selected, the user should get the color from the BackgroundColor property. If NoColor is selected the user should use SystemColors.Window. The FontControl helper class doesn’t expose the ForegroundColorType property. Instead it implements the color selection algorithm internally (i.e. return correct color according to the type property). Property Identifier: UI_PKEY_FontProperties_BackgroundColorType

  • DeltaSize – Indicated whether the “Grow Font” or “Shrink Font” buttons were pressed. This property is only available as part of the ChangedProperties property and is not exposed by the FontControl helper class. Property Identifier: UI_PKEY_FontProperties_DeltaSize

Using FontControl – Ribbon Markup

Commands and Views sections:

<?xml version=‘1.0‘ encoding=‘utf-8‘?>
<Application xmlns=‘http://schemas.microsoft.com/windows/2009/Ribbon‘>
    <Application.Commands>
    <Command Name=“cmdTabMain“ Id=“1001“ LabelTitle=“Main“ />
    <Command Name=“cmdGroupRichFont“ Id=“1002“ LabelTitle=“Rich Font“ />
    <Command Name=“cmdRichFont“ Id=“1003“ Keytip=“F“ />
  </Application.Commands>

    <Application.Views>
        <Ribbon>
      <Ribbon.Tabs>
        <Tab CommandName=“cmdTabMain“>
          <Group CommandName=“cmdGroupRichFont“ SizeDefinition=“OneFontControl“>
            <FontControl CommandName=“cmdRichFont“ FontType=“RichFont“ />
          </Group>
        </Tab>
      </Ribbon.Tabs>
    </Ribbon>
    </Application.Views>
</Application>

More details on FontControl attributes can be found on MSDN.

Using FontControl – Code Behind The following code shows the basic steps of using a ribbon FontControl which stays in sync with the selected text in a standard .NET RichTextBox control.


  • Initializing:
partial class RibbonItems
{
    //First write a text to the RichTextBox RichTextBox1 and mark it as selected.
    //Then you can see what happend with Preview, CancelPreview and Execute by the ribbon fontcontrol

    private Form1 _form;

    public void Init(Form1 form)
    {
        _form = form;
        RichFont.FontChanged += new EventHandler<FontControlEventArgs>(_richFont_ExecuteEvent);
        RichFont.Preview += new EventHandler<FontControlEventArgs>(_richFont_OnPreview);
        RichFont.CancelPreview += new EventHandler<FontControlEventArgs>(_richFont_OnCancelPreview);
    }
}

  • Setting RichTextBox properties when FontControl has changed:
void _richFont_ExecuteEvent(object sender, FontControlEventArgs e)
{
    ...

    // skip if selected font is not valid
    if ((RichFont.Family == null) ||
         (RichFont.Family.Trim() == string.Empty) ||
         (RichFont.Size == 0))
    {
        return;
    }

    // prepare font style
    FontStyle fontStyle = FontStyle.Regular;
    if (RichFont.Bold == FontProperties.Set)
    {
        fontStyle |= FontStyle.Bold;
    }
    if (RichFont.Italic == FontProperties.Set)
    {
        fontStyle |= FontStyle.Italic;
    }
    if (RichFont.Underline == FontUnderline.Set)
    {
        fontStyle |= FontStyle.Underline;
    }
    if (RichFont.Strikethrough == FontProperties.Set)
    {
        fontStyle |= FontStyle.Strikeout;
    }

    // set selected font
    // creating a new font can't fail if the font doesn't support the requested style
    // or if the font family name doesn't exist
    try
    {
        _form.RichTextBox1.SelectionFont = new Font(RichFont.Family, (float)RichFont.Size, fontStyle);
    }
    catch (ArgumentException)
    {
    }

    // set selected colors
    _form.RichTextBox1.SelectionColor = RichFont.ForegroundColor;
    _form.RichTextBox1.SelectionBackColor = RichFont.BackgroundColor;

    // set subscript / superscript
    switch (RichFont.VerticalPositioning)
    {
        case FontVerticalPosition.NotSet:
        case FontVerticalPosition.NotAvailable:
            _form.RichTextBox1.SelectionCharOffset = 0;
            break;

        case FontVerticalPosition.SuperScript:
            _form.RichTextBox1.SelectionCharOffset = 10;
            break;

        case FontVerticalPosition.SubScript:
            _form.RichTextBox1.SelectionCharOffset = -10;
            break;
    }
}

!Note: RichTextBox doesn’t support Subscript and Superscript natively. What it does support is setting the character offset, so this is what I use to simulate the required behavior.


  • Adding support for preview while changing font family and size:
void _richFont_OnPreview(object sender, FontControlEventArgs e)
{
    Dictionary<FontPropertiesEnum, object> dict = e.ChangedFontValues;
    FontPropertyStore store = e.CurrentFontStore;
    UpdateRichTextBox(dict);
    //UpdateRichTextBox(store);
}

void _richFont_OnCancelPreview(object sender, FontControlEventArgs e)
{
    Dictionary<FontPropertiesEnum, object> dict = e.ChangedFontValues;
    FontPropertyStore store = e.CurrentFontStore;
    //UpdateRichTextBox(dict);
    UpdateRichTextBox(store);
}

private void UpdateRichTextBox(Dictionary<FontPropertiesEnum, object> changedProps)
{
    string family = null;
    float? size = null;
    if (changedProps != null)
    {
        if (changedProps.ContainsKey(FontPropertiesEnum.Family))
            family = (string)changedProps[FontPropertiesEnum.Family];
        if (changedProps.ContainsKey(FontPropertiesEnum.Size))
            size = (float)(decimal)changedProps[FontPropertiesEnum.Size];
    }
    UpdateRichTextBox(family, size);
}

private void UpdateRichTextBox(FontPropertyStore propertyStore)
{
    UpdateRichTextBox(propertyStore.Family, (float)propertyStore.Size);
}

private void UpdateRichTextBox(string newFamily, float? newSize)
{
    FontStyle fontStyle;
    string family;
    float size;

    if (_form.RichTextBox1.SelectionFont != null)
    {
        fontStyle = _form.RichTextBox1.SelectionFont.Style;
        family = _form.RichTextBox1.SelectionFont.FontFamily.Name;
        size = _form.RichTextBox1.SelectionFont.Size;
    }
    else
    {
        fontStyle = FontStyle.Regular;
        family = string.Empty;
        size = 0;
    }
    if (newFamily != null)
        family = newFamily;
    if (newSize != null)
        size = (float)newSize;

    // creating a new font can't fail if the font doesn't support the requested style
    // or if the font family name doesn't exist
    try
    {
        _form.RichTextBox1.SelectionFont = new Font(family, size, fontStyle);
    }
    catch (ArgumentException)
    {
    }
}

!Note:
Only font family and font size should support preview since only they have attached combo boxes.


  • Updating FontControl when text selection changes in RichTextBox:
internal void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
    // update font control font
    if (_form.RichTextBox1.SelectionFont != null)
    {
        RichFont.Family = _form.RichTextBox1.SelectionFont.FontFamily.Name;
        RichFont.Size = (decimal)_form.RichTextBox1.SelectionFont.Size;
        RichFont.Bold = _form.RichTextBox1.SelectionFont.Bold ? FontProperties.Set : FontProperties.NotSet;
        RichFont.Italic = _form.RichTextBox1.SelectionFont.Italic ? FontProperties.Set : FontProperties.NotSet;
        RichFont.Underline = _form.RichTextBox1.SelectionFont.Underline ? FontUnderline.Set : FontUnderline.NotSet;
        RichFont.Strikethrough = _form.RichTextBox1.SelectionFont.Strikeout ? FontProperties.Set : FontProperties.NotSet;
    }
    else
    {
        RichFont.Family = string.Empty;
        RichFont.Size = 0;
        RichFont.Bold = FontProperties.NotAvailable;
        RichFont.Italic = FontProperties.NotAvailable;
        RichFont.Underline = FontUnderline.NotAvailable;
        RichFont.Strikethrough = FontProperties.NotAvailable;
    }

    // update font control colors
    RichFont.ForegroundColor = _form.RichTextBox1.SelectionColor;
    RichFont.BackgroundColor = _form.RichTextBox1.SelectionBackColor;

    // update font control vertical positioning
    switch (_form.RichTextBox1.SelectionCharOffset)
    {
        case 0:
            RichFont.VerticalPositioning = FontVerticalPosition.NotSet;
            break;

        case 10:
            RichFont.VerticalPositioning = FontVerticalPosition.SuperScript;
            break;

        case -10:
            RichFont.VerticalPositioning = FontVerticalPosition.SubScript;
            break;
    }
}
⚠️ **GitHub.com Fallback** ⚠️