kgmmurugesh Ответов: 3

Как печатать символы, измеряя их ширину?


Я хочу напечатать текст "ААА". Сначала я печатаю "а", а затем измеряю ширину текста, чтобы получить позицию x для следующего текста, подобного этому. Когда я печатаю таким образом, это дает некоторый разрыв между текстами. Как решить эту проблему?

Что я уже пробовал:

Public Class Form1
    Private TMPbmp As New Bitmap(1, 1)
    Private TMPgfx As Graphics = Graphics.FromImage(TMPbmp)
    Private TxtSize As SizeF
    Public prnDocument As New System.Drawing.Printing.PrintDocument
    Public WithEvents prnPreview As New System.Windows.Forms.PrintPreviewDialog
    Private egraphics As Graphics
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Click
        AddHandler prnDocument.PrintPage, AddressOf prnDocument_PrintPage
        prnPreview.Document = prnDocument
        prnPreview.WindowState = FormWindowState.Maximized
        prnPreview.ShowDialog()
    End Sub
    Private Sub prnDocument_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
        Dim lalign As New StringFormat
        egraphics = e.Graphics
        egraphics.PageUnit = GraphicsUnit.Point
        lalign.Alignment = StringAlignment.Near

        Dim lwi As Single = TextWidth("A", New Font("Arial", 19))
        egraphics.DrawString("A", New Font("Arial", 19), New SolidBrush(Color.Black), 10, 50, lalign)
        egraphics.DrawString("A", New Font("Arial", 19), New SolidBrush(Color.Black), 10 + lwi, 50, lalign)
        eGraphics.DrawString("A", New Font("Arial", 19), New SolidBrush(Color.Black), 10 + lwi + lwi, 50, lalign)
    End Sub
    Public Function TextWidth(ByVal Matter As String, ByVal pFont As System.Drawing.Font) As Single
        TMPgfx.PageUnit = GraphicsUnit.Point
        TxtSize = TMPgfx.MeasureString(Matter, pFont)
        TextWidth = TxtSize.Width
    End Function
End Class

3 Ответов

Рейтинг:
2

Dave Kreskowiak

Никто больше не указывал на то, что ваш код приведет к утечке ресурса и в конечном итоге к краху Windows.

Эти объекты шрифтов и кистей, которые вы создаете, должны быть вызваны Dispose, чтобы освободить ресурсы GDI. Вы не можете просто создать их в стиле "огонь и забыть".

Гораздо более чистая версия кода будет выглядеть примерно так:

Private Sub prnDocument_PrintPage(ByVal sender As Object, ByVal e As PrintPageEventArgs)
    Dim g As Graphics = e.Graphics
    g.PageUnit = GraphicsUnit.Point

    Dim lalign As New StringFormat
    lalign.Alignment = StringAlignment.Near

    Using (Font font As New Font("Arial", 19))
        Using (Brush brushBlack As New SolidBrush(Color.Black)
            Dim lwi As Single = TextWidth("A", font)

            g.DrawString("A", font, brushBlack, 10, 50, lalign)
            g.DrawString("A", font, brushBlack, 10 + lwi, 50, lalign)
            g.DrawString("A", font, brushBlack, 10 + lwi + lwi, 50, lalign)
        End Using
    End Using
End Sub


Рейтинг:
2

OriginalGriff

Это сложно, но если вы хотите печатать символы с правильным интервалом, вам нужно измерить всю строку, потому что ширина символа-это не единственное, что влияет на ширину строки, есть правила "человеческого глаза", которые также применяются. А пропорциональные шрифты (например, Arial) - это все для того, чтобы текст "выглядел хорошо".

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

Если вы хотите напечатать "ААА", то измерьте "Ааа" - вы не можете получить "правильный результат", измеряя "А" и предполагая, что ширина "ААА" ровно в три раза больше ширины!


Рейтинг:
15

Jochen Arndt

Это объясняется в разделе замечаний руководства. MeasureString описание функции:

Метод MeasureString предназначен для использования с отдельными строками и включает в себя небольшое количество дополнительного пространства до и после строки, чтобы обеспечить нависающие глифы. Кроме того, метод DrawString настраивает точки глифа для оптимизации качества отображения и может отображать строку более узкую, чем указано в MeasureString. Чтобы получить метрики, подходящие для соседних строк в макете (например, при реализации форматированного текста), используйте метод MeasureCharacterRanges или один из методов MeasureString, который принимает StringFormat, и передайте GenericTypographic. Кроме того, убедитесь, что TextRenderingHint для графики является AntiAlias.

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


kgmmurugesh

Спасибо за вашу помощь. Я использую следующий код.

Браузер государственной функции(pstrcharacter бывал, как струна, pfont бывал как системы.Рисование.Шрифт) Как Одиночный
Тусклый а как одиночный
Дим B как один

Попробуй
TMPgfx.Страница-ИНФОРМЕР = GraphicsUnit.Точка
TxtSize = TMPgfx.MeasureString(pstrcharacter, pfont)
a = TxtSize.Ширина
TxtSize = TMPgfx.MeasureString(pstrcharacter + pstrcharacter, pfont)
b = TxtSize.Ширина
Браузер = Б - а
Поймать ex как исключение
Бросок экс
Конец Попытки

Конечная Функция

kgmmurugesh

Браузер государственной функции(pstrcharacter бывал, как струна, pfont бывал как системы.Рисование.Шрифт) Как Одиночный
Тусклый а как одиночный
Дим B как один

Попробуй
TMPgfx.Страница-ИНФОРМЕР = GraphicsUnit.Точка
TxtSize = TMPgfx.MeasureString(pstrcharacter, pfont)
a = TxtSize.Ширина
TxtSize = TMPgfx.MeasureString(pstrcharacter + pstrcharacter, pfont)
b = TxtSize.Ширина
Браузер = Б - а
Поймать ex как исключение
Бросок экс
Конец Попытки

Конечная Функция