1

我正在使用 渲染文本FormattedText,但似乎有任何方法可以对渲染的输出执行每个字符的命中测试。它是只读的,所以我基本上只需要选择,不需要编辑。

我会使用RichTextBox或类似的,但我需要根据嵌入在文本本身中的控制代码输出文本,因此它们并不总是嵌套,这使得构建正确的内联元素非常复杂。我也有点担心该解决方案的性能;我有很多行,并且经常附加新行。

我看过GlyphRun,看来我可以从它或相关类中进行命中测试,但我会重新实现很多功能,而且似乎应该有一种更简单的方法......

有谁知道实现这一点的好方法?

4

4 回答 4

4

您可以从 FormattedText 对象中获取每个字符的几何形状,并使用每个字符的边界进行命中测试。

var geometry = (GeometryGroup)((GeometryGroup)text.BuildGeometry(new Point(0, 0))).Children[0];
foreach (var c in geometry.Children)
{
  if (c.Bounds.Contains(point))
    return index;
  index++;
}

在 OnRender 中,您可以渲染这些几何对象而不是格式化文本。

于 2011-07-27T05:31:27.393 回答
3

最好的方法是设计一个好的数据结构来存储你的文本,并且还要考虑命中测试。一个示例可能是将文本拆分为块(单词、行或段落,具体取决于您的需要)。然后每个这样的块应该有一个边界框,应该在任何格式化操作中重新计算。还要考虑设计中的插入符号位置。

一旦你有了这样的设施,就很容易进行命中测试,只需使用边界框。它还将有助于后续操作,例如突出显示文本的特定部分。

于 2009-02-12T04:44:50.573 回答
1

完全同意 Sesh - 不重新实现整个 FormattedText 功能负载的最简单方法是将要进行命中测试的单个项目拆分为它们自己的控件/内联。

考虑使用 TextBlock 并将每个单词添加为它自己的内联(或),然后绑定到内联的 IsMouseDirectlyOver 属性,我们将委托添加到 MouseEnter 和 MouseLeave 事件。

如果你想对实际字形进行像素级命中测试(即鼠标正好在这个 'i' 的点中),那么你需要使用 GlyphRuns 并对字形进行手动命中测试(阅读:hard工作)。

于 2009-02-12T08:15:38.100 回答
1

我参加聚会已经很晚了——如果聚会没有结束,并且你不需要实际的角色几何图形,我发现这样的东西很有用:

 for (int i = 0; i < FormattedText.Text.Length; i++)
 {
            characterHighlightGeometry = FormattedText.BuildHighlightGeometry(new Point(), i, 1);
            CharacterHighlightGeometries.Children.Add(characterHighlightGeometry);
 }

BuildGeometry() 仅包含角色的实际路径几何。BuildHighlightGeometry() 生成所有字符的外部边界 - 包括空格,因此可以通过以下方式找到空格的索引:

 foreach (var c in CharacterHighlightGeometries.Children)
        {
            if (c.Bounds.Contains(centerpoint))
            {
                q = c;
                cpos = index;
                break;
            }
            index++;
        }

希望这可以帮助。

于 2015-01-16T19:58:20.573 回答