Какой хороший способ выполнить тестирование попадания на FormattedText? - PullRequest
1 голос
/ 12 февраля 2009

Я отрисовываю текст, используя FormattedText, но, похоже, существует какой-либо способ выполнить проверку попадания на символ на отображаемом выводе. Это только для чтения, поэтому мне нужно только выделение, без редактирования.

Я бы использовал RichTextBox или аналогичный, но мне нужно выводить текст на основе управляющих кодов, встроенных в сам текст, поэтому они не всегда вкладываются, что делает построение правильных встроенных элементов очень сложным. Я также немного беспокоюсь о производительности этого решения; У меня есть большое количество строк, и часто добавляются новые строки.

Я посмотрел на GlyphRun, похоже, я мог бы получить тестирование на попадание из него или из связанного с ним класса, но я бы переопределил многие функции, и, похоже, должен быть более простой способ ... .

Кто-нибудь знает хороший способ реализовать это?

Ответы [ 4 ]

4 голосов
/ 27 июля 2011

Вы можете получить геометрию каждого персонажа из объекта 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 вы можете визуализировать эти геометрические объекты вместо отформатированного текста.

3 голосов
/ 12 февраля 2009

Лучший способ - создать хорошую структуру данных для хранения вашего текста, которая также учитывает проверку на попадание. Одним из примеров может быть разделение текста на блоки (слова, строки или абзацы в зависимости от того, что вам нужно). Тогда каждый такой блок должен иметь ограничивающий прямоугольник, который должен быть пересчитан при любых операциях форматирования. Также учтите позиции каретки в вашем дизайне.

Когда у вас есть такая возможность, вам будет очень легко проводить тестирование на попадание, просто используйте ограничивающие рамки. Это также поможет в последующих операциях, таких как выделение определенной части текста.

1 голос
/ 16 января 2015

Я очень опаздываю на вечеринку - если вечеринка не закончилась, и вам не нужна реальная геометрия персонажа, я нашел что-то вроде этого полезным:

 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++;
        }

Надеюсь, это поможет.

1 голос
/ 12 февраля 2009

Полностью согласен с Sesh - самый простой способ избежать повторной реализации всей функциональности FormattedText - разделить отдельные элементы, которые вы хотите проверить, на их собственные элементы управления / встраивает.

Рассмотрите возможность использования TextBlock и добавления каждого слова в качестве его собственного Inline (или), а затем либо привязки к встроенному свойству IsMouseDirectlyOver, наши делегаты добавления к событиям MouseEnter & MouseLeave.

Если вы хотите выполнить тестирование на уровне пикселей реальных глифов (т. Е. Точно ли мышь находится в точке этого «i»), то вам нужно будет использовать GlyphRuns и выполнять ручное тестирование на глифы ( читай: тяжелая работа).

...