using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; namespace DiabloInterface.Gui.Controls { public class FontComboBox : ComboBox { Dictionary<string, Font> fontCache = new Dictionary<string, Font>(); StringFormat stringFormat; int itemHeight; [Category("Appearance"), DefaultValue(12)] public int DropDownFontSize { get; set; } = 12; // Fonts are initialized only if not in designmode // instead of only DesignMode property @see http://stackoverflow.com/questions/1166226/detecting-design-mode-from-a-controls-constructor private bool IsInDesignMode { get { if (DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime) { return true; } // disposes handle automatically when leaving 'using' using (var process = Process.GetCurrentProcess()) { return process.ProcessName == "devenv"; } } } public FontComboBox() { Sorted = true; DrawMode = DrawMode.OwnerDrawVariable; stringFormat = new StringFormat(StringFormatFlags.NoWrap); stringFormat.Trimming = StringTrimming.EllipsisCharacter; stringFormat.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.None; stringFormat.Alignment = StringAlignment.Near; stringFormat.LineAlignment = StringAlignment.Center; CalculateItemHeight(); if (!IsInDesignMode) { PopulateFonts(); } } void PopulateFonts() { if (Items.Count != 0) return; foreach (FontFamily family in FontFamily.Families) { Items.Add(family.Name); } } void CalculateItemHeight() { using (Font font = new Font(Font.FontFamily, DropDownFontSize)) { var size = TextRenderer.MeasureText("yY", font); itemHeight = size.Height + 2; } } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { foreach (var font in fontCache.Values) { font.Dispose(); } fontCache.Clear(); if (stringFormat != null) { stringFormat.Dispose(); stringFormat = null; } } } Font GetDisplayFont(string family) { Font font; // Font already loaded into cache. if (fontCache.TryGetValue(family, out font)) { return font; } FontStyle[] styles = new FontStyle[] { FontStyle.Regular, FontStyle.Bold, FontStyle.Italic, FontStyle.Bold | FontStyle.Italic }; font = null; // Try to load one of the specified font styles. foreach (FontStyle style in styles) { font = GetDisplayFont(family, style); if (font != null) break; } // Failed to load any font styles, default to combobox font. if (font == null) { font = Font; } fontCache[family] = font; return font; } Font GetDisplayFont(string family, FontStyle style) { try { return new Font(family, DropDownFontSize, style); } catch (ArgumentException) { return null; } } protected override void OnMeasureItem(MeasureItemEventArgs e) { base.OnMeasureItem(e); e.ItemHeight = itemHeight; } protected override void OnDrawItem(DrawItemEventArgs e) { base.OnDrawItem(e); // Nothing to draw. if (e.Index < 0 || e.Index >= Items.Count) return; e.DrawBackground(); if ((e.State & DrawItemState.Focus) == DrawItemState.Focus) e.DrawFocusRectangle(); using (var brush = new SolidBrush(e.ForeColor)) { string fontFamily = Items[e.Index].ToString(); e.Graphics.DrawString(fontFamily, GetDisplayFont(fontFamily), brush, e.Bounds, stringFormat); } } } }