-
Notifications
You must be signed in to change notification settings - Fork 18
FontControl
Windows Ribbon for WinForms library now supports FontControl control. The result of this post is a yet another sample, “12-FontControl”, found on the project site.

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

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 Execute / Preview / CancelPreview events. For example, if you click on the “Bold” button, the Execute 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:
private Ribbon _ribbon;
private RibbonFontControl _richFont;
public Form1()
{
InitializeComponent();
_ribbon = new Ribbon();
_richFont = new RibbonFontControl(_ribbon, (uint)RibbonMarkupCommands.cmdRichFont);
_richFont.ExecuteEvent += new EventHandler<ExecuteEventArgs>(_richFont_ExecuteEvent);
_richFont.PreviewEvent += new EventHandler<ExecuteEventArgs>(_richFont_OnPreview);
_richFont.CancelPreviewEvent += new EventHandler<ExecuteEventArgs>(_richFont_OnCancelPreview);
}- Setting RichTextBox properties when FontControl has changed:
void _richFont_ExecuteEvent(object sender, ExecuteEventArgs e)
{
FontControlEventArgs args = FontControlEventArgs.Create(sender, 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
richTextBox1.SelectionFont =
new Font(_richFont.Family, (float)_richFont.Size, fontStyle);
// set selected colors
richTextBox1.SelectionColor = _richFont.ForegroundColor;
richTextBox1.SelectionBackColor = _richFont.BackgroundColor;
// set subscript / superscript
switch (_richFont.VerticalPositioning)
{
case FontVerticalPosition.NotSet:
richTextBox1.SelectionCharOffset = 0;
break;
case FontVerticalPosition.SuperScript:
richTextBox1.SelectionCharOffset = 10;
break;
case FontVerticalPosition.SubScript:
richTextBox1.SelectionCharOffset = -10;
break;
}
}Older code:
void _richFont_ExecuteEvent(object sender, ExecuteEventArgs 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
richTextBox1.SelectionFont =
new Font(_richFont.Family, (float)_richFont.Size, fontStyle);
// set selected colors
richTextBox1.SelectionColor = _richFont.ForegroundColor;
richTextBox1.SelectionBackColor = _richFont.BackgroundColor;
// set subscript / superscript
switch (_richFont.VerticalPositioning)
{
case FontVerticalPosition.NotSet:
richTextBox1.SelectionCharOffset = 0;
break;
case FontVerticalPosition.SuperScript:
richTextBox1.SelectionCharOffset = 10;
break;
case FontVerticalPosition.SubScript:
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, ExecuteEventArgs e)
{
FontControlEventArgs args = FontControlEventArgs.Create(sender, e);
Dictionary<FontPropertiesEnum, object> dict = args.ChangedFontValues;
FontPropertyStore store = args.CurrentFontStore;
UpdateRichTextBox(dict);
}
void _richFont_OnCancelPreview(object sender, ExecuteEventArgs e)
{
FontControlEventArgs args = FontControlEventArgs.Create(sender, e);
Dictionary<FontPropertiesEnum, object> dict = args.ChangedFontValues;
FontPropertyStore store = args.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)
{
}
}Older code:
void _richFont_OnPreview(object sender, ExecuteEventArgs e)
{
PropVariant propChangesProperties;
e.CommandExecutionProperties.GetValue(ref RibbonProperties.FontProperties_ChangedProperties, out propChangesProperties);
IPropertyStore changedProperties = (IPropertyStore)propChangesProperties.Value;
UpdateRichTextBox(changedProperties);
}
void _richFont_OnCancelPreview(object sender, ExecuteEventArgs e)
{
IPropertyStore fontProperties = (IPropertyStore)e.CurrentValue.PropVariant.Value;
UpdateRichTextBox(fontProperties);
}
private void UpdateRichTextBox(IPropertyStore propertyStore)
{
RibbonLib.FontPropertyStore fontPropertyStore = new RibbonLib.FontPropertyStore(propertyStore);
PropVariant propValue;
FontStyle fontStyle = richTextBox1.SelectionFont.Style;
string family = richTextBox1.SelectionFont.FontFamily.Name;
float size = richTextBox1.SelectionFont.Size;
if (propertyStore.GetValue(ref RibbonProperties.FontProperties_Family, out propValue) == HRESULT.S_OK)
{
family = fontPropertyStore.Family;
}
if (propertyStore.GetValue(ref RibbonProperties.FontProperties_Size, out propValue) == HRESULT.S_OK)
{
size = (float)fontPropertyStore.Size;
}
richTextBox1.SelectionFont = new Font(family, size, fontStyle);
}!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:
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
// update font control font
if (richTextBox1.SelectionFont != null)
{
_richFont.Family = richTextBox1.SelectionFont.FontFamily.Name;
_richFont.Size = (decimal)richTextBox1.SelectionFont.Size;
_richFont.Bold = richTextBox1.SelectionFont.Bold ?
FontProperties.Set : FontProperties.NotSet;
_richFont.Italic = richTextBox1.SelectionFont.Italic ?
FontProperties.Set : FontProperties.NotSet;
_richFont.Underline = richTextBox1.SelectionFont.Underline ?
FontUnderline.Set : FontUnderline.NotSet;
_richFont.Strikethrough = 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 = richTextBox1.SelectionColor;
_richFont.BackgroundColor = richTextBox1.SelectionBackColor;
// update font control vertical positioning
switch (richTextBox1.SelectionCharOffset)
{
case 0:
_richFont.VerticalPositioning = FontVerticalPosition.NotSet;
break;
case 10:
_richFont.VerticalPositioning = FontVerticalPosition.SuperScript;
break;
case -10:
_richFont.VerticalPositioning = FontVerticalPosition.SubScript;
break;
}
}-
Basics
- Introduction, Background on the windows ribbon
- Basic Ribbon Wrapper Basic .NET wrappers for windows ribbon.
- Quickstart Tutorial
- First WinForms Ribbon Application How to create an empty WinForms application with ribbon support.
-
Working with Ribbon Controls
- Application Menu with Buttons How to use the ribbon application menu.
- Application Menu with SplitButton and DropDownButton How to use the ribbon application menu with ribbon split button and ribbon dropdown button controls.
- Tabs, Groups and HelpButton How to use ribbon tabs, groups and the ribbon help button control.
- Spinner How to use the ribbon spinner control.
- ComboBox How to use the ribbon combo box control.
- DropDownGallery, SplitButtonGallery and InRibbonGallery How to use the ribbon drop down gallery, split button gallery and in ribbon gallery controls.
- CheckBox and ToggleButton How to use the ribbon check box and toggle button controls.
- DropDownColorPicker How to use the ribbon drop down color picker control.
- FontControl How to use the ribbon font control.
- ContextualTabs How to work with ribbon contextual tabs.
- ContextPopup How to work with ribbon context popup.
- RecentItems How to work with ribbon recent items control.
- QuickAccessToolbar How to work with the ribbon quick access toolbar.
- The Ribbon Class How to work with the ribbon class. Methods, Properties, Events
- EventLogger Since Windows 8: Logging ribbon events
- UICollectionChangedEvent How to work with the ChangedEvent in an IUICollection
-
Working with miscellany Ribbon features
- ApplicationModes How to work with ribbon application modes.
- SizeDefinition How to define custom size definitions for ribbon group elements.
- Localization How to localize a ribbon.
- Changing Ribbon Colors How to change the ribbon colors.
- Working with Images How to work with images in the ribbon.
- Use Ribbon as External DLL How to load ribbon resources from external DLLs.
- Wrapper class RibbonItems An auto generated wrapper class from the ribbon markup.
-
Designing, building, previewing Windows Ribbon with RibbonTools
- RibbonTools basics Settings, Command line, ...
- Create a new project Create a WordPad sample project
- Preview the Ribbon
- Specifying Ribbon Commands
- Designing Ribbon Views
- Convert Images to Alpha Bitmaps
-
Modeling Guidelines
-
How to ...