我正在使用FormattedText
渲染文本,但似乎有任何方法可以对渲染输出执行每个字符命中测试。它是只读的,所以我基本上只需要选择,不需要编辑。
我使用RichTextBox
或类似的,但我需要根据嵌入文本本身的控制代码输出文本,因此它们并不总是嵌套,这使得构建正确的内联元素非常复杂。我也有点担心该解决方案的性能;我有很多行,经常添加新行。
我看过GlyphRun
,似乎我可以从它或相关的类中进行测试,但是我会重新实现很多功能,似乎应该有一个更简单的方法...
有没有人知道实现这个的好方法?
答案 0 :(得分: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中,您可以渲染这些几何对象而不是格式化文本。
答案 1 :(得分:3)
最好的方法是设计一个用于存储文本的良好数据结构,并考虑命中测试。一个例子可以是将文本分成块(单词,行或段落,具体取决于您的需要)。然后每个这样的块应该有一个边界框,应该在任何格式化操作中重新计算。还要考虑设计中的插入位置。
一旦你拥有了这样的设施,就可以很容易地进行命中测试,只需使用边界框即可。它还有助于后续操作,例如突出显示文本的特定部分。
答案 2 :(得分:1)
完全同意Sesh - 最简单的方法就是不要重新实现一大堆FormattedText功能,而是将你想要测试的单个项目分成他们自己的控件/内联。
考虑使用TextBlock并添加每个单词作为它自己的内联(或),然后绑定到内联的IsMouseDirectlyOver属性,我们添加委托给MouseEnter& MouseLeave事件。
如果你想对实际的字形进行像素级命中测试(即鼠标恰好在这个'i'的点上),那么你需要使用GlyphRuns并对字形进行手动命中测试(读:努力工作)。
答案 3 :(得分: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++;
}
希望这有帮助。