Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Get number of copies correctly 2

Status
Not open for further replies.

markros

Programmer
May 21, 2007
3,150
US
In this thread184-1538957 I see a very interesting code posted by Mike Cagnon. However, it doesn't correctly determine the number of copies. Can someone please check it and tell, what has to be corrected?

Thanks.

PluralSight Learning Library
 
What do you mean - it doesn't correctly determine the number of copies ??

Its right there in his code...
Sys(2600,hPRINTDLG+52,4,BinToC(1,"4rs")) && nCopies
and later in the code....
?" Paper Copies: ", CToBin(Sys(2600,hDevMode+54,2),"2rs")

Are you saying that the code is inaccurate?

Can someone please check it and tell, what has to be corrected?
Is there a reason that you can't check the code and let the rest of us know what you find?

Good Luck,
JRB-Bldr
 
Yes, this is exactly what I am saying. In my tests I always get 1 regardless of the actual number I put there. I can put 7, 4, 9, 15, etc., but the result I am getting is always 1.

So, I assume that this code has a problem, but I am not that well versed in API to figure this out myself.

PluralSight Learning Library
 
One thing is odd for sure: Writing a 4 byte long (4rs) value to adress hPRINTDLG+52, but reading back 2 bytes (2rs) from hPRINTDLG+54. There is a logic to it, that only readin out 2 bytes would start from another adress, but the "r" in ctobins parameter means reverse order, so the last two bytes are supposedly 0, if you never print more than 65536 copies.

Maybe it's wrong to write 4 bytes in the first place, and instead what should be written is:

Sys(2600,hPRINTDLG+54,4,BinToC(1,"2rs")) && nCopies

Bye, Olaf.
 
I already tried the following by the advice of Gregory Adam
Code:
? 'Copies = ', CToBin(sys(2600,hPRINTDLG+52,4), '4rs')

I added this piece of code right after lnAction =
and before IF hResult =

And now the most interesting thing - he says it works for him 100% percent, but for me it works in some cases and in most it still returns 1.






PluralSight Learning Library
 
Only when I change the printer first it seems to work. If I just type the number of copies or change the number of copies using spinner I get 1 returned.

This is perplexing as the same code works for Gregory correctly on the same OS (Windows 7).

In any case, since it doesn't work for me, I can not expect it will work for everyone else, so I'm thinking now of a different alternative - using a form from MS to simulate the prompt. I actually like that form, but yesterday I had to fix a few bugs in that form also and I think I saw some weird behavior of the printer's combo (it went blank, etc.), so I need more tests.

PluralSight Learning Library
 
I'm not sure what the "form from MS" refers to. Personally, I would say that, if you try a packaged a solution that you can't get to work properly, the best thing is to create your own from scratch.

So, in this case, I'd be inclined to create my own Printer dialogue, based on a native VFP form.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
The sys(2600) calls fill a c struct called "PRINTDLGEX", you can see this from the memory allocation.

So, how is this structure defined?


nCopies is a DWORD in this structure, so it should be 4 bytes. The offset is determined by the size of all the other members of the struct. I can't tell without further detailed inspection if it should be 52 or 54, but it should be the same for both lines setting and reading the number of copies.

Bye, Olaf.
 
I see now:

What's read out is some other structure called DEVMODE struct:

The offset for the number of copies is differing, so I think the code is alright.

The meaning is just not, what you expect, the DEVMODE structure rather tells about defaults, not user choices or current settings.

So what number of copies do you actually want to know? The device default, the foxpro report setting? Or something else?

You may look into the help topic on SYS(1037) to see, if SYS(1037,2) would give you the info you want.

Bye, Olaf.
 
Here is the code I'm trying and I'm not sure what are Min/Max pages and where are they used, but if they are set correctly, then it should be 52. I don't get correct result

