.Net Graphics.ScaleTransform converte o trabalho de impressão em bitmap. Alguma outra maneira de dimensionar o texto?

StackOverflow https://stackoverflow.com/questions/2637174

Pergunta

estou a usar Graphics.ScaleTransform Para esticar as linhas de texto para que se encaixem na largura da página e imprimindo essa página. No entanto, isso converte o trabalho de impressão em um bitmap - para uma impressão com muitas páginas, isso faz com que o tamanho do trabalho de impressão suba a proporções obscenas e diminui imensamente imensamente.

Se eu não escalar assim, o trabalho de impressão permanecerá muito pequeno, pois está apenas enviando comandos de impressão de texto para a impressora.

Minha pergunta é: existe outra maneira além de usar Graphics.ScaleTransform Para esticar a largura do texto?

Código de exemplo para demonstrar isso está abaixo (seria chamado com Print.Test(True) e Print.Test(False) para mostrar os efeitos do escala no trabalho de impressão):

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

ATUALIZAR: Eu usei a interop com chamadas de GDI. Aqui está o código relevante; A classe GDI está cheia de definições que copiei do wiki em http://pinvoke.net/ para as funções e constantes relevantes.

    ' 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)
Foi útil?

Solução

Sim, a classe gráfica suporta o texto em escala. Mas ele precisa fazer isso renderizando o texto para um bitmap primeiro, redimensione o bitmap e passe esse bitmap redimensionado para o driver da impressora. Todos esses bitmaps são um grande arquivo de spooler.

Você precisará justificar o texto sozinho. Não há suporte para isso na estrutura. Uma maneira de fazer isso é seqüestrar um controle de edição rico e deixar isso cuidar da justificativa e da impressão. Versão 5, msftEdit.dll, suporta justificativa completa. A melhor maneira de encontrar o código necessário é encontrar um dos muitos projetos que implementam um editor de texto com RTB, semelhante ao WordPad no Windows.

Outras dicas

Estou supondo aqui, mas você deve aumentar o tamanho da fonte em uma porcentagem da proporção pela qual deseja escalar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top