在TextBox控件中修改字符间距/宽度

3
我正在尝试动态设置TextBox控件中每个字符的间距(宽度)。我已经阅读了大量资料,但我不认为这在常规TextBox中是可能的。我愿意使用RichTextBox或任何其他可以解决此问题的控件。
为了证明这是可能的,我打开了Word,并能够选择一个字符并调整其间距并将其“拉伸”出来。我希望在我的.NET应用程序中实现相同的行为。
是否有可用的代码示例或控件,展示如何实现这一点?

1
我真的想不出其他方法来做这件事,除了使用自绘控件;一种继承TextBox类的控件,但你可以控制字符的绘制;因为你已经知道每个字符的位置,所以你可以指定(如果你使用固定宽度字体)这些东西在框中如何显示。或者你可以使用第三方控件,如DevExpress、DevComponents或Telerak。 - user674311
1
你需要自己实现控制并使用Graphics.ScaleTransform() + Graphics.DrawString()。字母间距很难调整,需要使用Graphics.MeasureCharacterRanges。让它看起来好看更加困难。 - Hans Passant
一个便宜的解决方案是使用WebBrowser控件来代替自己创建控件 - 这样你只需要生成HTML就可以实现你想要的功能。虽然没有测试过,但我认为这个方法可行。当然,你不能在控件中输入文本 - 你必须将其分成工作区和显示区...至少不像TextBox那样扩展WebBrowser。 - J...
很遗憾,目前我不能选择使用WPF。 - Alex
3个回答

5
如果您同意链接到一些WPF的程序集(WindowsBase和PresentationCore),您可以编写一个自定义的TextBox并在WinForms实现中使用它。 WPF有一些很好的类,如GlyphTypeFace(允许加载字体文件并从字形构建几何图形)和GlyphRun(允许绘制一系列字形-文本)。但是我们不能在这里使用GlyphRun,因为我们希望能够修改某些字形的几何形状。因此,我们需要手动获取几何图形并对其进行变换。
下面是一个示例:
Winforms代码:
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        // ElementHost allows Winforms to host WPF visual components
        ElementHost host = new ElementHost();
        host.Dock = DockStyle.Fill;
        host.Child = new MyTextBox();
        Controls.Add(host);
    }

定制的文本框代码:

public class MyTextBox: UIElement
{
    protected override void OnRender(DrawingContext drawingContext)
    {
        const string sampleText = "Sample String";
        const int sampleEmSize = 30;

        GlyphTypeface typeFace = new GlyphTypeface(new Uri("file:///C:/WINDOWS/FONTS/segoeui.ttf"));

        GeometryGroup group = new GeometryGroup();
        group.FillRule = FillRule.Nonzero;

        double x = 0;
        double y = sampleEmSize;
        for (int i = 0; i < sampleText.Length; i++)
        {
            ushort glyphIndex = typeFace.CharacterToGlyphMap[sampleText[i]];
            Geometry glyphGeometry = typeFace.GetGlyphOutline(glyphIndex, sampleEmSize, sampleEmSize).Clone();
            TransformGroup glyphTransform = new TransformGroup();

            if (sampleText[i] == 'm') // this is a sample, we just change the 'm' characte
            {
                const double factor = 2;
                glyphTransform.Children.Add(new ScaleTransform(factor, 1));
                glyphTransform.Children.Add(new TranslateTransform(x, y));
                x += factor * typeFace.AdvanceWidths[glyphIndex] * sampleEmSize;
            }
            else
            {
                glyphTransform.Children.Add(new TranslateTransform(x, y));
                x += typeFace.AdvanceWidths[glyphIndex] * sampleEmSize;
            }

            glyphGeometry.Transform = glyphTransform;
            group.Children.Add(glyphGeometry);
        }

        drawingContext.DrawGeometry(Brushes.Black, null, group);
    }
}

这是在WinForms上的结果:

enter image description here

当然,如果你想支持编辑,还有一些工作要做,但这可以让你开始。

也许这个问题/答案也可以帮到你:https://dev59.com/NVTTa4cB1Zd3GeqPsGhb - juFo

0
你可以考虑使用Telerik WinForms控件。我知道它们非常注重样式元素。

0

供您参考,我编写了这段代码,可以让您更改输入到RichTextBox中的每个字符的字体和字体样式。

public int a = 0;
private void richTextBox1_TextChanged(object sender, EventArgs e)
    {
        if (a == 0)
        {
            richTextBox1.SelectionFont = new Font(RichTextBox.DefaultFont, FontStyle.Bold);
            a = 1;
        }
        else if (a == 1)
        {
            richTextBox1.SelectionFont = new Font("Georgia",13, FontStyle.Bold);
            a = 2;
        }
        else if (a == 2)
        {
            richTextBox1.SelectionFont = new Font("Impact", 11, FontStyle.Italic);
            a = 0;
        }
    }

如果这对你有帮助,请告诉我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接