Code:
clear
#Define SIZEOF_PRINTDLGEX     84
#Define SIZEOF_PRINTPAGERANGE  8
** nFlag options
#Define PD_ALLPAGES                  0x00000000
#Define PD_SELECTION                 0x00000001
#Define PD_PAGENUMS                  0x00000002
#Define PD_NOSELECTION               0x00000004
#Define PD_NOPAGENUMS                0x00000008
#Define PD_COLLATE                   0x00000010
#Define PD_PRINTTOFILE               0x00000020
#Define PD_PRINTSETUP                0x00000040
#Define PD_NOWARNING                 0x00000080
#Define PD_RETURNDC                  0x00000100
#Define PD_RETURNIC                  0x00000200
#Define PD_RETURNDEFAULT             0x00000400
#Define PD_SHOWHELP                  0x00000800
#Define PD_USEDEVMODECOPIES          0x00040000
#Define PD_USEDEVMODECOPIESANDCOLLATE 0x00040000
#Define PD_DISABLEPRINTTOFILE        0x00080000
#Define PD_HIDEPRINTTOFILE           0x00100000
#Define PD_NONETWORKBUTTON           0x00200000
#Define PD_CURRENTPAGE               0x00400000
#Define PD_NOCURRENTPAGE             0x00800000
#Define START_PAGE_GENERAL    Bitlshift(0xffffffff,0)
#Define GMEM_FIXED       0x00
#Define GMEM_ZEROINIT    0x40
#Define GPTR             (GMEM_FIXED+GMEM_ZEROINIT)
#Define DM_OUT_BUFFER  2
#Define DM_IN_PROMPT   4
#Define CCHDEVICENAME 32
#Define CCHFORMNAME   32
#Define PD_RESULT_CANCEL               0
#Define PD_RESULT_PRINT                1
#Define PD_RESULT_APPLY                2

 

Declare Long GlobalAlloc In WIN32API Long uFlags, Long uBytes
Declare Long GlobalLock In WIN32API Long Hmem
Declare Long GlobalUnlock In WIN32API Long Hmem
Declare Long GlobalFree In WIN32API Long Hmem
Declare Integer PrintDlg In comdlg32.Dll Long lppd
Declare Integer PrintDlgEx In comdlg32.Dll Long lppd
Declare Long DeleteDC In WIN32API Long hdc

 

Local hPRINTDLG, hPageRanges, hdc, hResult, nFlagsm, hResult
Local hGDevMode, hGDevNames, nPageRange, hPageRange, lnAction
Local lcDeviceName, lcFormName, hDevMode, hDevNames

** Allocate memory for the PRINTDLGEX structure

hPRINTDLG = GlobalAlloc(GPTR,SIZEOF_PRINTDLGEX)
** Allocate memory for 10x PRINTPAGERANGE structures
hPageRanges = GlobalAlloc(GPTR,SIZEOF_PRINTPAGERANGE*10)
hdc = 0
hResult = 0
** Initialize the PRINTPAGERANGE structure
nFlags = Bitor(PD_RETURNDC,PD_ALLPAGES)
Sys(2600,hPageRanges,8,BinToC(1,"4rs")+BinToC(1,"4rs"))
** Initialize the PRINTDLGEX structure
Sys(2600,hPRINTDLG+ 0,4,BinToC(SIZEOF_PRINTDLGEX,"4rs")) && lStructSize
Sys(2600,hPRINTDLG+ 4,4,BinToC(_vfp.HWnd,"4rs"))         && hwndOwner
Sys(2600,hPRINTDLG+20,4,BinToC(nFlags,"4rs"))            && Flags
Sys(2600,hPRINTDLG+32,4,BinToC(0,"4rs"))                 && nPageRanges
Sys(2600,hPRINTDLG+36,4,BinToC(10,"4rs"))                && nMaxPageRanges
Sys(2600,hPRINTDLG+40,4,BinToC(hPageRanges,"4rs"))       && lpPageRanges
Sys(2600,hPRINTDLG+44,4,BinToC(1,"4rs"))                 && nMinPage
Sys(2600,hPRINTDLG+48,4,BinToC(1000,"4rs"))              && nMaxPage
Sys(2600,hPRINTDLG+52,4,BinToC(1,"4rs"))                 && nCopies
Sys(2600,hPRINTDLG+76,4,BinToC(START_PAGE_GENERAL,"4rs")) && nStartPage

