• Welcome to PlanetSquires Forums.
 

GDI Plus Printing Problems

Started by James Klutho, June 19, 2017, 07:53:42 PM

Previous topic - Next topic

James Klutho

I am having a heck of a time getting a GDI+ bitmap to print to a printer in Freebasic.  I have been trying to adapt some of Jose's Powerbasic code but I am in over my head.  Could anyone give me a pointer on the code below.  I can get the bitmap to print to the screen OK (but only after hours of trial and error) but no luck on the printer. Thanks



FUNCTION EZP_DrawBitmap (BYVAL MyDC as hDC,BYVAL hbmp AS HBITMAP,MyAngle as single, BYVAL x AS SINGLE = 0, BYVAL y AS SINGLE = 0, _
   BYVAL nRight AS SINGLE = 0, BYVAL nBottom AS SINGLE = 0, AspectFlag as integer = 0) AS GpStatus

   DIM nStatus AS GpStatus, pGraphics AS GpGraphics PTR, pBitmap AS GpBitmap PTR
   DIM nWidth AS DWORD, nHeight AS DWORD
   DIM StartupInput AS GdiplusStartupInput
   DIM token AS ULONG_PTR
   Dim pixelColor As COLORREF
   dim TempDC1 as hDC
   dim TempDC2 as hDC
   dim hbit as HBITMAP
   dim xxx as LONG
   Dim frameCount AS integer
   DIM pageGuid AS GUID => ( &H86DC6274, &H8061, &H7E4C, {&H8E ,&H3F, &HEE, &H73, &H33, &HA7, &HA4, &H8 })
   Dim nCount AS LONG
   '$FrameDimensionPage       = GUID$("{7462DC86-6180-4C7E-8E3F-EE7333A7A483}")
   
    ' // Initialize GDI+
   StartupInput.GdiplusVersion = 1
   GdiplusStartup(@token, @StartupInput, NULL)
   
   DO
      nStatus = GdipCreateBitmapFromHBITMAP (hbmp, NULL, @pBitmap)
      IF pBitmap = NULL THEN EXIT DO
      GdipGetImageWidth(cast(GpImage PTR, pBitmap), @nWidth)
      GdipGetImageHeight(cast(GpImage PTR, pBitmap), @nHeight)
     
       'Full Picture
       if nRight = 0 and nBottom = 0 THEN
         nRight = nWidth   
         nBottom = nHeight   
       end if
       
       if  AspectFlag <> 0 THEN
        if nRight = 0 and nBottom = 0 THEN
          'Nothing for now
         else
           nBottom = nBottom *(nHeight/nWidth)   
        end if 
       end if
       
     MyAngle = MyAngle + 180
       
     GdipImageRotateFlip(cast(any ptr,pBitmap),6)
     
     nStatus = GdipCreateFromHDC(MyDC, @pGraphics)
     if EZP.SorP = 1 THEN   
        nStatus = GdipImageGetFrameDimensionsCount(cast(any ptr,pBitmap), @nCount)
        IF nCount THEN
            ' // Get the list of frame dimensions from the Image object.
            REDIM dimensionIDs(nCount - 1) AS GUID
            nStatus = GdipImageGetFrameDimensionsList(cast(any ptr,pBitmap), @dimensionIDs(0), nCount)
            ' // Get the number of frames in the first (and only) frame dimension.
            nStatus = GdipImageGetFrameCount(cast(any ptr,pBitmap), @dimensionIDs(0), @frameCount)
            IF frameCount = 0 THEN GOTO LExit
        END IF   
         
     END IF
     
      IF nStatus <> S_OK OR pGraphics = 0 THEN Print "Problem with Graphic DC" 
     
      nStatus = GdipBitmapGetPixel(pBitmap, 1, 1, @pixelColor)
      IF pGraphics = NULL THEN EXIT DO
      GdipSetSmoothingMode(pGraphics, SmoothingModeAntiAlias)
      GdipSetInterpolationMode(pGraphics, InterpolationModeHighQualityBicubic)
      GdipRotateWorldTransform(pGraphics,MyAngle,MatrixOrderAppend)
      GdipTranslateWorldTransform(pGraphics,x+(nRight/2), y +(nBottom/2),MatrixOrderAppend)
      if EZP.SorP = 0 THEN
         GdipDrawImageRectI(pGraphics,cast(any ptr, pBitmap),nRight/2,nBottom/2,-nRight,-nBottom)
        else
          FOR xxx = 0 TO frameCount - 1
            nStatus = GdipImageSelectActiveFrame(cast(any ptr, pBitmap), @pageGuid, xxx)
            GdipDrawImageRectI(pGraphics,cast(any ptr, pBitmap),nRight/2,nBottom/2,-nRight,-nBottom)   
          next xxx
      end if
      GdipResetWorldTransform(pGraphics)
           
      EXIT DO
   LOOP
   
   LExit:
       
   IF pBitmap THEN GdipDisposeImage(cast(GpImage PTR, pBitmap))
   IF pGraphics THEN GdipDeleteGraphics(pGraphics)
   
   ' // Shutdown GDI+
   GdiplusShutdown token
   
   RETURN nStatus

