【问题标题】:Modifying character spacing/width in a TextBox control修改 TextBox 控件中的字符间距/宽度
【发布时间】:2012-02-04 14:06:13
【问题描述】:

我正在尝试动态设置 TextBox 控件中每个字符的间距(宽度)。我已经阅读了大量内容,但我认为这在普通的 TextBox 中是不可能的。我对 RichTextBox 或任何其他可以解决此问题的控件持开放态度。

为了证明这是可能的,我打开了 Word,我能够选择一个字符并调整其间距并“拉伸”它。我希望在我的 .NET 应用程序中实现相同的行为。

是否有代码示例或控制说明如何实现?

【问题讨论】:

  • 我真的想不出任何其他方法来做到这一点,除了所有者绘制的控件;一个继承了 TextBox 类,然后是一个你控制字符的绘制;由于您已经知道每个字符的位置,您可以指定(例如,如果您使用固定字体)这些内容在框中的显示方式。或者,您可以使用 DevExpress、DevComponents 或 Telerak 等第 3 方控件。
  • 您必须实现自己的控件并使用 Graphics.ScaleTransform() + Graphics.DrawString()。很难得到正确的字母间距,Graphics.MeasureCharacterRanges。更难让它看起来不错。
  • 制作自己的控件的一个便宜的技巧可能是使用 WebBrowser 控件——这样你只需要生成 HTML 来做你想做的事。未经测试,但我认为它可以工作。当然,您将无法输入控件 - 您必须在工作区和显示区之间进行分割……至少无需像 TextBox 那样扩展 WebBrowser。
  • 很遗憾,WPF 目前不适合我。

标签: .net winforms fonts textbox richtextbox


【解决方案1】:

如果您接受链接到某些 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 上的结果:

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

【讨论】:

【解决方案2】:

供您参考,我编写了这段代码,它可以让您更改您在 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;
        }
    }

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

【讨论】:

    【解决方案3】:

    您可以查看用于 WinForms 的 Telerik 控件。我知道他们非常重视风格元素。

    【讨论】:

      猜你喜欢
      • 2015-07-25
      • 1970-01-01
      • 1970-01-01
      • 2017-07-28
      • 2015-06-26
      • 1970-01-01
      • 2011-08-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多