** Display the Print dialog
hResult = PrintDlgEx(hPRINTDLG)
** Pull updated values from PRINTDLGEX structure
hGDevMode = CToBin(Sys(2600,hPRINTDLG+8,4),"4rs")
hGDevNames = CToBin(Sys(2600,hPRINTDLG+12,4),"4rs")
hdc = CToBin(Sys(2600,hPRINTDLG+16,4),"4rs")
nFlags = CToBin(Sys(2600,hPRINTDLG+20,4),"4rs")
lnAction = CToBin(Sys(2600,hPRINTDLG+80,4),"4rs")
If hResult = 0
** Lock movable memory
   hDevMode = GlobalLock(hGDevMode)
   hDevNames = GlobalLock(hGDevNames)
** Display Action taken by user
   Do Case
      Case lnAction = PD_RESULT_CANCEL
         ?"Action: CANCEL"
      Case lnAction = PD_RESULT_PRINT
         ?"Action: PRINT"
      Case lnAction = PD_RESULT_APPLY
         ?"Action: APPLY"
   Endcase

 

** Display print range selection
   Do Case
      Case lnAction != PD_RESULT_PRINT
** No Printing
      Case Bitand(nFlags,PD_SELECTION)=PD_SELECTION
         ?" Selection"
      Case Bitand(nFlags,PD_CURRENTPAGE)=PD_CURRENTPAGE
         ?" Current Page"
      Case Bitand(nFlags,PD_PAGENUMS)=PD_PAGENUMS
         ?" Page Ranges"
         nPageRanges = CToBin(Sys(2600,hPRINTDLG+32,4),"4rs")
         For nPageRange = 0 To nPageRanges-1
            hPageRange = hPageRanges+(nPageRange*SIZEOF_PRINTPAGERANGE)
            nFrom = CToBin(Sys(2600,hPageRange,4),"4rs")
            nTo = CToBin(Sys(2600,hPageRange+4,4),"4rs")
            ?"   From: "+Transform(nFrom)+" To: "+Transform(nTo)
         Endfor
      Otherwise
         ?" All Pages"
   ENDCASE
   
      ? 'Min Page = ', CToBin(sys(2600,hPRINTDLG+44,4), '4rs')  && added this 
      ? 'Max Page = ', CToBin(sys(2600,hPRINTDLG+48,4), '4rs')  && added this 
      ? '# of Copies = ', CToBin(sys(2600,hPRINTDLG+52,4), '4rs')  && added this 

 

** Display the DEVMODE structure, showing printing preferences

   If hDevMode <> 0
      ?"DEVMODE:"
** DEVMODE: [URL unfurl="true"]http://msdn2.microsoft.com/en-us/library/ms535771.aspx[/URL]
      lcDeviceName = Sys(2600,hDevMode+0,CCHDEVICENAME)
      lcDeviceName = " "+Left(lcDeviceName, At(0h00,lcDeviceName)-1)
      ?" Device Name: ",   lcDeviceName
      ?" Orientation: ",   CToBin(Sys(2600,hDevMode+44,2),"2rs")
      ?" Paper Size: ",    CToBin(Sys(2600,hDevMode+46,2),"2rs")
      ?" Paper Length: ",  CToBin(Sys(2600,hDevMode+48,2),"2rs")
      ?" Paper Width: ",   CToBin(Sys(2600,hDevMode+50,2),"2rs")
      ?" Paper Scale: ",   CToBin(Sys(2600,hDevMode+52,2),"2rs")
      ?" Paper Copies: ",  CToBin(Sys(2600,hDevMode+54,2),"2rs")
   
      ?" Default Source: ",CToBin(Sys(2600,hDevMode+56,2),"2rs")
      ?" Print Qualilty: ",CToBin(Sys(2600,hDevMode+58,2),"2rs")
      ?" Color: ",         CToBin(Sys(2600,hDevMode+60,2),"2rs")
      ?" Duplex: ",        CToBin(Sys(2600,hDevMode+62,2),"2rs")
      ?" Y Resolution: ",  CToBin(Sys(2600,hDevMode+64,2),"2rs")
      ?" TT Option: ",     CToBin(Sys(2600,hDevMode+66,2),"2rs")
      ?" Collate: ",       CToBin(Sys(2600,hDevMode+68,2),"2rs")
      lcFormName = Sys(2600,hDevMode+70,CCHFORMNAME)
      lcFormName = " "+Left(lcFormName, At(0h00,lcFormName)-1)
      ?" Form Name: ",      lcFormName
      ?" LogPixels: ",      CToBin(Sys(2600,hDevMode+102,2),"2rs")
      ?" BitsPerPixel: ",   CToBin(Sys(2600,hDevMode+104,2),"2rs")
 

      
    
   Endif

