Results 1 to 13 of 13

Thread: [RESOLVED] A better way for Print Page dpi awareness

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Resolved [RESOLVED] A better way for Print Page dpi awareness

    In Printer Priting mode, I have considered the scale of printer vs screen. I expect I will get the same result because I have scaled the size of Text Rectangle. Printer DPI (normal 600) is larger than screen dpi (normal 96), so the ratio is 600/96 = 6.25.

    But the text got slight difference on my preview Window and printer Page. The text is being wrapped in difference. Refer to my attachments.

    I think the reason is the scale. Theory is OK but...

    How to solve my problem or has a better way for Print Page dpi awareness?

    Scale :

    If bPrintingView then
    SetRect rc, Round(rc.Left + 2 ), Round(rc.Top + 1), Round(rc.Right - 2), Round(rc.Bottom - 1)
    ElseIf bPrintingMode Then
    SetRect rc, Round(rc.Left + 2 * dpiXRatio), Round(rc.Top + 1* dpiYRatio), Round(rc.Right - 2 * dpiXRatio), Round(rc.Bottom - 1* dpiYRatio)
    End If
    Sample Code:

    the hdc in preview window, it is picturebox hdc,otherwise, it is Printer.hdc

    Code:
    Dim lhDC As Long
        lhDC = GetDC(0)
        ScreenLogPixelsX = GetDeviceCaps(lhDC, 88) 'Const LOGPIXELSX As Long = 88  Number of pixels per logical inch along the screen width
        ScreenLogPixelsY = GetDeviceCaps(lhDC, 90) 'Const LOGPIXELSY As Long = 90  Number of pixels per logical inch along the screen height
        ReleaseDC 0, lhDC
        
        'Logical pixels inch in X and Y
        Dim DpiX As Long
        Dim DpiY As Long
        DpiX = GetDeviceCaps(hPrinterDC, 88) 'LOGPIXELSX= 88 (e.g. Sharp AR-5316: 600,Depend on Printer setting)
        DpiY = GetDeviceCaps(hPrinterDC, 90) ' LOGPIXELSY = 90 (e.g. Sharp AR-5316: 600,Depend on Printer setting)
        Dim dpiXRatio As Single
        Dim dpiYRatio As Single
        dpiXRatio = DpiX / ScreenLogPixelsX
        dpiYRatio = DpiY / ScreenLogPixelsY
    
    If  bPrintingView then
       SetRect rc, Round(rc.Left + 2 ), Round(rc.Top + 1), Round(rc.Right - 2), Round(rc.Bottom - 1)
    ElseIf bPrintingMode Then
       SetRect rc, Round(rc.Left + 2 * dpiXRatio), Round(rc.Top + 1* dpiYRatio), Round(rc.Right - 2 * dpiXRatio), Round(rc.Bottom - 1* dpiYRatio)
    End If
    
    Dim oFont As Std_Font
    Dim hFont as Long, hOldFont as Long
    Dim wFormat As Long
    
    wFormat = &H12810
    Set oFont = m_oFont
     
    hFont= CreateFont(-pMulDiv(oFont.Size, GetDeviceCaps(hdc, 90), 72!), 0, 0, 0, IIf(oFont.Bold, 700, 400), _
                                IIf(oFont.Italic, 1, 0), IIf(oFont.Underline, 1, 0), IIf(oFont.Strikethrough, 1, 0), 1, 0, 0, 3, 48, oFont.Name)
     Set oFont = Nothing
     hOldFont= SelectObject(hdc, hFont)
     DrawTextEx hdc, Text, rc, wFormat
     SelectObject hdc, hOldFont
     DeleteObject hFont
    Attached Images Attached Images   
    Last edited by Jonney; Jul 18th, 2015 at 11:19 PM.

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: A better way for Print Page dpi awareness

    Are you sure the indent (offset) of each paragraph in your preview window is proportionally correct? Maybe it's just that simple? Paragraph starts a couple pixels more to the right, so the text wrapping isn't the same any longer.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: A better way for Print Page dpi awareness

    Quote Originally Posted by LaVolpe View Post
    Are you sure the indent (offset) of each paragraph in your preview window is proportionally correct? Maybe it's just that simple? Paragraph starts a couple pixels more to the right, so the text wrapping isn't the same any longer.
    I remove all other text except the multi-line text:

    I debug the rc position:
    ------------ Left Top Right Bottom
    Preview: 283 173 679 358
    Printing: 1768 1081 4244 2238
    283*6.25 = 1768.75
    173*6.25 = 1081.25
    679*6.25 = 4243.75
    358*6.25 = 2237.5

    The Coordinates are almost proportionally same, But I can't figure out why DrawText wrapped differently.
    Last edited by Jonney; Jul 19th, 2015 at 09:34 AM.

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: A better way for Print Page dpi awareness

    Are you using a true-type font? Maybe if you manually extend the right edge of the rectangle a pixel at a time to find out where the wrap is exactly the same, then you might be able to detect the problem?
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: A better way for Print Page dpi awareness

    Quote Originally Posted by LaVolpe View Post
    Are you using a true-type font? Maybe if you manually extend the right edge of the rectangle a pixel at a time to find out where the wrap is exactly the same, then you might be able to detect the problem?
    I saw the same problem by direct assignment, I used "Tahoma", size is 9 for this testing :

    Code:
        If bPrintingView Then
            rc.Left = 283 '283 173 679 358
            rc.Top = 173
            rc.Right = 679
            rc.Bottom = 358
            DrawTextW hDC, StrPtr(Text), -1, rc, wFormat
    
        ElseIf bPrintingMode Then
            rc.Left = 1768
            rc.Top = 1081
            rc.Right = 4244
            rc.Bottom = 2238
            DrawTextW hDC, StrPtr(Text), -1, rc, wFormat
    
        End If
    Last edited by Jonney; Jul 19th, 2015 at 10:04 AM.

  6. #6
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: A better way for Print Page dpi awareness

    You asked is there a better way? Maybe. On this link, MSDN briefly talks about issues similar to yours. Here is their answer
    Finally, be aware that although TrueType fonts scale nicely, they don’t scale linearly: Increasing the DPI by 10 percent does not generally increase a string’s length by exactly 10 percent. (GDI+ doesn’t have this problem; see the GDI+ section.) This happens because any given letter only looks good at certain sizes, and TrueType picks the nearest size that looks good.
    Is GDI+ the cure?
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  7. #7

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: A better way for Print Page dpi awareness

    Quote Originally Posted by LaVolpe View Post
    You asked is there a better way? Maybe. On this link, MSDN briefly talks about issues similar to yours. Here is their answer

    Is GDI+ the cure?
    I will try GDI+ tomorrow. Thanks for the clue.

  8. #8

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: A better way for Print Page dpi awareness

    I an trying to replace GDI with GDI+, But situation get complicated:
    1. In GDI+, Preview window (picturebox) do show text, but the text font size looks smaller than normal (or than GDI).
    2. In GDI+, LeftBottom and RightBottom alignment doesn't work when RECT is smaller than height of text need.
    3. My Printer doesn't draw at all in GDI+ code. Nothing Text being drawn by GDI+ though picture and GDI code works.

    GDI Code :
    Code:
    hFont = CreateFont(-pMulDiv(m_oFont.Size, GetDeviceCaps(hDC, 90), 72!), 0, 0, 0, IIf(m_oFont.Bold, 700, 400), _
             IIf(m_oFont.Italic, 1, 0), IIf(m_oFont.Underline, 1, 0), IIf(m_oFont..Strikethrough, 1, 0), 1, 0, 0, 0, 48, m_oFont.Name)
    hOldFont = SelectObject(hDC, hFont)
    lColor = SetTextColor(hDC, vbBlack)
    DrawTextW hDC, StrPtr(Text), -1, rc, wFormat
    SetTextColor hDC, lColor
    SelectObject hDC, hOldFont
    DeleteObject hFont
    GDI+ Code:
    Code:
    Dim hStringFormat As Long
    
        lFontStyle = (IIf(m_oFont.Bond, 1, 0) Or _
                     IIf(m_oFont.Italic, 2, 0) Or _
                     IIf(m_oFont.Underline, 4, 0) Or _
                     IIf(m_oFont.Strikethrough, 8, 0))
        GdipCreateFontFamilyFromName StrPtr(m_oFont.Name), 0&, hFontFamily
        GdipCreateFont hFontFamily, m_oFont.Size, lFontStyle, UnitPixel, hFont
    
        GdipCreateStringFormat 0&, 0&, hStringFormat
        If ((wFormat And 16) <= 0) Then
            GdipSetStringFormatFlags hStringFormat, StringFormatFlags.NoWrap
        End If
    
        If ((wFormat And 1) > 0) Then
            GdipSetStringFormatAlign hStringFormat, StringAlignment.StringAlignmentCenter
        ElseIf ((wFormat And 2) > 0) Then
            GdipSetStringFormatAlign hStringFormat, StringAlignment.StringAlignmentFar
        Else
            GdipSetStringFormatAlign hStringFormat, StringAlignment.StringAlignmentNear
        End If
    
        If ((wFormat And 4) > 0) Then
            GdipSetStringFormatLineAlign hStringFormat, StringAlignment.StringAlignmentCenter
        Else
            If ((wFormat And 8) > 0) Then
                GdipSetStringFormatLineAlign hStringFormat, StringAlignment.StringAlignmentFar
            Else
                GdipSetStringFormatLineAlign hStringFormat, StringAlignment.StringAlignmentNear
            End If
        End If
    
        GdipSetTextRenderingHint hGraphics, TextRenderingHintSystemDefault
        GdipSetCompositingQuality hGraphics, CompositingQualityAssumeLinear
        GdipSetPixelOffsetMode hGraphics, PixelOffsetModeHalf
    
    Dim tRectF As RECTF
        tRectF.Left = rc.Left
        tRectF.Top = rc.Top
        tRectF.Width = rc.Right - rc.Left
        tRectF.Height = rc.Bottom - rc.Top
        GdipSetClipRectI hGraphics, rc.Left, rc.Top, rc.Right - rc.Left, rc.Bottom - rc.Top, CombineMode.CombineModeReplace
    
    Dim hBrush As Long
        GdipCreateSolidFill RGBtoARGB(vbBlack, 255), hBrush
    
        GdipDrawString hGraphics, StrPtr(Text), Len(Text), hFont, tRectF, hStringFormat, hBrush
        GdipResetClip hGraphics
        GdipDeleteBrush hBrush
        GdipDeleteStringFormat hStringFormat
        GdipDeleteFont hFont
        GdipDeleteFontFamily hFontFamily

  9. #9
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: A better way for Print Page dpi awareness

    Those differences are quite normal, and you don't even have a guarantee, that
    each and every Printer will follow a certain Font-Selection-Command with the exact
    font in that exact metrics.

    The only way to achieve true WYSIWYG-output (between Preview and Printer)
    when using GDI, is to work with Enhanced-Metafiles (EMF).

    Those APIs can provide you with a hDC as well - then you will render into the
    EMF-File (either InMemory, or against a Disk-File) over that EMF.hDC - and
    for correct "PlayBack" on both (a Pixelbased-Preview-Container on Screen,
    or a Printer) you will then use "PlayEnhMetafile".

    Here's an example which might be useful to validate the EMF-based approach
    first on your System (simple Code, using EMF-Wrapper-Classes from vbRichClient5).

    When these tests with EMF work out well on your Systems and Printers, you'd have
    an ensurance that your own EMF-API-implementations are worth an attempt
    (in case you don't plan to ship the RC5 with your solution).

    Here's a Demo-Zip:

    EMFReports.zip

    Here's what the Demo produces (in Landscape-Mode, but this can be switched)...

    EMF-Rendering into a VB-PictureBox:




    EMF-Rendering onto a PDF-Printer:



    HTH

    Olaf

  10. #10

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: A better way for Print Page dpi awareness

    Those differences are quite normal, and you don't even have a guarantee, that
    each and every Printer will follow a certain Font-Selection-Command with the exact
    font in that exact metrics.

    The only way to achieve true WYSIWYG-output (between Preview and Printer)
    when using GDI, is to work with Enhanced-Metafiles (EMF).

    Those APIs can provide you with a hDC as well - then you will render into the
    EMF-File (either InMemory, or against a Disk-File) over that EMF.hDC - and
    for correct "PlayBack" on both (a Pixelbased-Preview-Container on Screen,
    or a Printer) you will then use "PlayEnhMetafile".

    Here's an example which might be useful to validate the EMF-based approach
    first on your System (simple Code, using EMF-Wrapper-Classes from vbRichClient5).

    When these tests with EMF work out well on your Systems and Printers, you'd have
    an ensurance that your own EMF-API-implementations are worth an attempt
    (in case you don't plan to ship the RC5 with your solution).
    Thanks for the great experiment. I will try to draw into Metafile-DC.
    Meta file has advantages such as adding our own transparent water print.
    I am still wondering why the GDI+ code doesn't work for printer hdc. Sure some flaw inside my code.

    I am still wondering why the GDI+ code doesn't work for printer hdc. Sure some flaw inside my code.
    Edited: I see. I have to scale the canvas considering printer dpi and screen dpi. But GDI doesn't need.
    Last edited by Jonney; Jul 23rd, 2015 at 08:48 AM.

  11. #11

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: A better way for Print Page dpi awareness

    Give up. I will try Schmidt's method: print into emf.

  12. #12
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: A better way for Print Page dpi awareness

    A quick FYI before you rewrite too much. According to the GDI+ docs:

    In the preceding code, the three GDI+ drawing commands are in between calls to the StartDoc and EndDoc functions, each of which receives the printer device context handle. All graphics commands between StartDoc and EndDoc are routed to a temporary metafile. After the call to EndDoc, the printer driver converts the data in the metafile into the format required by the specific printer being used.

    Note If spooling is not enabled for the printer being used, the graphics output is not routed to a metafile. Instead, individual graphics commands are processed by the printer driver and then sent to the printer.
    If you haven't already, check to see if spooling is enabled for your printer. If it isn't, try activating it, then testing your existing code again.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  13. #13

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: A better way for Print Page dpi awareness

    Quote Originally Posted by Tanner_H View Post
    A quick FYI before you rewrite too much. According to the GDI+ docs:



    If you haven't already, check to see if spooling is enabled for your printer. If it isn't, try activating it, then testing your existing code again.
    I tried, the spooling can't being activated for pdfcreator and network sharing printer.

    My problem is that the multiline text on preview window is not the same wrapped on Printing using the same GDI code or GDI+ code with different scale in (Printer dpi) / (screen dpi) . It's not WYSIWYG-output between Preview and Printer. GDI DrawTextW/TextOutW and GDI+ both failed. As Schmidt said, the only way is to print into file or DIB during print preview then output to printer.

    Excel does a good job, I see it always producing WYSIWYG. But I don't know how MS did.
    Last edited by Jonney; Jul 23rd, 2015 at 07:47 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width