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

WinForms程序中化学式显示格式问题咨询

嘿,我之前在WinForms项目里也碰到过要显示规范化学式的需求,给你几个亲测有效的实现方案,按需选就行:

方案1:用WinForms自带的RichTextBox控件(最便捷)

RichTextBox自带字符偏移和字体调整功能,完全能满足下标、上标的需求,不用额外引入第三方库,成本最低。核心思路是遍历化学式字符串,识别原子数量(下标)和电荷符号/数值(上标),动态调整选中字符的偏移量和字体大小。

示例代码:

private void RenderChemicalFormula(RichTextBox targetBox, string rawFormula)
{
    targetBox.Clear();
    // 设置默认字体
    var regularFont = new Font("Arial", 12, FontStyle.Regular);
    targetBox.SelectionFont = regularFont;
    targetBox.SelectionCharOffset = 0;

    for (int i = 0; i < rawFormula.Length; i++)
    {
        char currentChar = rawFormula[i];
        if (char.IsDigit(currentChar))
        {
            // 判断是下标还是上标:电荷数通常跟在+/-前后,原子数跟在元素符号后
            bool isSubscript = true;
            if (i > 0 && (rawFormula[i-1] == '+' || rawFormula[i-1] == '-'))
                isSubscript = false;
            if (i < rawFormula.Length -1 && (rawFormula[i+1] == '+' || rawFormula[i+1] == '-'))
                isSubscript = false;

            // 切换到下标/上标样式
            targetBox.SelectionCharOffset = isSubscript ? -3 : 3;
            targetBox.SelectionFont = new Font("Arial", 9, FontStyle.Regular);
            targetBox.AppendText(currentChar.ToString());
            
            // 恢复默认样式
            targetBox.SelectionCharOffset = 0;
            targetBox.SelectionFont = regularFont;
        }
        else if (currentChar == '+' || currentChar == '-')
        {
            // 电荷符号设为上标
            targetBox.SelectionCharOffset = 3;
            targetBox.AppendText(currentChar.ToString());
            targetBox.SelectionCharOffset = 0;
        }
        else
        {
            // 普通字符直接追加
            targetBox.AppendText(currentChar.ToString());
        }
    }
}

调用时直接传你的反应式:

RenderChemicalFormula(richTextBox1, "H2SO4 ⇌ 2H+ + SO42-");
方案2:用WebView2加载HTML(格式最标准)

如果想要更专业、无偏差的下标上标格式,HTML的<sub>和<sup>标签是天生的解决方案。你可以把原始化学式字符串转换成带HTML标签的格式,然后用WebView2控件加载显示,效果非常规整。

示例代码:

private void LoadFormulaInWebView(WebView2 webView, string rawFormula)
{
    // 用正则表达式智能替换下标和上标
    string htmlFormula = Regex.Replace(rawFormula, @"([A-Za-z])(\d+)", @"$1<sub>$2</sub>");
    htmlFormula = Regex.Replace(htmlFormula, @"(\d+)([+-])", @"<sup>$1$2</sup>");
    htmlFormula = Regex.Replace(htmlFormula, @"([+-])", @"<sup>$1</sup>");

    // 包裹成完整的HTML页面
    string fullHtml = $@"
    <html>
        <body style='font-family: Arial; font-size: 14px; margin: 0; padding: 8px;'>
            {htmlFormula}
        </body>
    </html>";
    
    webView.NavigateToString(fullHtml);
}
方案3:自定义GDI+绘制控件(高度自定义)

如果需要完全控制字体、间距、颜色等细节,或者不想用现成控件,可以自己写一个自定义标签控件,重绘时手动处理每个字符的位置和样式。

示例控件框架:

public class ChemicalFormulaLabel : Label
{
    private string _chemicalFormula;
    public string ChemicalFormula
    {
        get => _chemicalFormula;
        set
        {
            _chemicalFormula = value;
            Invalidate(); // 触发重绘
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        if (string.IsNullOrEmpty(_chemicalFormula)) return;

        float xPos = 5;
        float yPos = 5;
        var regularFont = new Font("Arial", 14, FontStyle.Regular);
        var subSupFont = new Font("Arial", 10, FontStyle.Regular);

        for (int i = 0; i < _chemicalFormula.Length; i++)
        {
            char c = _chemicalFormula[i];
            if (char.IsDigit(c))
            {
                bool isSubscript = true;
                if (i > 0 && (_chemicalFormula[i-1] == '+' || _chemicalFormula[i-1] == '-'))
                    isSubscript = false;
                if (i < _chemicalFormula.Length -1 && (_chemicalFormula[i+1] == '+' || _chemicalFormula[i+1] == '-'))
                    isSubscript = false;

                // 调整绘制Y坐标:下标往下偏移,上标往上偏移
                float drawY = isSubscript ? yPos + regularFont.Size - subSupFont.Size : yPos;
                e.Graphics.DrawString(c.ToString(), subSupFont, Brushes.Black, xPos, drawY);
                xPos += e.Graphics.MeasureString(c.ToString(), subSupFont).Width;
            }
            else if (c == '+' || c == '-')
            {
                e.Graphics.DrawString(c.ToString(), subSupFont, Brushes.Black, xPos, yPos);
                xPos += e.Graphics.MeasureString(c.ToString(), subSupFont).Width;
            }
            else
            {
                e.Graphics.DrawString(c.ToString(), regularFont, Brushes.Black, xPos, yPos);
                xPos += e.Graphics.MeasureString(c.ToString(), regularFont).Width;
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:26:03