Создать редактор гитарных аккордов в WPF (из RichTextBox?)

Основная цель приложения, над которым я работаю в 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 . Я хочу, чтобы текст был похож на kering right, а не на enter image description here. Второе изображение не имеет кернинга между V и A . Оранжевые линии служат только для визуализации эффекта (но они отмечают смещение по оси x, где будет размещаться аккорд). Код, использованный для создания первого образца, - Ta VA , а для второго образца Ta V A .

Есть идеи, как заставить RichTextBox сделать это? Или есть лучший способ сделать это в WPF? Могу ли я разделить на подклассы Inline или Run ? Приветствуются любые идеи, хаки, магия TextPointer , код или ссылки на связанные темы.


Изменить:

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

  1. Попытка превратить RichTextBox в редактор аккордов - взгляните на Как я могу создать подкласс класса Inline? .
  2. Создайте новый редактор из отдельных компонентов например Panel s TextBox es и т. д., как предлагается в HB answer . Это потребовало бы большого количества кодирования, а также привело бы к следующим (нерешенным) проблемам:


Edit # 2

Высококачественный ответ Маркуса Хюттера показал мне, что с RichTextBox можно сделать гораздо больше Тогда я ожидал, когда сам пытался настроить его под свои нужды. Только сейчас у меня было время подробно изучить ответ. Маркус может быть RichTextBox волшебником. Мне нужно помочь мне с этим, но есть и некоторые нерешенные проблемы с его решением:

  1. Это приложение будет посвящено "красиво" напечатанным текстам песен. Основная цель - чтобы текст выглядел идеально с типографской точки зрения. Когда хорды расположены слишком близко друг к другу или даже перекрываются, Маркус предлагает, чтобы я итеративно добавлял пробелы перед его положением, пока их расстояние не станет достаточным. Фактически существует требование, чтобы пользователь мог установить минимальное расстояние между двумя аккордами. Это минимальное расстояние должно соблюдаться и не превышаться до тех пор, пока это необходимо. Пробелы недостаточно детализированы - как только я добавлю последнее необходимое пространство, я, вероятно, сделаю пробел шире, чем необходимо - из-за этого документ будет выглядеть «плохо». Я не думаю, что это может быть принято. Мне нужно вставить пробел произвольной ширины .
  2. Могут быть строки без аккордов (только текст) или даже строки без текста (только аккорды). Если для LineHeight установлено значение 25 или другое фиксированное значение для всего документа, это приведет к тому, что строки без аккордов будут иметь «пустые строки» над ними. Когда есть только аккорды и нет текста, для них не будет места.

Есть и другие второстепенные проблемы, но я либо думаю, что смогу их решить, либо считаю их неважными. В любом случае, я думаю, что ответ Маркуса действительно ценен - ​​не только для того, чтобы показать мне возможный путь, но и для демонстрации общей схемы использования RichTextBox с украшением.

19
задан Michael Scott Cuthbert 2 January 2019 в 05:49
поделиться