如何为自定义控件从资源中设置自定义字体?
Hi Arulpriya, let's walk through why your custom control's font isn't updating when using AddMemoryFont, and fix it step by step!
Common Missing Steps & Fixes
1. Ensure You're Creating a Font Instance from the Loaded Memory Font
Calling AddMemoryFont only loads the font into the control's private font collection—it doesn't automatically set the control's font. You need to explicitly create a Font object using the loaded font family and assign it to your control's Font property.
Example code for loading and assigning:
protected override void OnCreateControl() { base.OnCreateControl(); // Load font bytes from resources byte[] fontResource = Properties.Resources.YourCustomFont; // Add to control's memory font collection IntPtr fontHandle = AddMemoryFont(fontResource, fontResource.Length); // Create a FontFamily from the loaded font handle FontFamily customFontFamily = FontFamily.FromHfont(fontHandle); // Assign a new Font instance to the control's Font property this.Font = new Font(customFontFamily, 10f, FontStyle.Regular); }
2. Verify Your Font Property Override Triggers Redraws
When overriding the Font property, make sure you're not just calling the base setter—you need to trigger a control redraw to reflect the new font. Add Invalidate() to force the control to repaint with the updated font.
Example property override:
private Font _controlFont; public override Font Font { get => _controlFont ?? base.Font; set { if (_controlFont != value) { _controlFont = value; // Update the base font base.Font = value; // Force the control to redraw with the new font Invalidate(); // Explicitly trigger FontChanged if needed OnFontChanged(EventArgs.Empty); } } }
3. Check Your OnPaint Logic Uses the Current Font
If you've overridden OnPaint, double-check that you're using this.Font (not a hardcoded font) when drawing text. A common mistake is referencing a static font object instead of the control's dynamic Font property.
Correct OnPaint example:
protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // Use the control's current Font for drawing e.Graphics.DrawString("Custom Text", this.Font, Brushes.Black, new Point(10, 10)); }
4. Re-Load Memory Fonts After Deserialization
Serialization typically only saves font metadata (name, size, style)—not the raw font bytes. After deserialization, you'll need to re-load the memory font from resources and re-assign it to the Font property.
Add this logic to your control's deserialization handler:
protected override void OnDeserialization(object sender) { base.OnDeserialization(sender); // Re-load and assign the memory font here byte[] fontResource = Properties.Resources.YourCustomFont; IntPtr fontHandle = AddMemoryFont(fontResource, fontResource.Length); FontFamily customFontFamily = FontFamily.FromHfont(fontHandle); this.Font = new Font(customFontFamily, this.Font.Size, this.Font.Style); }
5. Validate the Memory Font Loaded Successfully
Sometimes AddMemoryFont can fail silently (e.g., invalid font bytes). Add a check to ensure the FontFamily is valid before assigning:
FontFamily customFontFamily = FontFamily.FromHfont(fontHandle); if (customFontFamily.IsStyleAvailable(FontStyle.Regular)) { this.Font = new Font(customFontFamily, 10f, FontStyle.Regular); } else { // Fallback to default font if loading failed this.Font = SystemFonts.DefaultFont; }
Final Notes
- Avoid calling
AddMemoryFontmultiple times for the same font (it can cause memory leaks). Add a check to load it only once (e.g., inOnCreateControlwith a boolean flag). - Ensure your
FontChangedevent override properly callsbase.OnFontChanged(e)to preserve base class behavior.
内容的提问来源于stack exchange,提问作者Arulpriya

