You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForm RichTextBox方框绘制字符字体被替换问题求助

问题

在Windows窗体的RichTextBox控件中,已将字体设置为Consolas等宽字体,大部分内容可正常渲染,但加载或设置包含**方框绘制字符(Box-drawing characters)**的内容时,这类字符会被自动替换为Segoe UI Symbol字体,破坏了等宽排版效果。

示例代码:

private void InitializeComponent()
{
    // ...
    this.richTextBox1 = new System.Windows.Forms.RichTextBox();
    this.richTextBox1.Font =
       new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular,
                               System.Drawing.GraphicsUnit.Point, ((byte)(0)));
   this.richTextBox1.Location = new System.Drawing.Point(45, 34);
   this.richTextBox1.Name = "richTextBox1";
   this.richTextBox1.Size = new System.Drawing.Size(533, 318);
   this.richTextBox1.TabIndex = 0;
   this.richTextBox1.Text =
       "╔════════════════════════════════════════════════╗\n" +
       "║                 This is a test                 ║\n" +
       "╚════════════════════════════════════════════════╝";
    // ...
}

将内容复制到Microsoft Word后可观察到:仅 This is a test 部分使用Consolas字体,其余方框绘制字符均被替换为Segoe UI Symbol字体。已确认Consolas字体本身支持这些方框绘制字符,需要阻止RichTextBox的自动字体替换行为。


解决方案

方法1:手动构造RTF格式内容强制指定字体

RichTextBox底层依赖RTF渲染,直接设置Text属性时系统会触发自动字体替换逻辑。可以构造完整的RTF内容,强制所有字符使用Consolas字体:

// 构造RTF内容,\fs24对应12号字体(RTF字号为点数的2倍)
string rtfContent = @"{\rtf1\ansi\deff0{\fonttbl{\f0 Consolas;}}
\f0\fs24 
╔════════════════════════════════════════════════╗
║                 This is a test                 ║
╚════════════════════════════════════════════════╝
}";

richTextBox1.Rtf = rtfContent;

方法2:自定义RichTextBox拦截字体替换消息

通过重写控件的消息处理逻辑,拦截系统自动替换字体的操作,创建自定义控件:

using System.Runtime.InteropServices;
using System.Windows.Forms;

public class FixedFontRichTextBox : RichTextBox
{
    protected override void WndProc(ref Message m)
    {
        const int WM_CHARFORMAT = 0x0030;

        if (m.Msg == WM_CHARFORMAT)
        {
            // 强制设置全局字体为控件指定的Consolas
            var cf = new CHARFORMAT2();
            cf.cbSize = (uint)Marshal.SizeOf(cf);
            cf.dwMask = CFM_FACE | CFM_SIZE;
            cf.szFaceName = this.Font.Name;
            cf.yHeight = (int)(this.Font.Size * 20); // RTF字号单位为1/20点

            Marshal.StructureToPtr(cf, m.LParam, false);
        }
        base.WndProc(ref m);
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct CHARFORMAT2
    {
        public uint cbSize;
        public uint dwMask;
        public uint dwEffects;
        public int yHeight;
        public int yOffset;
        public int crTextColor;
        public byte bCharSet;
        public byte bPitchAndFamily;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string szFaceName;
    }

    private const uint CFM_FACE = 0x00000020;
    private const uint CFM_SIZE = 0x00000080;
}

使用时将窗体中的RichTextBox替换为该自定义控件即可。

方法3:将纯文本转换为带字体指定的RTF

通过工具方法将普通文本包装为指定字体的RTF内容,再设置给控件的Rtf属性:

public static string TextToRtf(string text, Font font)
{
    // 转义RTF特殊字符,包装为指定字体的RTF结构
    string escapedText = text.Replace("\\", "\\\\").Replace("{", "\\{").Replace("}", "\\}");
    return $"{{\\rtf1\\ansi\\deff0{{\\fonttbl{{\\f0 {font.Name};}}}}\\f0\\fs{font.Size * 20} {escapedText}}}";
}

// 使用示例
richTextBox1.Rtf = TextToRtf(richTextBox1.Text, richTextBox1.Font);

内容的提问来源于stack exchange,提问作者Martin Prikryl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:55:37