Создание столбцов текста с шрифтом переменной ширины

Asked
Viewd3662

6

Я пытаюсь создать столбцы текста для приложения C #, которое будет работать в MSN Messenger. У меня проблемы с приведением всего в порядок.

Вот пример результата, который мне нужен:

 1)  Pizza Hut                                            123 Fake St.
2)  Domino's Pizza                                       123 Fake St.
3)  The Cheesecake Cafe                                  123 Fake St.
4)  Capital Pizza & Steakhouse                           123 Fake St.
5)  Funky Pickle Pizza                                   123 Fake St.
6)  Boston Pizza                                         123 Fake St.
7)  Rose Bowl Rouge Lounge                               123 Fake St.
8)  Royal Pizza                                          123 Fake St.
9)  A Columbus Pizza & Donair Inc                        123 Fake St.
 

Но поскольку это шрифт переменной ширины, он отображается следующим образом:

 1)  Pizza Hut                                        123 Fake St.
2)  Domino's Pizza                                   123 Fake St.
3)  The Cheesecake Cafe                                  123 Fake St.
4)  Capital Pizza & Steakhouse                               123 Fake St.
5)  Funky Pickle Pizza                                   123 Fake St.
6)  Boston Pizza                                     123 Fake St.
7)  Rose Bowl Rouge Lounge                               123 Fake St.
8)  Royal Pizza                                          123 Fake St.
9)  A Columbus Pizza & Donair Inc                    123 Fake St.
 

Я пробовал использовать функцию C # string.PadRight (), а также создал свою собственную функцию, которая добавляет отступы с помощью пробелов и табуляций. Оба прекрасно работают со шрифтами фиксированной ширины, но не работают со шрифтами переменной ширины.

Есть ли способ определить ширину строки заданным шрифтом?

Или у кого-нибудь есть другие предложения?

4 ответов

7

Просто используйте класс TextRenderer . . Самый простой случай:

 Size size = TextRenderer.MeasureText("Hello world", someFont);
 

Если у вас нет доступа к System.Windows.Fonts, Графика. MeasureString остается, у него есть некоторые ограничения, но он должен работать:

 Bitmap bmp = new Bitmap(1,1);
Graphics graphics = Graphics.FromImage(bmp);
SizeF size = graphics.MeasureString("Hello world", someFont);
 

Но имейте в виду, что если шрифт вашего текста и пробелы ДОЛЖНЫ быть одинаковыми, будут случаи, когда вы не сможете идеально выровнять текст. Я не знаю, что MSN Messenger может делать в вашем случае, но за исключением случаев, когда у вас есть доступ хотя бы к подмножеству HTML, у вас не будет идеального вывода.

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

Если также требуется поддержка нескольких операционных систем, у вас могут возникнуть большие проблемы, поскольку шрифт Arial на Mac и ПК не выглядит (и не измеряется) точно так же.

  • Для эквивалента Java в java.awt есть FontMetrics, см. http://stackoverflow.com/questions/258486/calculate-the-display-width-of-a-string-in-java/258499#258499

    Spoike22 сентября 2009, 09:01
  • Похоже, что это часть пространства имен System.Windows.Forms, но мое приложение на самом деле является веб-службой, которая возвращает службу Windows, которая подключается к MSN.Таким образом, пространство имен System.Windows не может быть найдено, когда я пытаюсь создать свое приложение.

    Есть идеи, как мне получить доступ к этой функции?

    Stephen Curial02 марта 2009, 22:43
  • Я добавил образец с MeasureString, это небольшая уловка, поскольку вам нужно растровое изображение для работы, но оно должно это сделать.

    Julien Roncaglia02 марта 2009, 23:04
0

Вы можете попробовать использовать класс Graphics для измерения длины строки с заданным шрифтом, а затем использовать это, чтобы определить, сколько вкладок использовать.

  • Это было бы хорошим решением, но как мне получить доступ к экземпляру графического класса из веб-службы?

    Я нашел этот код, объясняющий это для приложения Windows Forms: http://www.dev102.com/2008/10/09/measure-string-size-in-pixels-c/

    Stephen Curial02 марта 2009, 22:55
-1

Вам, вероятно, следует форматировать все в HTML, тогда вы можете просто вывести элементы TABLE и TR / TD для столбцов

0

Похоже, вы пытаетесь отобразить все это в ASCII в одном текстовом поле. Да? Если это так, то это довольно сложно. Похоже, сейчас у вас есть фиксированное количество вкладок после каждой, и это может быть проблемой. Вместо этого вы можете использовать пробелы - я подозреваю, что вы делаете это с помощью padright (не очень знаком с этой конкретной функцией).

Ключевым моментом является то, что с таким чистым ASCII, показанным шрифтом переменной ширины, вы никогда не сможете добиться идеального выравнивания во втором столбце. Вы можете приблизиться к нему, если будете прилежны, но это все - если у вас есть одна строка с большим количеством заглавных W, а другая с большим количеством строчных i, у вас будут большие различия в ширине, независимо от того, что вы делаете. Если вы выполняете рендеринг в GDI, лучший подход - сделать один вызов DrawText для каждого столбца. Вы можете сделать одну большую строку из каждого столбца, если хотите, и вызвать MeasureString в первом столбце, чтобы определить, сколько места вам нужно переместить для второго столбца.

Или, если это интерфейс, в котором вы можете работать с html, таблицы или div отлично подойдут. Зависит от специфики вашей среды. Вы также можете сделать что-то вроде двух меток с автоматической установкой высоты на панели FlowLayout, если это WinForms и т. Д. Есть много вариантов для выполнения этой работы, но только не чистый ascii с шрифтом переменной ширины.

РЕДАКТИРОВАТЬ: Кроме того, я видел, как вы спрашивали, как получить экземпляр класса Graphics в веб-службе. Вы можете сделать что-то вроде этого:

     private static Bitmap bitmap = new Bitmap( 1, 1 );
    private static Graphics graphics = null;

    public static Graphics GetGeneralGraphics()
    {
        if ( graphics == null )
            graphics = Graphics.FromImage( bitmap );
        return graphics;
    }
 

Вероятно, вы захотите сделать эти локальные переменные (которые вы правильно удалите по завершении работы) в контексте веб-служб.