Archive Browser
Download Cyotek.Windows.Forms.FontDialog.zip version 1.0.0, last updated 24/08/2015 (531.00 KB)
Download- md5: c6446bb984067f8c06070622748afc4e
/* Cyotek FontDialog
* http://cyotek.com
* http://cyotek.com/blog/tag/fontdialog
*
* Copyright © 2015 Cyotek Ltd.
*
* Licensed under the MIT License. See LICENSE.txt for the full text.
*/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms646832(v=vs.85).aspx
namespace Cyotek.Windows.Forms
{
/// <summary>
/// Prompts the user to choose a font from among those installed on the local computer.
/// </summary>
/// <seealso cref="T:System.Windows.Forms.CommonDialog"/>
[DefaultEvent("Apply")]
[DefaultProperty("Font")]
[Description("Displays a dialog box that prompts the user to choose a font from those installed on the local computer.")]
public class FontDialog : CommonDialog
{
#region Fields
private Font _font;
private int _maxSize;
private int _minSize;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Cyotek.Windows.Forms.FontDialog"/> class.
/// </summary>
public FontDialog()
{
this.Reset();
}
#endregion
#region Events
/// <summary>
/// Occurs when the user clicks the <strong>Apply</strong> button in the font dialog box.
/// </summary>
[Description("Occurs when the user clicks the Apply button.")]
public event EventHandler Apply;
#endregion
#region Properties
/// <summary>
/// Gets or sets a value indicating whether the user can change the character set specified in the <strong>Script</strong> combo box to display a character set other than the one currently displayed.
/// </summary>
/// <value>
/// <strong>true</strong> if the user can change the character set specified in the <strong>Script</strong> combo box; otherwise, <strong>false</strong>. The default value is <strong>true</strong>.
/// </value>
[DefaultValue(true)]
[Category("Behavior")]
[Description("Controls whether the character set of the font can be changed.")]
public bool AllowScriptChange { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box allows graphics device interface (GDI) font simulations.
/// </summary>
/// <value>
/// <strong>true</strong> if font simulations are allowed; otherwise, <strong>false</strong>. The default value is <strong>true</strong>.
/// </value>
[DefaultValue(true)]
[Category("Behavior")]
[Description("Controls whether GDI font simulations are allowed.")]
public bool AllowSimulations { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box allows vector font selections.
/// </summary>
/// <value>
/// <strong>true</strong> if vector fonts are allowed; otherwise, <strong>false</strong>. The default value is <strong>true</strong>.
/// </value>
[DefaultValue(true)]
[Category("Behavior")]
[Description("Controls whether vector fonts can be selected.")]
public bool AllowVectorFonts { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box displays both vertical and horizontal fonts or only horizontal fonts.
/// </summary>
/// <value>
/// <strong>true</strong> if both vertical and horizontal fonts are allowed; otherwise, <strong>false</strong>. The default value is <strong>true</strong>.
/// </value>
[DefaultValue(true)]
[Category("Behavior")]
[Description("Controls whether vertical fonts can be selected.")]
public bool AllowVerticalFonts { get; set; }
/// <summary>
/// Gets or sets the selected font color.
/// </summary>
/// <value>
/// The color of the selected font. The default value is Black.
/// </value>
[DefaultValue(typeof(Color), "Black")]
[Category("Data")]
[Description("The color selected in the dialog box.")]
public Color Color { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box allows only the selection of fixed-pitch fonts.
/// </summary>
/// <value>
/// <strong>true</strong> if only fixed-pitch fonts can be selected; otherwise, <strong>false</strong>. The default value is <strong>false</strong>.
/// </value>
[DefaultValue(false)]
[Category("Behavior")]
[Description("Controls whether only fixed pitch fonts can be selected.")]
public bool FixedPitchOnly { get; set; }
/// <summary>
/// Gets or sets the selected font.
/// </summary>
/// <value>
/// The selected font.
/// </value>
[Category("Data")]
[Description("The font selected in the dialog box.")]
public Font Font
{
get
{
Font font;
float fontSize;
int minSize;
int maxSize;
font = _font ?? SystemFonts.DefaultFont;
fontSize = font.SizeInPoints;
// clamp the font to the minimum size if set
minSize = this.MinSize;
if (minSize > 0 && fontSize < minSize)
{
font = new Font(font.FontFamily, minSize, font.Style, GraphicsUnit.Point);
}
// clamp the font to the maximum size if set
maxSize = this.MaxSize;
if (maxSize > 0 && fontSize > maxSize)
{
font = new Font(font.FontFamily, maxSize, font.Style, GraphicsUnit.Point);
}
return font;
}
set { _font = value; }
}
/// <summary>
/// Gets or sets a value indicating whether the dialog box specifies an error condition if the user attempts to select a font or style that does not exist.
/// </summary>
/// <value>
/// <strong>true</strong> if the dialog box specifies an error condition when the user tries to select a font or style that does not exist; otherwise, <strong>false</strong>. The default is <strong>false</strong>.
/// </value>
[DefaultValue(false)]
[Category("Behavior")]
[Description("Controls whether to report an error if the selected font does not exist.")]
public bool FontMustExist { get; set; }
/// <summary>
/// Gets or sets the maximum point size a user can select.
/// </summary>
/// <value>
/// The maximum point size a user can select. The default is 0.
/// </value>
[DefaultValue(0)]
[Category("Data")]
[Description("The maximum point size that can be selected (or zero to disable).")]
public int MaxSize
{
get { return _maxSize; }
set
{
if (value < 0)
{
value = 0;
}
_maxSize = value;
if (_maxSize > 0 && _maxSize < _minSize)
{
_minSize = _maxSize;
}
}
}
/// <summary>
/// Gets or sets the minimum point size a user can select.
/// </summary>
/// <value>
/// The minimum point size a user can select. The default is 0.
/// </value>
[DefaultValue(0)]
[Category("Data")]
[Description("The minimum point size that can be Selected (or zero to disable).")]
public int MinSize
{
get { return _minSize; }
set
{
if (value < 0)
{
value = 0;
}
_minSize = value;
if (_maxSize > 0 && _maxSize < _minSize)
{
_maxSize = _minSize;
}
}
}
/// <summary>
/// Gets or sets a value indicating whether the dialog box allows selection of fonts for all non-OEM and Symbol character sets, as well as the ANSI character set.
/// </summary>
/// <value>
/// <strong>true</strong> if selection of fonts for all non-OEM and Symbol character sets, as well as the ANSI character set, is allowed; otherwise, <strong>false</strong>. The default value is <strong>false</strong>.
/// </value>
[DefaultValue(false)]
[Category("Behavior")]
[Description("Controls whether to exclude OEM and Symbol character sets.")]
public bool ScriptsOnly { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box contains an <strong>Apply</strong> button.
/// </summary>
/// <value>
/// <strong>true</strong> if the dialog box contains an <strong>Apply</strong> button; otherwise, <strong>false</strong>. The default value is <strong>false</strong>.
/// </value>
[DefaultValue(false)]
[Category("Behavior")]
[Description("Controls whether to show the Apply button.")]
public bool ShowApply { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box displays the color choice.
/// </summary>
/// <value>
/// <strong>true</strong> if the dialog box displays the color choice; otherwise, <strong>false</strong>. The default value is <strong>false</strong>.
/// </value>
[DefaultValue(false)]
[Category("Behavior")]
[Description("Controls whether to show a color choice.")]
public bool ShowColor { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box contains controls that allow the user to specify strikethrough, underline, and text color options.
/// </summary>
/// <value>
/// <strong>true</strong> if the dialog box contains controls to set strikethrough, underline, and text color options; otherwise, <strong>false</strong>. The default value is <strong>true</strong>.
/// </value>
[DefaultValue(true)]
[Category("Behavior")]
[Description("Controls whether to show the underline, strikeout, and font color selections.")]
public bool ShowEffects { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box displays a <strong>Help</strong> button.
/// </summary>
/// <value>
/// <strong>true</strong> if the dialog box displays a <strong>Help</strong> button; otherwise, <strong>false</strong>. The default value is <strong>false</strong>.
/// </value>
[DefaultValue(false)]
[Category("Behavior")]
[Description("Controls whether to show the Help button.")]
public bool ShowHelp { get; set; }
#endregion
#region Methods
/// <summary>
/// When overridden in a derived class, resets the properties of a common dialog box to their default values.
/// </summary>
public override void Reset()
{
this.Color = Color.Black;
this.AllowScriptChange = true;
this.AllowSimulations = true;
this.AllowVectorFonts = true;
this.AllowVerticalFonts = true;
this.ShowColor = false;
this.FontMustExist = false;
this.FixedPitchOnly = false;
this.MaxSize = 0;
this.MaxSize = 0;
this.Font = null;
this.ShowApply = false;
this.ShowHelp = false;
this.ShowEffects = true;
}
/// <summary>
/// Retrieves a string that includes the name of the current font selected in the dialog box.
/// </summary>
public override string ToString()
{
return string.Concat(base.ToString(), ", Font: ", this.Font.ToString());
}
/// <summary>
/// Defines the common dialog box hook procedure that is overridden to add specific functionality to a common dialog box.
/// </summary>
/// <returns>
/// A zero value if the default dialog box procedure processes the message; a nonzero value if the default dialog box procedure ignores the message.
/// </returns>
/// <param name="hWnd">The handle to the dialog box window. </param><param name="msg">The message being received. </param><param name="wparam">Additional information about the message. </param><param name="lparam">Additional information about the message. </param>
protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
{
// This code is lifted directly from System.Windows.Forms.FontDialog
switch (msg)
{
case NativeMethods.WM_COMMAND:
if ((int)wparam == 0x402)
{
NativeMethods.LOGFONT lf = new NativeMethods.LOGFONT();
NativeMethods.SendMessage(new HandleRef(null, hWnd), NativeMethods.WM_CHOOSEFONT_GETLOGFONT, 0, lf);
this.UpdateFont(lf);
int index = (int)NativeMethods.SendDlgItemMessage(new HandleRef(null, hWnd), 0x473, NativeMethods.CB_GETCURSEL, IntPtr.Zero, IntPtr.Zero);
if (index != NativeMethods.CB_ERR)
{
this.UpdateColor((int)NativeMethods.SendDlgItemMessage(new HandleRef(null, hWnd), 0x473, NativeMethods.CB_GETITEMDATA, (IntPtr)index, IntPtr.Zero));
}
try
{
this.OnApply(EventArgs.Empty);
}
catch (Exception e)
{
Application.OnThreadException(e);
}
}
break;
case NativeMethods.WM_INITDIALOG:
if (!this.ShowColor)
{
IntPtr hWndCtl = NativeMethods.GetDlgItem(new HandleRef(null, hWnd), NativeMethods.cmb4);
NativeMethods.ShowWindow(new HandleRef(null, hWndCtl), NativeMethods.SW_HIDE);
hWndCtl = NativeMethods.GetDlgItem(new HandleRef(null, hWnd), NativeMethods.stc4);
NativeMethods.ShowWindow(new HandleRef(null, hWndCtl), NativeMethods.SW_HIDE);
}
break;
}
return base.HookProc(hWnd, msg, wparam, lparam);
}
/// <summary>
/// Raises the <see cref="Apply" /> event.
/// </summary>
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
protected virtual void OnApply(EventArgs e)
{
EventHandler handler;
handler = this.Apply;
if (handler != null)
{
handler(this, e);
}
}
/// <summary>
/// When overridden in a derived class, specifies a common dialog box.
/// </summary>
/// <returns>
/// true if the dialog box was successfully run; otherwise, false.
/// </returns>
/// <param name="hwndOwner">A value that represents the window handle of the owner window for the common dialog box. </param>
protected override bool RunDialog(IntPtr hwndOwner)
{
NativeMethods.LOGFONT lf;
NativeMethods.CHOOSEFONT cf;
IntPtr plf;
bool result;
int minSize;
int maxSize;
bool showColor;
lf = new NativeMethods.LOGFONT();
this.Font.ToLogFont(lf);
plf = Marshal.AllocHGlobal(Marshal.SizeOf(lf));
Marshal.StructureToPtr(lf, plf, false);
showColor = this.ShowColor || this.ShowEffects;
cf = new NativeMethods.CHOOSEFONT();
cf.lStructSize = Marshal.SizeOf(typeof(NativeMethods.CHOOSEFONT));
cf.Flags = this.GetFlags();
cf.hwndOwner = hwndOwner;
cf.lpfnHook = this.HookProc;
minSize = this.MinSize;
maxSize = this.MaxSize;
if (minSize > 0 || maxSize > 0)
{
cf.nSizeMin = minSize;
cf.nSizeMax = maxSize > 0 ? maxSize : int.MaxValue;
}
cf.rgbColors = ColorTranslator.ToWin32(showColor ? this.Color : Color.Black);
cf.lpLogFont = plf;
try
{
result = NativeMethods.ChooseFont(ref cf);
if (result)
{
// create a managed font from the updated LOGFONT
lf = (NativeMethods.LOGFONT)Marshal.PtrToStructure(plf, typeof(NativeMethods.LOGFONT));
if (!string.IsNullOrEmpty(lf.lfFaceName))
{
this.UpdateFont(lf);
}
// and update the color
if (showColor)
{
this.UpdateColor(cf.rgbColors);
}
}
}
finally
{
// always be freein' allocated memory!
Marshal.FreeHGlobal(plf);
}
return result;
}
/// <summary>
/// Gets the flags to apply to the CHOOSEFONT structure
/// </summary>
private int GetFlags()
{
NativeMethods.CHOOSEFONTFLAGS flags;
flags = NativeMethods.CHOOSEFONTFLAGS.CF_INITTOLOGFONTSTRUCT | NativeMethods.CHOOSEFONTFLAGS.CF_TTONLY | NativeMethods.CHOOSEFONTFLAGS.CF_ENABLEHOOK;
if (this.ShowApply)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_APPLY;
}
if (this.ShowEffects)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_EFFECTS;
}
if (this.FixedPitchOnly)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_FIXEDPITCHONLY;
}
if (this.FontMustExist)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_FORCEFONTEXIST;
}
if (this.MinSize != 0 || this.MaxSize != 0)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_LIMITSIZE;
}
if (!this.AllowScriptChange)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_NOSCRIPTSEL;
}
if (!this.AllowSimulations)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_NOSIMULATIONS;
}
if (!this.AllowVectorFonts)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_NOVERTFONTS;
}
if (this.ScriptsOnly)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_SCRIPTSONLY;
;
}
if (this.ShowHelp)
{
flags |= NativeMethods.CHOOSEFONTFLAGS.CF_SHOWHELP;
}
return (int)flags;
}
/// <summary>
/// Resets the font.
/// </summary>
private void ResetFont()
{
this.Font = null;
}
/// <summary>
/// Determine if we should serialize font.
/// </summary>
/// <returns>
/// true if it succeeds, false if it fails.
/// </returns>
private bool ShouldSerializeFont()
{
return !this.Font.Equals(Control.DefaultFont);
}
/// <summary>
/// Updates the color
/// </summary>
/// <param name="rgb"> The OLE color value. </param>
private void UpdateColor(int rgb)
{
if (ColorTranslator.ToWin32(this.Color) != rgb)
{
this.Color = ColorTranslator.FromOle(rgb);
}
}
/// <summary>
/// Updates the font described by the specified LOGFONT structure
/// </summary>
/// <param name="lf"> The source font. </param>
private void UpdateFont(NativeMethods.LOGFONT lf)
{
Font font;
try
{
// This one line is the whole point of having to write this class as it can
// throw an exception, which System.Windows.Forms.FontDialog doesn't handle
font = Font.FromLogFont(lf);
}
catch
{
font = null;
}
if (font != null)
{
this.Font = font;
}
}
#endregion
}
}
Donate
This software may be used free of charge, but as with all free software there are costs involved to develop and maintain.
If this site or its services have saved you time, please consider a donation to help with running costs and timely updates.
Donate