** Unlock movable memory
   GlobalUnlock(hGDevMode)
   GlobalUnlock(hGDevNames)
Else
   ?"ERROR: "+Transform(hResult,"@0")
Endif
** Clean up allocated memory
If hGDevMode <> 0
   GlobalFree(hGDevMode)
Endif
If hGDevNames <> 0
   GlobalFree(hGDevNames)
Endif
GlobalFree(hPageRanges)
GlobalFree(hPRINTDLG)
If hdc <> 0
   DeleteDC(hdc)
Endif
Return



PluralSight Learning Library
 
Sorry, Olaf, didn't see your second message. The point of this exercise is to get the selections by a user. I want to simulate the Prompt dialog. The reason I need it is that I print report in a loop one record at a time (because I need to print labels and each of them has to be a separate print job). So, I need to either somehow run the very first report with TO PRINTER PROMPT option and capture the selections made by user in this dialog - I don't think it's possible or if possible, somewhat complex, or I need to invoke my own dialog prior to the first report printing and use these selections for printing other reports.

My original quick solution was to use GetPrinter() dialog, but the users want to be able to specify number of copies. I want the dialog to look as close to 'native' prompt dialog, as possible.

PluralSight Learning Library
 
You checked wrong output :)
This:
Code:
 ? '# of Copies = ', CToBin(sys(2600,hPRINTDLG+52,4), '4rs')  && added this
shows you how many copies you select from spinner (or entered manually)

This:
Code:
   ?" Paper Copies: ",  CToBin(Sys(2600,hDevMode+54,2),"2rs")
is something that I'm not sure what :)

Borislav Borissov
VFP9 SP2, SQL Server 2000,2005 & 2008.
 
Hi Boris,

With your help I figured this out. My default system printer is Nova PDF. It doesn't allow to change number of copies. So, changing the number in this spinner doesn't do anything. It sure looks confusing, though, and took me a lot of time before you stirred me towards the answer.

The form I have does deal with enabling/disabling this correctly, so I'm almost sold on using the form instead of this dialog.

PluralSight Learning Library
 
Mike,

Thanks a lot. Before I download your class - are the comments in French or English?

I already implemented the form yesterday, but I may re-consider.

Things I didn't like using the dialog:

1. The printer selections are a bit hard to get (I had to scroll to see all printers)

2. The spinner for Copies is not automatically disabled when the printer doesn't allow to change number of copies. That was the big roadblock for me yesterday and thanks to Boris I was able to finally realize that (especially when I changed my default printer).

PluralSight Learning Library
 
I've downloaded the class and discovered it doesn't have any code. The last property shown in the sample page results in error and o.bin doesn't work either.

I see that the problem with disabling changing the value of copies was addressed in this class.

In any case, without any source code I'm not sure I can use it.

PluralSight Learning Library
 
The dialog is part of windows, I cannot change its look.
It is the same one you would see in Word.

The last property has a typo it should be:
?o.bitsperpixel

There is no o.Bin property.



Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
ReFox XI (www.mcrgsoftware.com)
 
I understand. What is different in the new class comparing with the originally posted code? In the new class I get a warning message when I try to change value in the spinner (I can type, but the spinner is disabled). I got the same behavior with the Prompt dialog.

Also, can you post the version of your class with the code? I can not use the class without code.

PluralSight Learning Library
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top