Scratch的基本TextBox

时间:2014-09-09 04:56:07

标签: c# .net winforms drawing gdi+

我以为我会对自己简单的TextBox Control进行攻击。我不太确定它们是如何编写的,但我看了一下Windows Forms TextBox的参考源,它只是添加了很多问题所以我想我会问自己的问题是基于如何我认为是一个TextBox控件:

如何绘制字符/文字? 因为我将从头开始创建TextBox,所以我显然需要绘制。所以知道当你在WinForms中绘制内容时,你不能只选择那个文本,你需要处理MouseDown和MouseMove事件,获取鼠标被按下的位置,然后确定哪个字符是在那个位置。但除非我们将这个角色与其坐标一起保存在某处,否则我们无法真正做到这一点。这意味着我们可能需要使用列表来存储用户输入的所有内容:

List<Character> characters = new List<Character>();

class Character
{
    public string Text { get; set; }
    public Location { get; set; }
    public Size { get; set; }
}

现在我们已经获得了该角色的位置,我们需要绘制一个填充的矩形,以便用户知道他们正在选择什么。我们可以通过在我们之前确定的坐标处获取角色的大小和位置来做到这一点。

这基本上是TextBox的工作原理吗?

1)当用户输入内容时,我们使用DrawString绘制“已键入”的内容,然后将其大小和位置存储在列表中以供将来参考? 2)当用户“选择”文本时,我们在列表中查找用户“选中”的坐标,然后在该位置绘制一个填充的矩形?

1 个答案:

答案 0 :(得分:4)

我确实编写了自己的WinForms TextBox(为了满足数据录入过程中拼写检查的需要,并通过字体下划线和颜色突出显示错误的拼写)。在我对此进行调查期间,我发现.net没有执行文本框渲染本身(它是一个Windows工具),所以不得不从头开始创建它。

我的方法与您的方法非常相似,但要记住的重点是没有一个数据结构足以存储文本框的所有内容。具体而言,文本框应具有以下内容的集合;

  1. 字符列表。
  2. TextRuns,它是所有共享相同演示文稿的字符的字符列表的索引 - 即字体,颜色等。文字翻译通常比字符少。
  3. 一个突出显示TextRun以记录用户当前突出显示的字符
  4. 克拉位置 - 这可能很棘手。文本框克拉可以在第一个字符之前或在最后一个字符之后,或者在它们之间的任何字符。
  5. 最后一个绘制文本框的图像 - 就像一个缓冲区,这样可以快速满足OnPaint消息,而无需重复MeasureString和DrawString调用。在多行或可滚动框的情况下,这通常可以大于TextBox的可渲染区域,在这种情况下,您可以根据请求呈现Rectangle子集。
  6. RenderRuns列表,表示一组字符的位置和大小,所有这些字符都在同一个TextRun中,并且绘制在同一文本框行上,并且是绘画的基本单位。 RenderRun将在Image和Size中具有偏移位置,使您可以为Image中的任何给定位置选择正确的RenderRun。随后选择特定字符将需要RenderRun中每个字符的MeasureString。您可以选择在Re​​nderRun中存储字符大小,或者在每次需要时动态计算它。
  7. 所有这一切的后果是

    • 自定义文本框明显慢于Windows本机等效文本
    • 花了更多的记忆

    所以我们只在那些需要拼写检查的领域使用它。

    最终我建议不要尝试它,因为虽然有可能整体“感觉”是它不是原生的Windows文本框,并且它表现得非常微妙地不同(尤其是它滚动的方式 - 按像素而不是直线)。

    希望这有帮助。