为C#设计自定义字体对话框/选择器,过滤掉非真实类型的字体

由于内置字体对话框在选择非真实类型字体时返回“非真实类型字体”exception,我正在尝试使用字体系列创建自定义字体对话框,该字体系列会过滤掉非真实类型字体。

控件工作正常但我需要这个对话框的大小和样式选择器。 我发布了当前的代码。 请帮我添加尺寸和样式选择器。 它也可能对你有用。

public class FontListBox : ListBox { private List _fonts = new List(); private Brush _foreBrush; public FontListBox() { DrawMode = DrawMode.OwnerDrawFixed; ItemHeight = 20; foreach (FontFamily ff in FontFamily.Families) { // determine the first available style, as all fonts don't support all styles FontStyle? availableStyle = null; foreach (FontStyle style in Enum.GetValues(typeof(FontStyle))) { if (ff.IsStyleAvailable(style)) { availableStyle = style; break; } } if (availableStyle.HasValue) { Font font = null; try { // do your own Font initialization here // discard the one you don't like :-) font = new Font(ff, 12, availableStyle.Value); } catch { } if (font != null) { _fonts.Add(font); Items.Add(font); } } } } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (_fonts != null) { foreach (Font font in _fonts) { font.Dispose(); } _fonts = null; } if (_foreBrush != null) { _foreBrush.Dispose(); _foreBrush = null; } } public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; if (_foreBrush != null) { _foreBrush.Dispose(); } _foreBrush = null; } } private Brush ForeBrush { get { if (_foreBrush == null) { _foreBrush = new SolidBrush(ForeColor); } return _foreBrush; } } protected override void OnDrawItem(DrawItemEventArgs e) { base.OnDrawItem(e); if (e.Index < 0) return; e.DrawBackground(); e.DrawFocusRectangle(); Rectangle bounds = e.Bounds; Font font = (Font)Items[e.Index]; e.Graphics.DrawString(font.Name, font, ForeBrush, bounds.Left, bounds.Top); } } public partial class MyFontDialog : Form { private FontListBox _fontListBox; public MyFontDialog() { InitializeComponent(); _fontListBox = new FontListBox(); _fontListBox.Dock = DockStyle.Fill; Controls.Add(_fontListBox); } } 

我在sourceforge上托管了这个项目https://sourceforge.net/p/newfontpicker/

您可以像这样修改MyFontDialog:

 public partial class MyFontDialog : Form { private FontListBox _fontListBox; private ListBox _fontSizeListBox; public MyFontDialog() { //InitializeComponent(); _fontListBox = new FontListBox(); _fontListBox.SelectedIndexChanged += OnfontListBoxSelectedIndexChanged; _fontListBox.Size = new Size(200, Height); Controls.Add(_fontListBox); _fontSizeListBox = new ListBox(); _fontSizeListBox.Location = new Point(_fontListBox.Width, 0); Controls.Add(_fontSizeListBox); } private void OnfontListBoxSelectedIndexChanged(object sender, EventArgs e) { _fontSizeListBox.Items.Clear(); Font font = _fontListBox.SelectedItem as Font; if (font != null) { foreach (FontStyle style in Enum.GetValues(typeof(FontStyle))) { if (font.FontFamily.IsStyleAvailable(style)) { _fontSizeListBox.Items.Add(style); } } } } } 

它将在字体列表框旁边创建一个列表框,其中包含可用字体样式列表。 至于尺寸选择,您只需添加一个带有硬编码列表的列表框:8,9,10,11,12,14,16,18,20,22,24,26,28,36,48和72就像标准的FontDialog一样,因为我们处理的是真正的字体。

http://www.developerfusion.com/code/254/determine-if-a-font-is-truetype/有一些VB代码来确定字体是否是TT字体。 所有它真正做的是调用一些Win32 API函数并检查结果。

可能有一些字体似乎是TT但不是,即使使用Win32 API(FontDialog可能正在进行)进行检查时也是如此。 如果Win32无法解决您的问题,那么查找字体无效的唯一方法就是检查exception。

好的,奥马尔,你应该试试:

1)使用’FontFamily.IsStyleAvailable’来避免/最小化捕获exception的需要 – 从而错过一些可用的字体。 2)使用Graphics.MeasureString播放一些内容,为每个看起来最好的单个字体设置大小,并为您提供相同高度的列…

快乐的尝试:)

丹麦延斯。