Основная цель приложения, над которым я работаю в WPF, - разрешить редактирование и, следовательно, печать текстов песен с гитарными аккордами над ним.
Возможно, вы видели аккорды, даже если вы не играете на каком-либо инструменте. Чтобы дать вам представление, это выглядит так:
E E6
I know I stand in line until you
E E6 F#m B F#m B
think you have the time to spend an evening with me
Но вместо этого уродливого шрифта с одним шрифтом я хочу иметь шрифт Times New Roman
с кернинг как для лирики, так и для аккордов (аккорды жирным шрифтом). И я хочу, чтобы пользователь мог редактировать это.
Этот сценарий не поддерживается для RichTextBox
. Вот некоторые из проблем, которые я не знаю, как решить:
- Аккорды имеют свои позиции, закрепленные над каким-либо персонажем в тексте текста (или, в общем,
TextPointer
строки текста). Когда пользователь редактирует текст, я хочу, чтобы аккорд оставался верным персонажем. Пример:
.
E E6
I know !!!SOME TEXT REPLACED HERE!!! in line until you
- Линейная упаковка: 2 строки (1-я с аккордами и 2-я лирика) логически одна линия, когда дело доходит до упаковки. Когда слово переносится на следующую строку, все хорды, которые над ним, должны также завернуться. Также, когда аккорд обертывает слово, что он над ним, он также обертывается. Пример:
.
E E6
think you have the time to spend an
F#m B F#m B
evening with me
- Аккорды должны оставаться на правильном персонаже, даже если аккорды слишком близки друг к другу. В этом случае дополнительное пространство автоматически добавляется в строку текста. Пример:
.
F#m E6
...you have the ti me to spend...
- Скажем, у меня есть строка текста
Ta VA
и аккорд надA
. Я хочу, чтобы текст песни выглядел как не как . Второе изображение не выражается междуV
иA
. Оранжевые линии есть только для визуализации эффекта (но они отмечают смещения x, где размещается аккорд). Код, используемый для создания первого образца, -<TextBlock FontFamily="Times New Roman" FontSize="60">Ta VA</TextBlock>
и для второго образца<TextBlock FontFamily="Times New Roman" FontSize="60"><Span>Ta V<Floater />A</Span></TextBlock>
.
Любые идеи о том, как получить RichTextBox
для этого? Или есть лучший способ сделать это в WPF? Будет ли я подклассифицировать Inline
или Run
справку? Любые идеи, хаки, магия TextPointer
, код или ссылки на связанные темы приветствуются.
Изменить:
Я изучаю 2 основных направления для решения этой проблемы, но оба они приводят к другим проблемам, поэтому я задаю новый вопрос:
- Попытка превратить
RichTextBox
в редактор аккордов - посмотрите Как создать подкласс класса Inline?. -
Создайте новый редактор из отдельных компонентов, таких как
Panel
TextBox
es и т.д., как предлагается в H.B. ответить. Это потребовало бы большого количества кодирования, а также привело бы к следующим (нерешенным) проблемам:- Компоненты изменят свою ширину/высоту в соответствии с их расположением макета (удаление пробела при начале строки и т.д.).
- Кернинг должен быть вставлен вручную на границе компонентов.
- Как сделать RichTextBox похожим на TextBlock? (не изящный хак/обходной путь известен)
Edit # 2
Высокий качественный ответ Markus Hütter показал мне, что гораздо больше можно сделать с помощью RichTextBox
, тогда я ожидал, когда я сам попытаюсь настроить его для себя, Я успел подробно изучить ответ только сейчас. Маркус может быть магом RichTextBox
Мне нужно помочь мне в этом, но есть и нерешенные проблемы с его решением:
- Это приложение будет посвящено "красивой" печатной лирике. Основная цель заключается в том, что текст выглядит идеально с типографической точки зрения. Когда аккорды слишком близки друг к другу или даже перекрываются, Маркус предполагает, что я итеративно добавляю дополнительные пространства до его положения до тех пор, пока их расстояние не станет достаточным. Существует фактически требование, чтобы пользователь мог установить минимальное расстояние между двумя аккордами. Это минимальное расстояние должно быть соблюдено и не превышено до тех пор, пока это не будет необходимо. Пробелы не достаточно гранулированы - как только я добавлю последнее пространство, я, вероятно, сделаю этот пробел более широким, чем необходимо, - что сделает документ "плохим". Я не думаю, что его можно было бы принять. Мне нужно будет вставить пространство пользовательской ширины.
- Могут быть строки без аккордов (только текст) или даже строки без текста (только аккорды). Если для параметра
LineHeight
установлено значение25
или другое фиксированное значение для всего документа, это приведет к тому, что строки без аккордов будут иметь "пустые строки" над ними. Когда есть только аккорды, и нет текста, для них не будет места.
Существуют и другие незначительные проблемы, но я либо думаю, что смогу их решить, либо считаю их неважными. В любом случае, я думаю, что ответ Маркуса действительно ценен - не только для того, чтобы показать мне возможный путь, но и как демонстрацию общей картины использования RichTextBox
с adorner.