【问题标题】:Basic TextBox from Scratch从零开始的基本文本框
【发布时间】:2014-09-09 04:56:06
【问题描述】:

我想我会尝试一下我自己的简单 TextBox 控件。我不太确定它们是如何编写的,但我查看了 Windows 窗体文本框的参考源,它只是添加了更多问题,所以我想我会问我自己的问题,这些问题基于如何我认为制作了一个 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)当用户“选择”文本时,我们在List中查找用户“选择”的坐标,然后在该位置绘制一个填充矩形?

【问题讨论】:

  • 您可能希望将文本存储为String 而不是单个字符,并使用Graphics.DrawString(...) 进行渲染。原因是国际字符单独出现与组合在一个单词中时不同。这确实提出了一个关于如何确定正确插入符号位置的有趣问题。
  • @Loathing 这是一个非常好的观点,感谢您提及它。
  • 从头开始创建一个文本框是一个非常大的任务。这是可能的,但要让它运作良好将是相当困难的。你的问题中最重要的词是“简单”作为我自己的简单文本框控件.. - 所以你应该制作一个所有书面列表您要实现的功能。
  • 文本框继承自 TextBoxBase,所以即使textbox.cs 也不是一个从头开始的项目。它使用TextRenderer 进行输出。
  • 文本框有很多额外的功能需要处理才能获得正确的行为。例如,它显示一个闪烁的插入符号,它可以换行,它可以支持使用 Unicode 字体从右到左渲染,它可以处理各种键盘快捷键,在鼠标交互上有不同的行为(单击、双击、三次单击、拖动/删除、突出显示、更改插入符号位置)等。

标签: c# .net winforms drawing gdi+


【解决方案1】:

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

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

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

这一切的后果是

  • 自定义文本框明显慢于 Windows 原生等效文本框
  • 需要更多内存

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

最终我会建议不要尝试它,因为尽管整体“感觉”可能是它不是原生 Windows 文本框,而且它的行为非常微妙(尤其是滚动方式 - 以像素为单位)而不是逐行)。

希望这会有所帮助。

【讨论】:

  • 非常感谢@Phillip,这真的很有帮助。我仍然会尝试它(否则我将无法停止思考它),但我不希望它和原生一样好。我不得不问这个问题的事实足以证明我不会很快获得本地体验:)
  • msdn.microsoft.com/en-us/library/office/… 下载 Open XML 文档库是个好主意。我意识到这为您提供了 Word 文档的数据结构,但是“丰富的”文本框将需要完全相同的数据结构,这可能是将您的设计基于执行相同类型的现有结构的非常好的方法工作,加上其完整的文档。我不是建议你实现一个 WordProcessor,而是使用 lib 作为你需要存储和处理什么样的东西的指南。
猜你喜欢
  • 1970-01-01
  • 2013-03-04
  • 1970-01-01
  • 2012-12-26
  • 1970-01-01
  • 2016-02-03
  • 2021-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多