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
相关产品推荐
相关产品推荐