END FUNCTION


José Roca

In the above code I don't see any printer instruction.

Have you tried the AfxGdipPrintHBITMAP function in AfxGdiPlus.inc?

James Klutho

Thanks Jose.  Yeah, I looked through all of it and it was my first "go by".  Your code is very helpful.  I am still stumped - I have spent days on this.  Attached is a printer project that I am working on for a couple of months and I guess it is coming along OK.  I have spent a good chunk of time on the GDI+ stuff which I still don't feel comfortable with.  This is sort of a DDOC / Virtual Print Engine clone.

This file has 1 graphic called "It's time to review" which is on page 2.  In the code the function that controls printing is EZP_DrawBitmap (on line 1238)   This example just has a bunch of scattered objects on page to test ideas.  The print button is hard-wired to print page 2 and points to EZP_PrintDoc.  The graphic shows on the print preview just fine but for the life of me I can't get it to print.

If someone would be kind enough to look at this I would be grateful.  At this point I am blind to my problem.  By the way, I will be writing docs for this project when it is done.

Thanks

José Roca


nStatus = GdipDrawImageRectI(pGraphics,cast(any ptr, pBitmap),nRight/2,nBottom/2,-nRight,-nBottom)


Negative width and height?

José Roca

#4
BTW I prefer to use GdiPlus only, e.g.


#define UNICODE
#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "Afx/AfxPrinter.inc"
#INCLUDE ONCE "Afx/CGdiPlus/CGdiPlus.inc"
USING Afx



DIM docInfo AS DOCINFOW
docInfo.cbSize = sizeof(DOCINFOW)
DIM wszDocName AS WSTRING * 260 = "GdiplusPrint"
docInfo.lpszDocName = cast(LPWSTR, @wszDocName)
DIM hdcPrint AS HDC = CreateDCW(NULL, AfxGetDefaultPrinter, NULL, NULL)
IF hdcPrint THEN
   StartDoc(hdcPrint, @docInfo)
   StartPage(hdcPrint)
   DIM graphics AS CGpGraphics = hdcPrint
   ' // Get the DPIs of the printer
   DIM dpiX AS SINGLE = graphics.GetDpiX
   DIM dpiY AS SINGLE = graphics.GetDpiY
   ' // Calculate the width and height according to the DPIs of the printer
   DIM cx AS LONG = GetDeviceCaps(hdcPrint, HORZRES) / (dpiX / 100)
   DIM cy AS LONG = GetDeviceCaps(hdcPrint, VERTRES) / (dpiY / 100)
   ' // ---------------------------------------------------
   DIM pen AS CGpPen = CGpPen(GDIP_ARGB(255, 0, 0, 0))
   graphics.DrawLine(@pen, 50, 50, 350, 550)
   graphics.DrawRectangle(@pen, 50, 50, 300, 500)
   graphics.DrawEllipse(@pen, 50, 50, 300, 500)
   ' // ---------------------------------------------------
   EndPage(hdcPrint)
   EndDoc(hdcPrint)
   DeleteDC(hdcPrint)
END IF


James Klutho

I saw the negative width and height on quite a few examples on the internet that rotated objects (which I want to do) and I don't understand it.  I tried positive numbers but no luck when I rotated and modified the world.  This is why I said I don't understand GDI+.  The way I have it works fine to a screen DC to display a bitmap but printers seem to fail on it.  There has to be a way to rotate a bitmap map that works on both screen and a printer.  The code I have fails at home printers and on the networked printers at work.

Thanks for looking at it.

James Klutho

#6
Well I found my bitmap printing problem and programmed a kludge to fix it.  It turns out the when printing in GDI+, even though the device context may be a printer with 600 dpi, GDI+ expects the location to be is SCREEN RESOLUTION (or something close to that).  I was always printing off the page.  The below code prints the bitmap in the middle of the page whereas a GDI printer device context would be in the upper left hand corner.  Wow, I used a ream of paper to figure this out.  Jim

    'hDC is a printer DC
    GdipCreateFromHDC(hDC, @pGraphics)
    GdipCreateBitmapFromHBITMAP(hbmp, NULL, @pBitmap)
    GdipDrawImage(pGraphics, CAST(GpImage PTR, pBitmap), 400, 600)

José Roca

#7
I think that, by default, GDI+ uses UnitDisplay as the unit of measurement. If the display device is a monitor, then the unit is 1 pixel, but for printers it uses 100 of inches (see DIM cx AS LONG = GetDeviceCaps(hdcPrint, HORZRES) / (dpiX / 100) in my AfxGdipPrintHBITMAP function). To use the same coordinates, call the GdipSetPageUnit function (see http://www.jose.it-berater.org/gdiplus/reference/flatapi/graphics/gdipsetpageunit.htm ) passing the constant UnitPixel (see https://msdn.microsoft.com/en-us/library/windows/desktop/ms534405(v=vs.85).aspx ).

James Klutho