.NET Graphics.ScaleTransform преобразует задание на печать в растровое изображение. Есть ли другой способ масштабирования текста? - PullRequest
1 голос
/ 14 апреля 2010

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

Если я не масштабируюсь таким образом, задание печати остается очень маленьким, поскольку оно просто отправляет команды печати текста на принтер.

У меня вопрос, есть ли другой способ, кроме Graphics.ScaleTransform, чтобы растянуть ширину текста?

Пример кода для демонстрации этого приведен ниже (будет вызываться с Print.Test(True) и Print.Test(False), чтобы показать влияние масштабирования на задание печати):

Imports System.Drawing
Imports System.Drawing.Printing
Imports System.Drawing.Imaging

Public Class Print

    Dim FixedFont As Font
    Dim Area As RectangleF
    Dim CharHeight As Double
    Dim CharWidth As Double
    Dim Scale As Boolean

    Const CharsAcross = 80
    Const CharsDown = 66
    Const TestString = "!""#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"

    Private Sub PagePrinter(ByVal sender As Object, ByVal e As PrintPageEventArgs)

        Dim G As Graphics = e.Graphics
        If Scale Then
            Dim ws = Area.Width / G.MeasureString(Space(CharsAcross).Replace(" ", "X"), FixedFont).Width
            G.ScaleTransform(ws, 1)
        End If

        For CurrentLine = 1 To CharsDown
            G.DrawString(Mid(TestString & TestString & TestString, CurrentLine, CharsAcross), FixedFont, Brushes.Black, 0, Convert.ToSingle(CharHeight * (CurrentLine - 1)))
        Next

        e.HasMorePages = False

    End Sub

    Public Shared Sub Test(ByVal Scale As Boolean)

        Dim OutputDocument As New PrintDocument
        With OutputDocument
            Dim DP As New Print
            .PrintController = New StandardPrintController
            .DefaultPageSettings.Landscape = False
            DP.Area = .DefaultPageSettings.PrintableArea
            DP.CharHeight = DP.Area.Height / CharsDown
            DP.CharWidth = DP.Area.Width / CharsAcross
            DP.Scale = Scale
            DP.FixedFont = New Font("Courier New", DP.CharHeight / 100, FontStyle.Regular, GraphicsUnit.Inch)
            .DocumentName = "Test print (with" & IIf(Scale, "", "out") & " scaling)"
            AddHandler .PrintPage, AddressOf DP.PagePrinter
            .Print()
        End With
    End Sub
End Class

ОБНОВЛЕНИЕ: Вместо этого я использовал взаимодействие с вызовами GDI. Вот соответствующий код; класс GDI просто полон определений, которые я скопировал из вики на http://pinvoke.net/ для соответствующих функций и констант.

    ' convert from Graphics units (100 dpi) to device units
    Dim GDIMappedCharHeight As Double = CharHeight * G.DpiY / 100
    Dim GDIMappedCharWidth As Double = CharWidth * G.DpiX / 100

    Dim FixedFontGDI As IntPtr = GDI.CreateFont(GDIMappedCharHeight, GDIMappedCharWidth, 0, 0, 0, 0, 0, 0, GDI.DEFAULT_CHARSET, GDI.OUT_DEFAULT_PRECIS, GDI.CLIP_DEFAULT_PRECIS, GDI.DEFAULT_QUALITY, GDI.FIXED_PITCH, "Courier New")
    Dim CharRect As New GDI.STRUCT_RECT

    Dim hdc As IntPtr = G.GetHdc()
    GDI.SelectObject(hdc, FixedFontGDI)

    ' I used SetBkMode transparent as my text needed to overlay a background
    GDI.SetBkMode(hdc, GDI.TRANSPARENT)

    ' draw it character by character to get precise grid
    For CurrentLine = 1 To CharsDown
        For CurrentColumn = 1 To CharsAcross
            With CharRect
                .left = GDIMappedCharWidth * (CurrentColumn - 1)
                .right = GDIMappedCharWidth * CurrentColumn
                .top = GDIMappedCharHeight * (CurrentLine - 1)
                .bottom = GDIMappedCharHeight * CurrentLine
            End With
            ' 2341 == DT_NOPREFIX|DT_NOCLIP|DT_VCENTER|DT_CENTER|DT_SINGLELINE
            GDI.DrawText(hdc, Mid(TestString & TestString & TestString, CurrentLine+CurrentColumn, 1), 1, CharRect, 2341)
        Next
    Next

    GDI.DeleteObject(FixedFontGDI)

    G.ReleaseHdc(hdc)

Ответы [ 2 ]

1 голос
/ 14 апреля 2010

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

Вам нужно будет обосновать текст самостоятельно. Там нет поддержки для этого в рамках. Один из способов сделать это - захватить богатый элемент управления и позволить ему позаботиться о выравнивании и печати. Версия 5, msftedit.dll, поддерживает полное обоснование. Лучший способ найти нужный код - это найти один из множества проектов, в которых реализован текстовый редактор с RTB, аналогично Wordpad в Windows.

0 голосов
/ 14 апреля 2010

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

...