Announcement

Collapse
No announcement yet.

Fun with printers?!?

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

  • Fun with printers?!?

    I've been reading through past postings regarding the
    Common Dialog printer set-up.

    I've added the following code to my app:

    Code:
    GLOBAL pd AS PRINTDLGAPI
    ...
      pd.lStructSize = LEN(PRINTDLGAPI)
      pd.Flags = %PD_HIDEPRINTTOFILE OR %PD_NOPAGENUMS OR %PD_NOSELECTION OR %PD_USEDEVMODECOPIESANDCOLLATE
      PrintDlg pd
    ...
    so far, so good. This creates the printer dialog and appears to
    work just fine.

    Later, I've added:

    Code:
       LOCAL szTemp AS ASCIIZ * 260
       LOCAL ptrDM AS DEVMODE PTR
    ...
          IF pd.hDevMode THEN
             ptrDM = pd.hDevMode
             szTemp = @ptrDM.dmDeviceName
             PrintFmt.hDCPrinter = CreateDC( "", szTemp, "", BYVAL pd.hDevMode )
    MSGBOX "hDC="+STR$( PrintFmt.hDCPrinter)+", szTemp = " + szTemp
          END IF
    
    
    ' <Farpoint Spread SSPrint call>
    
    
          IF pd.hDevMode THEN
             GlobalFree pd.hDevMode
             GlobalFree pd.hDevNames
             DeleteDC PrintFmt.hDCPrinter
          END IF
    The message box indicates that szTemp is garbage (approx 3 chars).
    CreateDC returns 0.

    Is there something obvious that I'm missing?

    Help!



    ------------------
    Bernard Ertl
    Bernard Ertl
    InterPlan Systems

  • #2
    hDevmode is usually only a handle, not a pointer (unless %GMEM_FIXED is specified in the GlobalAlloc call, but I do not believe that PrintDlg() uses that flag when it allocates the DM structure block).

    Therefore, you probably have to use something like this:
    Code:
    ptrDM = GlobalLock(pd.hDevMode)
    @ptrdm...
    GlobalUnlock pd.hDevMode
    GlobalFree pd.hDevMode
    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      He shoots.... He scores!

      Thanks Lance. Problem solved.



      ------------------
      Bernard Ertl
      Bernard Ertl
      InterPlan Systems

      Comment


      • #4
        OK. On to the next stumbling block....

        I've got :

        Code:
        ...
          IF <Print to printer> THEN
              IF pd.hDevMode THEN
                 ptrDM = GlobalLock( pd.hDevMode)
                 szTemp = @ptrDM.dmDeviceName
                 PrintFmt.hDCPrinter = CreateDC( "", szTemp, "", @ptrDM )
              END IF
              ' <Farpoint Spread SSPrint call>
              IF PrintFmt.hDCPrinter THEN DeleteDC PrintFmt.hDCPrinter
           END IF
        
        
           'Release memory even if not printing....
           IF pd.hDevMode THEN
              GlobalUnlock pd.hDevMode
              GlobalFree pd.hDevMode
              GlobalFree pd.hDevNames
              pd = initpd
           END IF
        When printing, I get a message box stating:

        "Already printing: <crlf>
        <my report name>"

        The printer queue shows an entry for my print
        job, but printing page zero of <X> pages.

        As soon as I click OK on the message box, I get
        another message box titled "Printers Folder"
        which states that there was an error writing
        to the printer - "The specified procedure could not be found."

        Any ideas what is (could be) causing this?


        ------------------
        Bernard Ertl

        [This message has been edited by Bern Ertl (edited July 23, 2001).]
        Bernard Ertl
        InterPlan Systems

        Comment


        • #5
          Never mind. I rebooted my machine and the error
          messages vanished.

          The code is printing now. Must have been some left over
          garbage in memory from earlier attempts.

          However, either I misunderstood the Win32.HLP or something is fishy:

          PD_USEDEVMODECOPIESANDCOLLATE

          Disables the Copies edit control if the printer driver does not support multiple copies, and disables the Collate checkbox if the printer driver does not support collation. If this flag is not specified, PrintDlg stores the user selections for the Copies and Collate options in the dmCopies and dmCollate members of the DEVMODE structure.

          If this flag isn't set, the copies and collate information is returned in the DEVMODE structure if the driver supports multiple copies and collation. If the driver doesn't support multiple copies and collation, the information is returned in the PRINTDLG structure. This means that an application only has to look at nCopies and PD_COLLATE to determine how many copies it needs to render and whether it needs to print them collated.
          I understood this to mean that with the flag set as I have it, the
          collate option would only be enabled if the printer driver supported it.
          In this case, if chosen, the dmCollate field of the DEVMODE structure
          would be set and I don't have to do any special processing when printing
          (ie. the printer device context would handle it automatically when
          initialized with this DEVMODE structure).

          In testing, the # of copies is working as expected, but it is
          not collating.



          ------------------
          Bernard Ertl
          Bernard Ertl
          InterPlan Systems

          Comment


          • #6
            With the pd_usedevmodecopiesandcollate flag on:
            You only have to check the devmode structure for copies
            no collation is done if the printer driver does not do it for you

            With the flag off:
            You have to check both the devmode and the pd structures for copies and collate, using the "highest" result from each

            Here is a sample from one of my printers (HP LJ 4000), with two copies selected. This printer driver does not support collation!
            Flag on:
            Collate box is disabled
            PD copies = 1, PD collate is off
            DM copies = 2, DM collate is off

            Flag off, collate is checked:
            PD copies = 2, PD collate is on
            DM copies = 1, DM collate is off

            Flag off, collate not checked:
            PD copies = 1, PD collate is off
            DM copies = 2, DM collate is off


            In summary, using the flag is easier, but with no collation unless the printer driver supports it. If you need to offer collation, you cannot use the flag.

            ------------------
            Dennis
            mailto:[email protected][email protected]</A>

            Comment


            • #7
              Thanks Dennis, that is what I thought was supposed to happen.

              I think I need to test with another printer driver.

              I'm currently using an NEC Superscript 860 laser printer. With
              the flag ON, the collate box is enabled, but whether I check it
              or not, the output remains non-collated. Perhaps the driver is
              screwed up.....



              ------------------
              Bernard Ertl
              Bernard Ertl
              InterPlan Systems

              Comment


              • #8
                I always prefer to use the PD_USEDEVMODECOPIESANDCOLLATE flag, and my printing code just tests the PD structure flags and copies fields to determine what should be done by MY code.

                The last sentence of the quote from MSDN is the clue here: if the the PD_COLLATE flag is set in the PD structure, YOUR code has to handle the collation (ie, the driver won't handle the collation for you).

                Same applies to the 'PD.nCopies' member; your code should print as many copies as that field indicates. That is, if PD.ncopies = 1 and multiple copies are selected by the user, your code only needs to print 1 copy and the driver will handle the rest for you.

                While I've never experimented with it, you may try adjusting the spool setting for "Start Printing After Last Page is Spooledd" rather than "After 1st Page is Spooled" and see if that makes any difference.

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

                Comment


                • #9
                  Hi Lance,

                  Your last post is befuddling .

                  I understood that if the PD_USEDEVMODECOPIESANDCOLLATE flag is set
                  and the driver does not support collation, the check box would be
                  disabled. Thus the PD_COLLATE flag should never have the opportunity
                  to be set.

                  What I'm gathering from your last post is that the PD_USEDEVMODECOPIESANDCOLLATE
                  flag is basically useless because my code will need to check for and possibly handle
                  the collation whether I use the flag or not.

                  Is that correct?



                  ------------------
                  Bernard Ertl
                  Bernard Ertl
                  InterPlan Systems

                  Comment


                  • #10
                    I'm terribly sorry! I confused the issue with a critical typo in that message. Lets try it again:

                    IMHO, the best way is NOT to use the PD_USEDEVMODECOPIESANDCOLLATE flag when you call PrintDlg().

                    When the PrintDlg() API returns, test for the prescence of the %PD_COLLATE collate flag (and PD.nCopies member) in PD structure, and work with the results of those only, ignoring the DevMode structure (as the driver will handle it for you if necessary).

                    Does this help?

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

                    Comment


                    • #11
                      If you do not use the flag, you MUST check both the pd and dm structures! (See my reply above, third example)

                      The reason I do use the flag is I do not care about collation, and provide no code to collate when the printer driver cannot.

                      ------------------
                      Dennis
                      mailto:[email protected][email protected]</A>

                      Comment


                      • #12
                        No that is not correct, unless MS have failed to document things correctly:
                        PD_USEDEVMODECOPIESANDCOLLATE
                        <snip>
                        If this flag isn't set... and the driver doesn't support multiple copies and collation, the information is returned in the PRINTDLG structure. This means that an application only has to look at nCopies and PD_COLLATE to determine how many copies it needs to render and whether it needs to print them collated.
                        Dennis, in your "example 3", the device driver will be taking care of the multiple copies (2 in your example), therefore PD.nCopies returns 1. This means your code sends one copy, and the driver prints it twice on your behalf. This is why you need to look for PD_COLLATE in PD after the call.

                        Printing is such fun.

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

                        Comment


                        • #13
                          Aha! Lance is human!

                          OK. So I understood the M$ docs correctly. I don't particularly
                          care about collation as copy machines can handle this chore 99.99%
                          of the time for my end users. But, I'm going to go ahead and forgo
                          this flag and add in collation handling code for the color printer
                          crowd....

                          Dennis,

                          I think what Lance is getting at, is that if the DM specifies multiple
                          copies, you only need print once and the driver will automatically handle
                          the extra copies. So, your code only need concern itself with the PD values.


                          I do have another question though. Upon re-reading the M$ help file,
                          I noticed the pd.hDC field. If I specify the PD_RETURNDC flag when calling
                          PrintDlg(), can I forgo the CreateDC call (see code in initial post)?

                          And if so, I suppose I still need to call DeleteDC when I'm done?

                          ------------------
                          Bernard Ertl

                          [This message has been edited by Bern Ertl (edited July 24, 2001).]
                          Bernard Ertl
                          InterPlan Systems

                          Comment


                          • #14
                            And I bleed when I get a paper cut too!

                            Aye, you must delete the DC with DeleteDC().

                            However, I prefer to use CreateDC() since I often "adjust" some portions of the DevMode structure before actually creating the device context.

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

                            Comment

                            Working...
                            X