如何在标题栏中显示带有下标或上标的文本? [英] How to display text with subscripts or superscripts in the Title Bar?

查看:117
本文介绍了如何在标题栏中显示带有下标或上标的文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够在Windows窗体或WPF窗口的标题栏中显示带下标的文本。这样做的原因是简单的。我们的项目团队已经编写了分子编辑器:

I would like to be able to show subscripted text in the Title Bar of a Windows Form or WPF Window. The reason for this is simple. Our project team has written a molecule editor:

我们不仅要显示其名称'ACME',还要显示以下内容:

Instead of just displaying its name, 'ACME', we would like to show something like:


ACME-编辑C 6 H 12 Cl

其中的文本是带下标的(并且可能是上标的)以及控件显示在Windows窗体或WPF主机中。

where the text is subscripted (and possibly superscripted) and whether the control is shown in a Windows Forms or WPF host.

推荐答案

最初的问题是询问如何在窗体的标题中插入RichTextBox。 ,以显示化学式。

当然可以做到:您可以看看 DwmExtendFrameIntoClientArea 和此处的文档:使用DWM的自定义窗口框架和许多 SO问题

The original question was asking how to insert a RichTextBox in a Form's Caption, to show a chemical formula.
It could be done, of course: you could take a look at DwmExtendFrameIntoClientArea and the Docs here: Custom Window Frame Using DWM and a number of SO questions.

但是,这里看起来有点超调。有一个更简单的选择:利用现有的Unicode SubScript符号(这是Unicode类别)来重现公式。

But it looked like overshooting, here. There's a simpler alternative: make use of the existing Unicode SubScript symbols (it's an Unicode cathegory) to reproduce the formula.

这些是印度阿拉伯数字的基本Subscript和SuperScript Unicode代码点。 :

These are the base Subscript and SuperScript Unicode codepoints of the Hindu-Arabic numerals:

char[] subScriptNumbers = {
    '\u2080', '\u2081', '\u2082', '\u2083', '\u2084',
    '\u2085', '\u2086', '\u2087', '\u2088', '\u2089'
};
char[] superScriptNumbers = {
    '\u2070', '\u00B9', '\u00B2', '\u00B3', '\u2074',
    '\u2075', '\u2076', '\u2077', '\u2078', '\u2079'
};

如注释所提示,简单公式为: C6H12Cl 可以转换为 C₆H₁2Cl ,将数字映射到SubScript范围中的相应Unicode值。例如:

As hinted in comments, the simple formula: C6H12Cl can be transformed to C₆H₁₂Cl, mapping the numbers to the corresponding Unicode values in the SubScript range. For example:

this.Text = string.Concat("C6H12Cl".Select(c => char.IsDigit(c) ? subScriptNumbers[c-48] : c));

或者,由于SubScript代码点是顺序的(而SuperScript的代码点则不是):

Or, since the SubScript codepoints are sequential (the SuperScript ones are not):

const int subScriptBase = 0x2080;
string chem = "C6H12Cl";
// Or this.Title, in WPF
this.Text = chem.Aggregate(new StringBuilder(), (sb, c) => 
    sb.Append(char.IsDigit(c) ? (char)(subScriptBase + c - 48) : c)).ToString();




由于似乎有人感兴趣,我建议使用一个稍微复杂的解析器(使用相同的逻辑),以产生不同种类的公式:


Since it appears that there's someone interested, I'm proposing a slightly more complex parser (which uses the same logic), to produce different kinds of formulas:

此处显示的类可以使用简单的表示法(类似于表示法)转换SubScript / SuperScript数字或字母的序列

The class shown here can convert sequences of SubScript/SuperScript numerals or letters, using a simple notation (similar to the notation of the Markup used by Wikipedia):

SuperScript: [+:symbols]          A[+:12]    => A¹²  
SubScript:   [-:symbols]          A[-:12]    => A₁₂
Fraction:    [f:symbols/symbols]  A·[f:x/12] => A·ˣ⁄₁₂

例如:

string formula = "N[+:(x+2)] · H[+:3] · γLog[-:e] + δ· [f:n11/x]";
// Or this.Text, in WinForms
this.Title = UniSubSup.Parse(formula);

将打印:

N⁽ˣ⁺²⁾·H³·γLogₑ+δ· ⁿ¹¹⁄​​ₓ

