2010-04-14 4 views
1

Я использую Graphics.ScaleTransform для растягивания строк текста, чтобы они соответствовали ширине страницы, а затем печатали эту страницу. Однако это преобразует задание на печать в растровое изображение - для печати со многими страницами это приводит к тому, что размер задания печати увеличивается до неприличных пропорций и значительно замедляет печать..NET 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 = "!""#$%&'()*+,-./:;<=>[email protected][\]^_`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 

UPDATE: Я использовал Interop с GDI вызывает вместо этого. Вот соответствующий код; класс GDI просто заполнен определениями, которые я скопировал из wiki по адресу 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) 

ответ

1

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

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

+0

Спасибо за ваш совет! Я взглянул на использование мощных элементов управления редактированием, но, похоже, это было потрясающе, поэтому я вступил в взаимодействие со старыми вызовами GDI прямо на графике hDC - к счастью, CreateFont для этого поддерживает ширину установки и высоту и передает ее на принтер без рендеринга растровых изображений. –

0

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

+0

Я устанавливаю высоту шрифта [показан в коде Новый шрифт («Courier New», DP.CharHeight/100, FontStyle.Regular, GraphicsUnit.Inch)] относительно высоты строки, но нужно установить ширину независимо от этого. К сожалению, масштабирование только размера растягивается как по ширине, так и по высоте в той же пропорции. –