Announcement

Collapse
No announcement yet.

Simple document printing problems

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Guest's Avatar
    Guest replied
    Thank you, Timm. Picked up your new posting yesterday morning
    (Sunday), but only got round to implementing it this pm. As
    before, it works like a charm, despite adaptations to my own
    printout. It looks like this ---

    If hDC Then
    DocName = "Cost summary"
    Di.lpszDocName = VarPtr(DocName)
    Di.cbSize = SizeOf(Di)
    If StartDoc(hDC, Di) Then
    SetBkMode hDc, %TRANSPARENT

    Do
    StartPage hDC
    GoSub HeadUpCosts
    tp&=tp&+130
    SelectObject hDc, sFont&
    Do
    r$=Left$(t$,90)
    t$=Right$(t$,Len(t$)-90)
    i$=Left$(r$,10)
    r$=Right$(r$,Len(r$)-10)
    i$=Trim$(i$)
    If Left$(i$,5)="Sect " Then i$="Sect"
    x$=Left$(r$,23)
    fds$=FullDescription(x$)
    If Len(Trim$(fds$))=0 Then fds$=""
    k$=""
    GoSub Printcosts
    Loop While tp& <= ep& And Len(t$) > 89 '6290
    MoveToEx hDc, 300, tp&-20, ByVal %NULL
    LineTo hDc, 4396, tp&-20
    EndPage hDc
    Loop While Len(t$) > 89
    End If
    EndDoc hDc
    txt = ""
    DeleteDC hDc
    DeleteObject MainPen&
    DeleteObject ThckPen&
    DeleteObject WhitePen&

    The HeadUpCosts starts each page, and the Gosub Printcosts is
    quite a large chunk of code which is fed one line at a time, each
    being identified as to its specific requirements. Thanks again!

    ------------------

    Leave a comment:


  • Timm Motl
    replied
    DienyduToit...

    In your last posting it sounded like you are using a long string made up of fixed length lines that need to be parsed and printed, and
    that this long string contains more lines than you can fit on one printed page. Here's an example of how you could print a string made
    up of 100 fixed length lines (25 characters each), "paging" after you've printed 40 lines on a page.
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #INCLUDE "WIN32API.INC"
    
    
    FUNCTION PrintSomething() AS LONG
       LOCAL hDc AS LONG
       LOCAL Di  AS DocInfo
       LOCAL DocName  AS ASCIIZ * 32
       LOCAL TempText AS ASCIIZ * 1024
       LOCAL PInfo5() AS PRINTER_INFO_5
       DIM PInfo5(0:2) AS PRINTER_INFO_5
       '
       ' Creating a long output string
       PrintString$ = ""
       FOR TempLoop& = 1 TO 100
          PrintString$ = PrintString$ + "This is line number:  " + RIGHT$(STR$(1000 + TempLoop&), 3)
       NEXT
       '
       EnumPrinters %PRINTER_ENUM_DEFAULT, BYVAL %NULL, 5, BYVAL VARPTR(PInfo5(0)), SIZEOF(PInfo5(0)) * 3, Needed&, Returned&
       hDC = CreateDC(BYVAL %Null, BYVAL PInfo5(0).pPrinterName, BYVAL %Null, BYVAL %Null)
       IF hDC THEN
          DocName = "Test Print Job"
          Di.lpszDocName = VARPTR(DocName)
          Di.cbSize = SIZEOF(Di)
          IF StartDoc(hDC, Di) THEN
             JobLineCounter& = 0
             DO
                StartPage hDC
                PageLineCounter& = 0
                DO
                   INCR PageLineCounter&
                   ' Parse next line out of long string
                   TempText = MID$(PrintString$, 1 + (JobLineCounter& * 25), 25)
                   TextOut hDc, 100, PageLineCounter& * 70, TempText, BYVAL LEN(TempText)
                   INCR JobLineCounter&
                LOOP WHILE PageLineCounter& < 40 AND JobLineCounter& < 100
                EndPage hDc
             LOOP WHILE JobLineCounter& < 100
             EndDoc hDc
             TempText = ""
             DeleteDC hDc
          ELSE
             DeleteDC hDC
          END IF
       END IF
       PrintString$ = ""
    END FUNCTION
    
    
    CALLBACK FUNCTION DlgProc
       SELECT CASE CBCTL
       CASE 100
          CALL PrintSomething
       END SELECT
    END FUNCTION
    
    
    FUNCTION PBMAIN
       LOCAL hDlg AS LONG
       DIALOG NEW 0, "Printer Test",,, 200, 60, %WS_SYSMENU TO hDlg
       CONTROL ADD BUTTON, hDlg, 100, "Print", 80, 15, 40, 14
       DIALOG SHOW MODAL hDlg, CALL DlgProc
    END FUNCTION
    Timm

    Leave a comment:


  • Guest's Avatar
    Guest replied
    I notice that this bit ---

    EndPage hDc
    'StartPage hDC
    ' If you had a second page, the print commands would go here...
    'EndPage hDc
    ' Etc...
    ' Etc...
    EndDoc hDc

    --- doesn't seem to work.

    At first, I had a string of fixed length print lines, which I fed
    to the print hDC one by one in a While/wend loop. Within the loop
    I then tested for "page full" and at that point simply put in an
    EndPage and a StartPage, and continued. This hangs the machine,
    and the system freezes, or otherwise the printer is "busy on
    another task" or words to that effect.

    Then I separated the long string into two which would each fit
    into a page, and did them on separate While/wend loops, each
    with its own StartDoc and EndDoc. Same result.

    Finally, I did the first one-page string on its own, then EndPage
    AND EndDoc, and repeated all the initial printer statements, like
    this --

    '(first string = first page. This prints out)
    GoSub PrintCosts '(which While/wends until strings finished)
    EndPage hDc
    EndDoc hDc
    DeleteDC hDc

    If Len(rmn$)=0 Then EOJ 'the second string is present, so ...

    ReDim PInfo5(0:2) As PRINTER_INFO_5

    EnumPrinters %PRINTER_ENUM_DEFAULT, ByVal %NULL, 5, ByVal VarPtr(PInfo5(0)), SizeOf(PInfo5(0)) * 3, Needed&, Returned&
    hDC = CreateDC(ByVal %Null, ByVal PInfo5(0).pPrinterName, ByVal %Null, ByVal %Null)
    t$=rmn$
    rmn$=""

    If hDC Then
    DocName = "Test Print Job"
    Di.lpszDocName = VarPtr(DocName)
    Di.cbSize = SizeOf(Di)
    If StartDoc(hDC, Di) Then
    SetBkMode hDc, %TRANSPARENT
    StartPage hDC
    GoSub HeadUpCosts 'second page does not print
    GoSub PrintCosts 'instead, system hangs
    End If
    End If
    If tp&<6290 Then
    MoveToEx hDc, 300, tp&-20, ByVal %NULL
    LineTo hDc, 4390, tp&-20
    End If
    End Select
    EOJ:
    EndPage hDc
    EndDoc hDc
    txt = ""
    DeleteDC hDc
    DeleteObject MainPen&
    DeleteObject ThckPen&
    DeleteObject WhitePen&
    Else
    DeleteDC hDC
    DeleteObject MainPen&
    DeleteObject ThckPen&
    DeleteObject WhitePen&
    End If
    End If

    STILL does the same! Is there something else to be added?


    ------------------

    Leave a comment:


  • Guest's Avatar
    Guest replied
    Timm, I wasn't REALLY expecting a further posting from you, but
    it certainly solved the last problem beautifully (that mention of
    a justification problem must have sounded very much like a broad
    hint ... !).

    No more hints, broad or otherwise -- I have a lift-off, thanks to
    your help. I only wish I had a scanner so I could e-mail you an
    example of what you have made possible: the most user-friendly,
    practical, commonsense workticket (job card) for the printing
    industry on the planet. Maybe on other planets as well. Our
    quotation letter, cost summaries and many other reports will
    obviously also benefit greatly from all this.

    Thank you again.



    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    To easily position and justify text, check out SetTextAlign(), TextOut(), etc...


    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Timm Motl
    replied
    DienyduToit...

    You are right... it will be more work on your part, but as you said, you will have higher quality output and more control.
    To print justified text, simply use the DrawText command instead of TextOut. Notice the addition of a variable named RC
    that is DIMensioned AS RECT (rectangle structure) that holds the output boundries for the text you will be "drawing".

    You should check out the DrawText command in the Win32 help file for more info on that.
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #INCLUDE "WIN32API.INC"
    
    
    FUNCTION MakeFont(BYVAL Font AS STRING, BYVAL PointSize AS LONG) AS LONG
       LOCAL hDC AS LONG
       LOCAL CyPixels AS LONG
       hDC = GetDC(%HWND_DESKTOP)
       CyPixels  = GetDeviceCaps(hDC, %LOGPIXELSY)
       ReleaseDC %HWND_DESKTOP, hDC
       PointSize = (PointSize * CyPixels) \ 72
       FUNCTION = CreateFont(0 - PointSize, 0, 0, 0, %FW_NORMAL, 0, 0, 0, %ANSI_CHARSET,_
                  %OUT_TT_PRECIS, %CLIP_DEFAULT_PRECIS, %DEFAULT_QUALITY, %FF_DONTCARE, BYCOPY Font)
    END FUNCTION
    
    
    FUNCTION PrintSomething() AS LONG
       DIM RC AS RECT
       LOCAL hDc AS LONG
       LOCAL Di  AS DocInfo
       LOCAL DocName  AS ASCIIZ * 32
       LOCAL TempText AS ASCIIZ * 1024
       LOCAL PInfo5() AS PRINTER_INFO_5
       DIM PInfo5(0:2) AS PRINTER_INFO_5
       EnumPrinters %PRINTER_ENUM_DEFAULT, BYVAL %NULL, 5, BYVAL VARPTR(PInfo5(0)), SIZEOF(PInfo5(0)) * 3, Needed&, Returned&
       hDC = CreateDC(BYVAL %Null, BYVAL PInfo5(0).pPrinterName, BYVAL %Null, BYVAL %Null)
       IF hDC THEN
          DocName = "Test Print Job"
          Di.lpszDocName = VARPTR(DocName)
          Di.cbSize = SIZEOF(Di)
          IF StartDoc(hDC, Di) THEN
             SetBkMode hDc, %TRANSPARENT
             StartPage hDC
                TempText = "This is a printer test"
                hFont& = MakeFont("MS Sans Serif", 30)
                SelectObject hDc, hFont&
                ' Draw a box
                Rectangle hDc, 0, 0, 1000, 70
                ' Define some text boundries that will fit inside the box
                RC.nLeft = 10
                RC.nTop = 10
                RC.nRight = 990
                RC.nBottom = 60
                ' Print the text LEFT JUSTIFIED inside the boundries
                DrawText hDC, TempText, LEN(TempText), RC, %DT_LEFT
                ' Draw another box
                Rectangle hDc, 0, 100, 1000, 170
                ' Define some text boundries that will fit inside the box
                RC.nLeft = 10
                RC.nTop = 110
                RC.nRight = 990
                RC.nBottom = 160
                ' Print the text HORIZONTALLY CENTERED inside the boundries
                DrawText hDC, TempText, LEN(TempText), RC, %DT_CENTER
                ' Draw another box
                Rectangle hDc, 0, 200, 1000, 270
                ' Define some text boundries that will fit inside the box
                RC.nLeft = 10
                RC.nTop = 210
                RC.nRight = 990
                RC.nBottom = 260
                ' Print the text RIGHT JUSTIFIED inside the boundries
                DrawText hDC, TempText, LEN(TempText), RC, %DT_RIGHT
             EndPage hDc
             EndDoc hDc
             TempText = ""
             DeleteDC hDc
          ELSE
             DeleteDC hDC
          END IF
       END IF
    END FUNCTION
    
    
    CALLBACK FUNCTION DlgProc
       SELECT CASE CBCTL
       CASE 100
          CALL PrintSomething
       END SELECT
    END FUNCTION
    
    
    FUNCTION PBMAIN
       LOCAL hDlg AS LONG
       DIALOG NEW 0, "Printer Test",,, 200, 60, %WS_SYSMENU TO hDlg
       CONTROL ADD BUTTON, hDlg, 100, "Print", 80, 15, 40, 14
       DIALOG SHOW MODAL hDlg, CALL DlgProc
    END FUNCTION
    Timm

    Leave a comment:


  • Guest's Avatar
    Guest replied
    Timm, your most recent posting provides the solution. It does
    mean a bit more work, but it places one in complete control of
    the printed result, and the print quality is noticably superior
    to the bitmap print equivalent. True, I have a little problem
    with rows of text which must be right-justified and vertically
    right-aligned, but a solution will no doubt present itself.

    Your previous posting (some or all!) are going to be used in
    a number of cases where the print info. is always contained in a
    single screen.

    I do want to thank you for all the time and trouble -- it has
    been (and will be) of tremendous help to me.


    ------------------

    Leave a comment:


  • Timm Motl
    replied
    DienyduToit...

    Unless there is some reason that you absolutely MUST copy the contents of one dialog to another dialog, then copy the second
    dialog's image to a bitmap and then print that bitmap, I would say you are going through a lot of hoops just to print something.

    It seems it would be much simpler to use ...
    Code:
    CONTROL GET TEXT hDlg, 100 TO TempText$
    ... to get the text out of each LABEL in your first dialog and then print it using code similar to the following ...
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #INCLUDE "WIN32API.INC"
    
    
    FUNCTION MakeFont(BYVAL Font AS STRING, BYVAL PointSize AS LONG) AS LONG
       LOCAL hDC AS LONG
       LOCAL CyPixels AS LONG
       hDC = GetDC(%HWND_DESKTOP)
       CyPixels  = GetDeviceCaps(hDC, %LOGPIXELSY)
       ReleaseDC %HWND_DESKTOP, hDC
       PointSize = (PointSize * CyPixels) \ 72
       FUNCTION = CreateFont(0 - PointSize, 0, 0, 0, %FW_NORMAL, 0, 0, 0, %ANSI_CHARSET,_
                  %OUT_TT_PRECIS, %CLIP_DEFAULT_PRECIS, %DEFAULT_QUALITY, %FF_DONTCARE, BYCOPY Font)
    END FUNCTION
    
    
    FUNCTION PrintSomething() AS LONG
       LOCAL hDc AS LONG
       LOCAL Di  AS DocInfo
       LOCAL DocName  AS ASCIIZ * 32
       LOCAL TempText AS ASCIIZ * 1024
       LOCAL PInfo5() AS PRINTER_INFO_5
       DIM PInfo5(0:2) AS PRINTER_INFO_5
       EnumPrinters %PRINTER_ENUM_DEFAULT, BYVAL %NULL, 5, BYVAL VARPTR(PInfo5(0)), SIZEOF(PInfo5(0)) * 3, Needed&, Returned&
       hDC = CreateDC(BYVAL %Null, BYVAL PInfo5(0).pPrinterName, BYVAL %Null, BYVAL %Null)
       IF hDC THEN
          DocName = "Test Print Job"
          Di.lpszDocName = VARPTR(DocName)
          Di.cbSize = SIZEOF(Di)
          IF StartDoc(hDC, Di) THEN
             SetBkMode hDc, %TRANSPARENT
             StartPage hDC
                ' Draw a box
                Rectangle hDc, 0, 0, 1000, 70
                ' Print some text inside that box
                TempText = "This is a printer test..."
                hFont& = MakeFont("MS Sans Serif", 30)
                   SelectObject hDc, hFont&
                   TextOut hDc, 30, 7, TempText, BYVAL LEN(TempText)
                ' Print that same text in some different fonts
                hFont& = MakeFont("Courier New", 30)
                   SelectObject hDc, hFont&
                   TextOut hDc, 30, 107, TempText, BYVAL LEN(TempText)
                hFont& = MakeFont("Ariel Bold", 50)
                   SelectObject hDc, hFont&
                   TextOut hDc, 30, 200, TempText, BYVAL LEN(TempText)
                hFont& = MakeFont("Courier New", 50)
                   SelectObject hDc, hFont&
                   TextOut hDc, 30, 325, UCASE$(TempText), BYVAL LEN(TempText)
                ' Draw some lines
                FOR LoopVal& = 1 TO 500 STEP 50
                   MoveToEx hDc, 30, 450 + LoopVal&, BYVAL %NULL
                   LineTo hDc, 1030, 450 + LoopVal&
                NEXT
             EndPage hDc
             'StartPage hDC
                ' If you had a second page, the print commands would go here...
             'EndPage hDc
             ' Etc...
             ' Etc...
             EndDoc hDc
             TempText = ""
             DeleteDC hDc
          ELSE
             DeleteDC hDC
          END IF
       END IF
    END FUNCTION
    
    
    CALLBACK FUNCTION DlgProc
       SELECT CASE CBCTL
       CASE 100
          CALL PrintSomething
       END SELECT
    END FUNCTION
    
    
    FUNCTION PBMAIN
       LOCAL hDlg AS LONG
       DIALOG NEW 0, "Printer Test",,, 200, 60, %WS_SYSMENU TO hDlg
       CONTROL ADD BUTTON, hDlg, 100, "Print", 80, 15, 40, 14
       DIALOG SHOW MODAL hDlg, CALL DlgProc
    END FUNCTION
    Timm

    [This message has been edited by Timm Motl (edited October 02, 2000).]

    Leave a comment:


  • Guest's Avatar
    Guest replied
    Timm, the dialog is a simple document to be printed on an A4 size
    sheet. It is initially created by the application as a scrolling
    dialog and permits the user to edit certain areas of it. When the
    user opts to print it, the application creates a new dialog of
    the proportions of an A4 sheet and on this it places only labels,
    and fills these with the text contents of the original dialog
    (which may be single/multi line text boxes or labels). This
    second dialog has a few additional headings but is otherwise an
    exact replica of the first, except that it is only black and
    white (black text on a white background and containing ONLY
    labels). One such case is a very conventional letter, another is
    a workticket (job card, or whatever the term is) and there are
    also a number of ordinary reports. We stick to A4 (297 x 210 mm)
    as far as possible.

    The one I am testing with at present is the job card. Typically,
    more than half of this is visible on screen. Also, some of the
    labels are enclosed in 'boxes', which are additional labels with
    style %BLACKFRAME.

    Since receiving your code, I have experimented with the
    'save-bitmap-to-disk' as well to save TWO bitmaps for the upper
    and lower portions of the dialog (the second by setting the
    dialog loc to a negative y-value), and then trying to print both
    in one print call, but so far no success. It may be that one
    should create the black and white dialog twice, once for the top
    and then once more for the lower portion.

    As mentioned, I have now (for the third time) ordered the Petzold
    book, and MAY be third-time-lucky. If so, that might just make a
    world of difference to my 'hits' on this forum! Who knows, I may
    even become a contributor instead of perennial beginner ...




    ------------------

    Leave a comment:


  • Timm Motl
    replied
    DienyduToit...

    The samples I posted use the GetWindowRect API call to determine the region to copy to the bitmap. This limits you to whatever is visible in the dialog. Maybe if you could more fully describe what your dialog contains that needs to be printed, there might be another way to approach it.

    Timm

    Leave a comment:


  • Guest's Avatar
    Guest replied
    Timm, thank you for all that time and trouble. This works as you
    said it would. I use your second option which is perfect for the
    purpose, giving the print dialog first (number of copies option
    etc.) and then print - in this case there is no purpose in saving
    the image to a disk file, but I can see that there will be uses
    for that one as well.

    In my present case, the dialog is larger than the screen,
    however. I have tried scaling down sizes and fonts
    proportionately so that the whole dialog would be visible, but
    this makes everthing too small -- the printed text gets to be
    distorted. The printed output is supposed to be portrait, 297mm
    deep by 210mm wide (A4) and this is not in line with screen
    proportions. The original dialog is virtually the same size as
    th A4 sheet and that prints perfectly -- but of course, only the
    visible part.

    Is there perhaps a way to create the bitmap for the visible
    portion, then update the dialog - or scroll it upwards - and then
    ADD this to the first bitmap before printing?

    Amazingly, browsing the Internet yesterday, I found a shop which
    DOES have the Petzold 5th edition, and promptly ordered
    (enormous price -- will read it in Debtors Prison).


    ------------------

    Leave a comment:


  • Timm Motl
    replied
    DienyduToit...

    Here's the example that prints directly to the default printer.
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #INCLUDE "WIN32API.INC"
    #INCLUDE "COMDLG32.INC"
    
    
    GLOBAL hDlg      AS LONG
    GLOBAL BMPLeft   AS DOUBLE
    GLOBAL BMPTop    AS DOUBLE
    GLOBAL BMPWidth  AS DOUBLE
    GLOBAL BMPHeight AS DOUBLE
    
    
    FUNCTION PrintDialog() AS LONG
       LOCAL X             AS LONG
       LOCAL Y             AS LONG
       LOCAL W             AS LONG
       LOCAL H             AS LONG
       LOCAL BMP           AS BITMAP
       LOCAL BMPI          AS BITMAPINFO
       LOCAL BMPrc         AS RECT
       LOCAL BMPMem        AS STRING
       LOCAL BMPMemPtr     AS LONG
       LOCAL BMPSize       AS LONG
       LOCAL hBMP          AS LONG
       LOCAL dcBMP         AS LONG
       LOCAL hDC           AS LONG
       LOCAL Copies        AS LONG
       LOCAL PDOptions     AS LONG
       LOCAL BMPPrinter    AS LONG
       LOCAL DocumentInfo  AS DOCINFO
       LOCAL DocumentName  AS ASCIIZ * 255
       DIM PInfo5(0:2) AS PRINTER_INFO_5
       EnumPrinters %PRINTER_ENUM_DEFAULT, BYVAL %NULL, 5, BYVAL VARPTR(PInfo5(0)), SIZEOF(PInfo5(0)) * 3, Needed&, Returned&
       BMPPrinter = CreateDC(BYVAL %NULL, BYVAL PInfo5(0).pPrinterName, BYVAL %NULL, BYVAL %NULL)
       IF BMPPrinter THEN
          GetWindowText hDlg, DocumentName, 255
          DocumentInfo.lpszDocName = VARPTR(DocumentName)
          DocumentInfo.lpszOutput = 0
          StartDoc BMPPrinter, DocumentInfo
          StartPage BMPPrinter
          X = GetDeviceCaps(BMPPrinter, %LOGPIXELSX) * BMPLeft
          Y = GetDeviceCaps(BMPPrinter, %LOGPIXELSY) * BMPTop
          W = GetDeviceCaps(BMPPrinter, %LOGPIXELSX) * BMPWidth
          H = GetDeviceCaps(BMPPrinter, %LOGPIXELSY) * BMPHeight
          GetWindowRect hDlg, BMPrc
          BMPI.bmiHeader.biSize = SIZEOF(BMPI.bmiHeader)
          BMPI.bmiHeader.biWidth = (BMPrc.nRight - BMPrc.nLeft)
          BMPI.bmiHeader.biHeight = (BMPrc.nBottom - BMPrc.nTop)
          BMPI.bmiHeader.biPlanes = 1
          BMPI.bmiHeader.biBitCount = 24
          BMPI.bmiHeader.biCompression = 0
          BMPSize = BMPI.bmiHeader.biWidth
          BMPSize = (BMPSize + 1) * (BMPI.bmiHeader.biBitCount / 8)
          BMPSize = ((BMPSize + 3) / 4) * 4
          BMPSize = BMPSize * BMPI.bmiHeader.biHeight
          BMPMem = STRING$(BMPSize, CHR$(0))
          BMPMemPtr = STRPTR(BMPMem)
          hDC = GetDC(0)
          dcBMP = CreateCompatibleDC(hDC)
          hBMP = CreateDIBSection(dcBMP, BMPI, 0, 0, 0, 0)
          GlobalLock hBMP
          SelectObject dcBMP, hBMP
          GetObject hBMP, SIZEOF(BMP), BMP
          BitBlt dcBMP, 0, 0, BMP.bmWidth, BMP.bmHeight, hDC, BMPrc.nLeft, BMPrc.nTop, %SRCCOPY
          IF (BMP.bmWidth / BMP.bmHeight) > (W / H) THEN
             H = W * BMP.bmHeight / BMP.bmWidth
          ELSE
             W = H * BMP.bmWidth / BMP.bmHeight
          END IF
          GetDIBits dcBMP, hBMP, 0, BMPI.bmiHeader.biHeight, BYVAL BMPMemPtr, BMPI, 0
          StretchDIBits BMPPrinter, X, Y, W, H, 0, 0, BMPI.bmiHeader.biWidth, _
                        BMPI.bmiHeader.biHeight, BYVAL BMPMemPtr, BMPI, 0, %SRCCOPY
          GlobalUnlock hBMP
          DeleteObject hBMP
          DeleteDC dcBMP
          ReleaseDC 0, hDC
          BMPMem = ""
          EndPage BMPPrinter
          EndDoc BMPPrinter
          DeleteDC BMPPrinter
       END IF
    END FUNCTION
    
    
    CALLBACK FUNCTION DlgProc
       SELECT CASE CBCTL
       CASE 102
          PrintDialog
       END SELECT
    END FUNCTION
    
    
    FUNCTION PBMAIN
       BMPLeft   = 0.5  ' Where to print your dialog image... margins on paper (in inches)
       BMPTop    = 0.5
       BMPWidth  = 6.0  ' What size to print your dialog image (in inches)
       BMPHeight = 4.0
       DIALOG NEW 0, "My Dialog",,, 300, 200, %WS_SYSMENU TO hDlg
       CONTROL ADD LABEL, hDlg, 101, "Click OK to print a copy of this dialog...", 85, 60, 190, 12
       CONTROL ADD BUTTON, hDlg, 102, "OK", 130, 160, 40, 15
       DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
    Timm

    Leave a comment:


  • Timm Motl
    replied
    DienyduToit...

    My first response to you gives an example of printing an image of a dialog by first
    writing it to a disk file (C:\TEMP.BMP) and then printing/deleting that file.

    This example will send the output to the printer without using a disk file. It still
    uses the Windows Print Dialog Box to let you select the number of copies to print.
    My next posting will contain an example that sends the dialog image directly to the
    current default printer without using the Windows Print Dialog Box.

    In all three of these examples, you must be sure that the BITMAPINFO declaration in
    your WIN32API.INC file matches the example I gave you in my first response.
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #INCLUDE "WIN32API.INC"
    #INCLUDE "COMDLG32.INC"
    
    
    GLOBAL hDlg      AS LONG
    GLOBAL BMPLeft   AS DOUBLE
    GLOBAL BMPTop    AS DOUBLE
    GLOBAL BMPWidth  AS DOUBLE
    GLOBAL BMPHeight AS DOUBLE
    
    
    FUNCTION PrintDialog() AS LONG
       LOCAL X             AS LONG
       LOCAL Y             AS LONG
       LOCAL W             AS LONG
       LOCAL H             AS LONG
       LOCAL BMP           AS BITMAP
       LOCAL BMPI          AS BITMAPINFO
       LOCAL BMPrc         AS RECT
       LOCAL BMPMem        AS STRING
       LOCAL BMPMemPtr     AS LONG
       LOCAL BMPSize       AS LONG
       LOCAL hBMP          AS LONG
       LOCAL dcBMP         AS LONG
       LOCAL hDC           AS LONG
       LOCAL Copies        AS LONG
       LOCAL PDOptions     AS LONG
       LOCAL BMPPrinter    AS LONG
       LOCAL DocumentInfo  AS DOCINFO
       LOCAL DocumentName  AS ASCIIZ * 255
       Copies = 1
       PDOptions = %PD_COLLATE + %PD_HIDEPRINTTOFILE + %PD_NOSELECTION + %PD_PAGENUMS + %PD_RETURNDC
       PrinterDialog 0, PDOptions, BMPPrinter, Copies, 1, 1, 1, 1
       IF BMPPrinter THEN
          GetWindowText hDlg, DocumentName, 255
          DocumentInfo.lpszDocName = VARPTR(DocumentName)
          DocumentInfo.lpszOutput = 0
          StartDoc BMPPrinter, DocumentInfo
          FOR PrintLoop& = 1 TO Copies
             StartPage BMPPrinter
             X = GetDeviceCaps(BMPPrinter, %LOGPIXELSX) * BMPLeft
             Y = GetDeviceCaps(BMPPrinter, %LOGPIXELSY) * BMPTop
             W = GetDeviceCaps(BMPPrinter, %LOGPIXELSX) * BMPWidth
             H = GetDeviceCaps(BMPPrinter, %LOGPIXELSY) * BMPHeight
             GetWindowRect hDlg, BMPrc
             BMPI.bmiHeader.biSize = SIZEOF(BMPI.bmiHeader)
             BMPI.bmiHeader.biWidth = (BMPrc.nRight - BMPrc.nLeft)
             BMPI.bmiHeader.biHeight = (BMPrc.nBottom - BMPrc.nTop)
             BMPI.bmiHeader.biPlanes = 1
             BMPI.bmiHeader.biBitCount = 24
             BMPI.bmiHeader.biCompression = 0
             BMPSize = BMPI.bmiHeader.biWidth
             BMPSize = (BMPSize + 1) * (BMPI.bmiHeader.biBitCount / 8)
             BMPSize = ((BMPSize + 3) / 4) * 4
             BMPSize = BMPSize * BMPI.bmiHeader.biHeight
             BMPMem = STRING$(BMPSize, CHR$(0))
             BMPMemPtr = STRPTR(BMPMem)
             hDC = GetDC(0)
             dcBMP = CreateCompatibleDC(hDC)
             hBMP = CreateDIBSection(dcBMP, BMPI, 0, 0, 0, 0)
             GlobalLock hBMP
             SelectObject dcBMP, hBMP
             GetObject hBMP, SIZEOF(BMP), BMP
             BitBlt dcBMP, 0, 0, BMP.bmWidth, BMP.bmHeight, hDC, BMPrc.nLeft, BMPrc.nTop, %SRCCOPY
             IF (BMP.bmWidth / BMP.bmHeight) > (W / H) THEN
                H = W * BMP.bmHeight / BMP.bmWidth
             ELSE
                W = H * BMP.bmWidth / BMP.bmHeight
             END IF
             GetDIBits dcBMP, hBMP, 0, BMPI.bmiHeader.biHeight, BYVAL BMPMemPtr, BMPI, 0
             StretchDIBits BMPPrinter, X, Y, W, H, 0, 0, BMPI.bmiHeader.biWidth, _
                           BMPI.bmiHeader.biHeight, BYVAL BMPMemPtr, BMPI, 0, %SRCCOPY
             GlobalUnlock hBMP
             DeleteObject hBMP
             DeleteDC dcBMP
             ReleaseDC 0, hDC
             BMPMem = ""
             EndPage BMPPrinter
          NEXT
          EndDoc BMPPrinter
          DeleteDC BMPPrinter
       END IF
    END FUNCTION
    
    
    CALLBACK FUNCTION DlgProc
       SELECT CASE CBCTL
       CASE 102
          PrintDialog
       END SELECT
    END FUNCTION
    
    
    FUNCTION PBMAIN
       BMPLeft   = 0.5  ' Where to print your dialog image... margins on paper (in inches)
       BMPTop    = 0.5
       BMPWidth  = 6.0  ' What size to print your dialog image (in inches)
       BMPHeight = 4.0
       DIALOG NEW 0, "My Dialog",,, 300, 200, %WS_SYSMENU TO hDlg
       CONTROL ADD LABEL, hDlg, 101, "Click OK to print a copy of this dialog...", 85, 60, 190, 12
       CONTROL ADD BUTTON, hDlg, 102, "OK", 130, 160, 40, 15
       DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
    Timm

    [This message has been edited by Timm Motl (edited September 30, 2000).]

    Leave a comment:


  • Timm Motl
    replied
    DienyduToit...

    From the sound of your request, I think this is what you are looking for...

    First you must edit your WIN32API.INC file and make sure the BITMAPINFO declaration matches the following...
    Code:
    TYPE BITMAPINFO
       bmiHeader AS BITMAPINFOHEADER
       bmiColors(256) AS RGBQUAD
    END TYPE
    Then you should be able to successfully run this code...
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #INCLUDE "WIN32API.INC"
    #INCLUDE "COMDLG32.INC"
    
    
    GLOBAL hDlg      AS LONG
    GLOBAL BMPLeft   AS DOUBLE
    GLOBAL BMPTop    AS DOUBLE
    GLOBAL BMPWidth  AS DOUBLE
    GLOBAL BMPHeight AS DOUBLE
    
    
    FUNCTION SaveBMPFile() AS LONG
       LOCAL BMPFile       AS LONG
       LOCAL hBMPMem       AS LONG
       LOCAL hDC           AS LONG
       LOCAL hDCMem        AS LONG
       LOCAL BMPrc         AS RECT
       LOCAL BMP           AS BITMAP
       LOCAL BMPI          AS BITMAPINFO
       LOCAL BMPFileHeader AS BITMAPFILEHEADER
       LOCAL BMPInfoHeader AS BITMAPINFOHEADER
    
       GetWindowRect hDlg, BMPrc
    
       BMPI.bmiHeader.biSize = SIZEOF(BMPI.bmiHeader)
       BMPI.bmiHeader.biWidth = (BMPrc.nRight - BMPrc.nLeft)
       BMPI.bmiHeader.biHeight = (BMPrc.nBottom - BMPrc.nTop)
       BMPI.bmiHeader.biPlanes = 1
       BMPI.bmiHeader.biBitCount = 24
       BMPI.bmiHeader.biCompression = 0
    
       hDC = GetDC(0)
       hDCMem = CreateCompatibleDC (hDC)
       hBMPMem = CreateDIBSection(hDCMem, BMPI, 0, 0, 0, 0)
       GlobalLock hBMPMem
       SelectObject hDCMem, hBMPMem
       GetObject hBMPMem, SIZEOF(BMP), BMP
       BitBlt hDCMem, 0, 0, BMP.bmWidth, BMP.bmHeight, hDC, BMPrc.nLeft, BMPrc.nTop, %SRCCOPY
    
       BMPFileHeader.bfType = CVI("BMP")
       BMPFileHeader.bfSize = LEN(BMPFileHeader) + LEN(BMPInfoHeader) + BMP.bmWidthBytes * BMP.bmHeight
       BMPFileHeader.bfOffBits = 54
       BMPInfoHeader.biSize = 40
       BMPInfoHeader.biWidth = BMP.bmWidth
       BMPInfoHeader.biHeight = BMP.bmHeight
       BMPInfoHeader.biPlanes = 1
       BMPInfoHeader.biBitCount = 24
       BMPInfoHeader.biSizeImage = (BMP.bmWidthBytes * BMP.bmHeight) + 54
    
       BMPFile = FREEFILE
       OPEN "C:\TEMP.BMP" FOR OUTPUT AS #BMPFile
       PRINT #BMPFile, BMPFileHeader BMPInfoHeader PEEK$(BMP.bmBits, (BMP.bmWidthBytes * BMP.bmHeight));
       CLOSE #BMPFile
    
       ReleaseDC 0, hDC
       DeleteDC hDCMem
       GlobalUnlock hBMPMem
       DeleteObject hBMPMem
    END FUNCTION
    
    
    FUNCTION PrintBMPFile() AS LONG
       LOCAL X            AS LONG
       LOCAL Y            AS LONG
       LOCAL W            AS LONG
       LOCAL H            AS LONG
       LOCAL BMP          AS BITMAP
       LOCAL BMPI         AS BITMAPINFO
       LOCAL BMPMem       AS STRING
       LOCAL BMPMemPtr    AS LONG
       LOCAL BMPSize      AS LONG
       LOCAL hBMP         AS LONG
       LOCAL dcBMP        AS LONG
       LOCAL Copies       AS LONG
       LOCAL PDOptions    AS LONG
       LOCAL BMPPrinter   AS LONG
       LOCAL DocumentInfo AS DOCINFO
       LOCAL DocumentName AS ASCIIZ * 255
    
       Copies = 1
       PDOptions = %PD_COLLATE + %PD_HIDEPRINTTOFILE + %PD_NOSELECTION + %PD_PAGENUMS + %PD_RETURNDC
       PrinterDialog 0, PDOptions, BMPPrinter, Copies, 1, 1, 1, 1
       IF BMPPrinter THEN
          DocumentName = "C:\TEMP.BMP"
          DocumentInfo.lpszDocName = VARPTR(DocumentName)
          DocumentInfo.lpszOutput = 0
          StartDoc BMPPrinter, DocumentInfo
          FOR PrintLoop& = 1 TO Copies
             StartPage BMPPrinter
             X = GetDeviceCaps(BMPPrinter, %LOGPIXELSX) * BMPLeft
             Y = GetDeviceCaps(BMPPrinter, %LOGPIXELSY) * BMPTop
             W = GetDeviceCaps(BMPPrinter, %LOGPIXELSX) * BMPWidth
             H = GetDeviceCaps(BMPPrinter, %LOGPIXELSY) * BMPHeight
    
             hBMP = LoadImage(0, "C:\TEMP.BMP", %IMAGE_BITMAP, 0, 0, %LR_LOADFROMFILE)
    
             hDesktop& = GetDesktopWindow()
             dcWindow& = GetDC(hDesktop&)
             dcBMP = CreateCompatibleDC(dcWindow&)
             ReleaseDC hDesktop&, dcWindow&
             GetObject hBMP, LEN(BMP), BMP
    
             BMPI.bmiHeader.biSize = LEN(BMPI.bmiHeader)
             BMPI.bmiHeader.biWidth = BMP.bmWidth
             BMPI.bmiHeader.biHeight = BMP.bmHeight
             BMPI.bmiHeader.biPlanes = 1
             BMPI.bmiHeader.biBitCount = BMP.bmBitsPixel
             BMPI.bmiHeader.biCompression = 0
    
             BMPSize = BMPI.bmiHeader.biWidth
             BMPSize = (BMPSize + 1) * (BMPI.bmiHeader.biBitCount / 8)
             BMPSize = ((BMPSize + 3) / 4) * 4
             BMPSize = BMPSize * BMPI.bmiHeader.biHeight
             BMPMem = STRING$(BMPSize, CHR$(0))
    
             IF (BMP.bmWidth / BMP.bmHeight) > (W / H) THEN
                H = W * BMP.bmHeight / BMP.bmWidth
             ELSE
                W = H * BMP.bmWidth / BMP.bmHeight
             END IF
    
             BMPMemPtr = STRPTR(BMPMem)
    
             GetDIBits dcBMP, hBMP, 0, BMPI.bmiHeader.biHeight, BYVAL BMPMemPtr, BMPI, 0
    
             StretchDIBits BMPPrinter, X, Y, W, H, 0, 0, BMPI.bmiHeader.biWidth, _
                           BMPI.bmiHeader.biHeight, BYVAL BMPMemPtr, BMPI, 0, %SRCCOPY
    
             DeleteObject hBMP
             DeleteDC dcBMP
             BMPMem = ""
             EndPage BMPPrinter
          NEXT
          EndDoc BMPPrinter
          DeleteDC BMPPrinter
       END IF
    END FUNCTION
    
    
    CALLBACK FUNCTION DlgProc
       SELECT CASE CBCTL
       CASE 102
          SaveBMPFile
          PrintBMPFile
          KILL "C:\TEMP.BMP"
       END SELECT
    END FUNCTION
    
    
    FUNCTION PBMAIN
       BMPLeft   = 0.5  ' Where to print your dialog image... margins on paper (in inches)
       BMPTop    = 0.5
       BMPWidth  = 6.0  ' What size to print your dialog image (in inches)
       BMPHeight = 4.0
       DIALOG NEW 0, "My Dialog",,, 300, 200, %WS_SYSMENU TO hDlg
       CONTROL ADD LABEL, hDlg, 101, "Click OK to print a copy of this dialog...", 85, 60, 190, 12
       CONTROL ADD BUTTON, hDlg, 102, "OK", 130, 160, 40, 15
       DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
    Timm

    [This message has been edited by Timm Motl (edited September 30, 2000).]

    Leave a comment:


  • Guest's Avatar
    Guest started a topic Simple document printing problems

    Simple document printing problems

    Rightaway, I must mention that I have so far been unable to
    obtain a Petzold (or similar) book -- have had the Petzold one
    on order for months, but hus far no joy.

    The code below is a concoction, or cocktail, or borrowed snippets
    from bulletin board postings and the FILES &c.

    I have pasted in the relevant bits from the WinAPI help to make
    it a blow-by-blow story.

    It does not bomb our or hang: it simply does not work. I'm sure
    there is a twenty-line piece of code somewhere which will do the
    trick -- mine turns out a pristinely clean white page with
    nothing on it.

    The document to be printed is a ready created dialog (wDlg&),
    which I am attempting to get into a compatible bitmap and then
    print, but no dice.

    Can somebody help, please?
    '___________________________________________________________________________________________________________

    (This function is from a posting by Jozsef Hegyi in late August)

    Function GetPrinterDC () As Long

    Local pInfo5() As PRINTER_INFO_5,_
    dwNeeded As Long,_
    dwReturned As Long,_
    iUpper As Long,_
    pByte As Byte Ptr,_
    szNull As Asciiz*0

    pByte = VarPtr(szNull)
    Call EnumPrinters (%PRINTER_ENUM_LOCAL, ByVal %NULL, 5, @pByte, 0, dwNeeded, dwReturned)

    iUpper = dwNeeded\SizeOf(pInfo5(0))
    ReDim pInfo5(0: iUpper)
    pByte = VarPtr(pInfo5(0))
    If EnumPrinters (%PRINTER_ENUM_DEFAULT, ByVal %NULL, 5, @pByte, _
    (iUpper+1)*SizeOf(pInfo5(0)), dwNeeded, dwReturned) Then
    Function = CreateDC (ByVal %NULL, pInfo5(0)[email protected], ByVal %NULL, ByVal %NULL)
    Else
    Function = 0
    End If
    End Function
    '___________________________________________________________________________________________________________

    Sub PrintThisScreen

    Local pd As PRINTDLGAPI
    Local di As DOCINFO
    Local dn As Asciiz * 64
    Local hWnd As Long
    Local hDC As Long
    Local hBmp As Long
    Local hBmpDC As Long
    Local r As RECT
    Local x As Long
    Local y As Long
    Local bmp As Bitmap
    Local pDC As Long

    ' Create a normal DC And a memory DC For the dialog. The
    ' normal DC provides a "snapshot" of the screen contents. The
    ' memory DC keeps a copy of this "snapshot" in the associated
    ' bitmap.

    hWnd = wDlg& 'wDlg& contains the visible material to be printed)
    GetWindowRect hWnd, r
    hdcScreen& = GetDC(hWnd)

    'To store an image temporarily, your application must call CreateCompatibleDC to create
    'a DC that is compatible with the current window DC.

    hdcCompatible& = CreateCompatibleDC(hdcScreen&)

    'After you create a compatible DC, you create a bitmap with the appropriate dimensions
    'by calling the CreateCompatibleBitmap function and then select it into this device
    'context by calling the SelectObject function.
    ' Create a compatible bitmap For hdcScreen.

    hbmScreen& = CreateCompatibleBitmap(hdcScreen&, _
    GetDeviceCaps(hdcScreen&, %HORZRES), _
    GetDeviceCaps(hdcScreen&, %VERTRES))

    If hbmScreen& = 0 Then
    MsgBox("hbmScreen& is at zero")
    DeleteDC hdcScreen&
    Exit Sub
    End If

    ' Select the bitmap into the compatible DC.

    Call SelectObject(hdcCompatible&, hbmScreen&)

    'After the compatible device context is created and the appropriate bitmap has been
    'selected into it, you can capture the image.

    'The Win32 API provides the BitBlt function to capture images. This function
    'performs a bit block transfer - that is, it copies data from a source bitmap
    'into a destination bitmap.

    'Because it copies data from bitmaps, you'd expect that two arguments to this
    'function would be bitmap handles; however, this is not the case. Instead,
    'BitBlt receives handles that identify two device contexts and copies the
    'bitmap data from a bitmap selected into the source DC into a bitmap
    'selected into the target DC. In this case, the target DC is the compatible
    'DC, so when BitBlt completes the transfer, the image has been stored in memory.

    ' Copy data for the selected display into a
    ' bitmap that is selected into a compatible DC.

    ' Call ShowWindow (hwnd, %SW_HIDE)

    GetObject hbmScreen&, SizeOf(bmp), bmp

    Call BitBlt(hdcCompatible&, _
    0,0, _
    bmp.bmWidth, bmp.bmHeight, _
    hdcScreen&, _
    0,0, _
    %SRCCOPY)

    ' pd.lStructSize = SizeOf(pd)
    ' pd.Flags = %PD_NOSELECTION Or %PD_NOPAGENUMS Or %PD_USEDEVMODECOPIES Or %PD_RETURNDC
    ' pd.hWndOwner = hWnd '%HWND_DESKTOP

    pd.lStructSize = SizeOf(pd)
    pd.hDevMode = %Null '(Handle) %Null
    pd.hDevNames = %Null '(Handle) %Null
    pd.Flags = %PD_RETURNDC
    pd.hwndOwner = hwnd
    pd.hDC = %Null '(HDC) %Null
    pd.nFromPage = 1
    pd.nToPage = 1
    pd.nMinPage = 0
    pd.nMaxPage = 0
    pd.nCopies = 1
    pd.hInstance = %Null '(Handle) %Null
    ' pd.lCustData = 0L
    ' pd.lpfnPrintHook = (LPPRINTHOOKPROC) %Null
    ' pd.lpfnSetupHook = (LPSETUPHOOKPROC) %Null
    ' pd.lpPrintTemplateName = %Null '(%LPSTR) %Null
    ' pd.lpSetupTemplateName = %Null '(%LPSTR) %Null
    ' pd.hPrintTemplate = %Null '(Handle) %Null
    ' pd.hSetupTemplate = %Null '(Handle) %Null

    ' Display the Print Dialog box.

    ' PrintDlg(pd)

    If IsFalse PrintDlg(pd) Then
    Exit Sub
    End If
    ' hBmpDC=GetPrinterDC
    ' pDC = CreateCompatibleDC(hBmpDC)

    dn = "Printer Test"
    di.cbSize = SizeOf(di)
    di.lpszDocName = VarPtr(dn)

    If StartDoc(pd.hDC, di) > 0 Then
    If StartPage(pd.hDC) <= 0 Then
    DeleteDC hDC
    DeleteDC hBmpDC
    ' DeleteDC pd.hDC
    DeleteDC hdcScreen&
    Exit Sub
    End If

    hBmpDC=pd.hDC 'GetPrinterDC
    pDC = CreateCompatibleDC(hBmpDC)

    ' x = GetDeviceCaps(pd.hDC, %HORZRES)
    ' y = CLng((x / r.nRight) * r.nBottom)

    'To redisplay the image, call BitBlt a second time, specifying the compatible DC
    'as the source DC and a window (or printer) DC as the target DC.

    Call BitBlt(pDC, _
    0,0, _
    bmp.bmWidth, bmp.bmHeight, _
    hdcCompatible&, _
    0,0, _
    %SRCCOPY)

    If EndPage(pd.hDC) <= 0 Then
    DeleteDC hDC
    DeleteDC hBmpDC
    DeleteDC pd.hDC
    DeleteDC hdcScreen&
    Exit Sub
    End If
    End If

    EndDoc pd.hDC
    DeleteDC hDC
    DeleteDC hBmpDC
    DeleteDC pd.hDC
    DeleteDC hdcScreen&
    End Sub
    '___________________________________________________________________________________________________________

    ------------------
Working...
X