will print:

N⁽ˣ⁺²⁾·H³·γLogₑ + δ·ⁿ¹¹⁄ₓ

Note1

标记包含空格,将被跳过:因此,解析了 [+ :( x + 2)] ,而 [+ :( x + 2)] 不是(如果应该忽略这些括号)。

Note1:
When a markup contains spaces, it's skipped: hence [+:(x+2)] is parsed, while [+:(x + 2)] is not (in case these brackets should be ignored).

Note2

我没有包括所有字母,因为并非所有字体都支持SubScript和SuperScript类别中的所有代码点。下标 n \u2099 ),这是比较常见的下标(例如Log n ),在大多数字体类型中不可用(因为sub / superScripting是通过不同的方式生成的。)
有些(很少)字体确实具有这些字形。像 fileformat.info 这样的网站都可以提供这些信息。

Note2:
I did not include all the letters because not all fonts support all the codepoints in the SubScript and SuperScript cathegories. The Subscript n (\u2099), which is relatively common (e.g., Logn), is not available in most of font types (since sub/superScripting is generated by different means).
Some (very few) Fonts do have these glyphs. WebSites like fileformat.info can provide these informations.

public class UniSubSup
{
    const char joiner =       '\u200D';
    const char nonJoiner =    '\u200C';
    const char fraction =     '\u2044';
    const char solidusShort = '\u0337';
    const char solidusLong =  '\u0338';

    protected internal static Dictionary<string, Func<string, string>> actions =
        new Dictionary<string, Func<string, string>>()
        {
            ["-"] = (s) => sub(s),
            ["+"] = (s) => sup(s),
            ["f"] = (s) => fract(s),
        };

    internal static string sub(string s) => 
        s.Aggregate(new StringBuilder(), (sb, c) => sb.Append(subScripts[c])).ToString();

    internal static string sup(string s) => 
        s.Aggregate(new StringBuilder(), (sb, c) => sb.Append(superScripts[c])).ToString();

    internal static string fract(string str)
    {
        var sb = new StringBuilder();
        var parts = str.Split('/');
        parts[0].Aggregate(sb, (s, c) => sb.Append(superScripts[c]));
        sb.Append(fraction);
        parts[1].Aggregate(sb, (s, c) => sb.Append(subScripts[c]));
        return sb.ToString();
    }

    static RegexOptions options = RegexOptions.Singleline | RegexOptions.Compiled;

    public static string Parse(string input)
    {
        string pattern = @"\[(\D{1}):(\S\/?\S*?)\]";
        var matches = Regex.Matches(input, pattern, options);
        StringBuilder result = new StringBuilder(input);
        foreach (Match m in matches)
        {
            result = result.Replace(m.Value, actions[m.Groups[1].Value](m.Groups[2].Value));
        }
        return result.ToString();
    }

    internal static Dictionary<char, char> superScripts = new Dictionary<char, char>()
    {
        ['0'] = '\u2070', ['1'] = '\u00B9', ['2'] = '\u00B2', ['3'] = '\u00B3',
        ['4'] = '\u2074', ['5'] = '\u2075', ['6'] = '\u2076', ['7'] = '\u2077',
        ['8'] = '\u2078', ['9'] = '\u2079',
        ['+'] = '\u207A', ['-'] = '\u207B', ['='] = '\u207C',
        ['('] = '\u207D', [')'] = '\u207E',
        ['e'] = '\u1D49', ['n'] = '\u207F', ['x'] = '\u02E3' 
    };

    internal static Dictionary<char, char> subScripts = new Dictionary<char, char>()
    {
        ['0'] = '\u2080', ['1'] = '\u2081', ['2'] = '\u2082', ['3'] = '\u2083',
        ['4'] = '\u2084', ['5'] = '\u2085', ['6'] = '\u2086', ['7'] = '\u2087',
        ['8'] = '\u2088', ['9'] = '\u2089',
        ['+'] = '\u208A', ['-'] = '\u208B', ['='] = '\u208C',
        ['('] = '\u208D', [')'] = '\u208E', ['/'] = '\u2044',
        ['e'] = '\u2091', ['n'] = '\u2099', ['x'] = '\u2093'
    };
}

这篇关于如何在标题栏中显示带有下标或上标的文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