Каков хороший способ выполнить проверку попадания в FormattedText?
Вопрос
Я визуализирую текст, используя FormattedText
, но, похоже, существует какой-либо способ выполнить посимвольное тестирование попаданий на визуализированном выводе.Он доступен только для чтения, поэтому мне нужно только выделение, а не редактирование.
я бы использовал RichTextBox
или что-то подобное, но мне нужно выводить текст на основе управляющих кодов, встроенных в сам текст, поэтому они не всегда вложены, что делает построение правильных встроенных элементов очень сложным.Меня также немного беспокоит производительность этого решения;У меня большое количество строк, и новые строки добавляются часто.
я посмотрел GlyphRun
, похоже, я мог бы провести тестирование на попадание из него или связанного с ним класса, но мне пришлось бы переопределить множество функций, и кажется, что должен быть более простой способ...
Кто-нибудь знает хороший способ реализовать это?
Решение
Лучший способ — разработать хорошую структуру данных для хранения вашего текста, которая также учитывает проверку попадания.Одним из примеров может быть разделение текста на блоки (слова, строки или абзацы в зависимости от того, что вам нужно).Тогда каждый такой блок должен иметь ограничивающую рамку, которая должна пересчитываться при любых операциях форматирования.Также учитывайте положение кареток в своем дизайне.
Если у вас есть такая возможность, проводить тестирование попадания становится очень легко, просто используйте ограничивающие рамки.Это также поможет в последующих операциях, таких как выделение определенной части текста.
Другие советы
Вы можете получить геометрию каждого символа из объекта 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 вы можете визуализировать эти геометрические объекты вместо форматированного текста.
Полностью согласен с Сешем - самый простой способ избежать повторной реализации всей нагрузки функциональности FormattedText - это разделить отдельные элементы, которые вы хотите проверить на попадание, на их собственные элементы управления/встроенные строки.
Рассмотрите возможность использования TextBlock и добавления каждого слова как отдельного Inline ( или ), а затем либо привяжите его к свойству Inline IsMouseDirectlyOver, либо добавьте делегатов к событиям MouseEnter и MouseLeave.
Если вы хотите провести проверку попадания реальных глифов на уровне пикселей (т.находится ли мышь точно в точке этого «i»), тогда вам нужно будет использовать GlyphRuns и выполнить ручную проверку нажатия на глифы (читай:тяжелая работа).
Я очень опоздал на вечеринку — если вечеринка еще не закончилась и вам не нужна фактическая геометрия персонажа, я нашел что-то вроде этого полезным:
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++;
}
Надеюсь это поможет.