vfp9 sp2 - reportlistener

06/06/2008 - 15:36 von Manfred Paul | Report spam
hallo füchse,
ich überlege folgendes zu realisieren:

druck in den speicher - danach seitenweise an drucker senden.
hintergrund:
z.b. 1 seite auf printer a
alle übrigen auf printer b (1 seite auf firmenpapier und andere auf weisses)

ich bin da auf folgende idee gestossen:
mit dem reportlistener den report rendern lassen - dann prüfen obs mehr wie
2 seiten im speicher sind und dann die bereits gerenderten seiten drucken -
somit kann es auch nie passieren dass z.b. eine zeile fehlt oder so.

oreportlistener=newobject("reportlistener")
oreportlistener.ListenerType=3
lcprinter1="HP Laserjet A"
lcprinter2="HP Laserjet B"
lcreport="c:\meinprogramm\testreport.frx"
REPORT FORM (lcreport) object oreportlistener
if _pagetotal=1
oreportlistener.outputpage(1,lcprinter1,1)
else
reportlistener.outputpage(1,lcprinter1)
reportlistener.outputpage(2-99999,lcprinter2)
endif

geht so (natürlich) leider nicht. lieg ich da ganz falsch oder ist nur eine
kleinigkeit falsch? kann mir da wer helfen?

vielen dank und schöes we
manfred paul
 

Lesen sie die antworten

#1 Andreas Beger
09/06/2008 - 11:28 | Warnen spam
Hallo Manfred,

oreportlistener=newobject("reportlistener")
oreportlistener.ListenerType=3
lcprinter1="HP Laserjet A"
lcprinter2="HP Laserjet B"
lcreport="c:\meinprogramm\testreport.frx"
REPORT FORM (lcreport) object oreportlistener
if _pagetotal=1
oreportlistener.outputpage(1,lcprinter1,1)
else
reportlistener.outputpage(1,lcprinter1)
reportlistener.outputpage(2-99999,lcprinter2)
endif

geht so (natürlich) leider nicht. lieg ich da ganz falsch oder ist nur
eine kleinigkeit falsch? kann mir da wer helfen?



Grundsàtzlich ist der Gedankengang richtig, ABER ...
Die Reportlistener-Methode OUTPUTPAGE ist leider nicht ganz so simpel zu
handhaben, wie es auf den ersten Blick aussieht.
Ich habe mich vor einiger Zeit mal mit dem Thema beschàftigt und mir dazu 2
Klassen erstellt. Zum besseren Verstàndnis folgendes Beispiel:


*** Start Beispiel

CREATE CURSOR test (test C(10))
FOR i=1 TO 200
INSERT INTO test VALUES ("1234567890")
ENDFOR

lcReport="testreport"

CREATE REPORT (lcReport) FROM test

oPrn = NEWOBJECT("GetPrnDC")
oPrn.lReturnDC = .F. && es wird kein DeviceContext gebraucht
=oPrn.getdc()
lcDevMode = oPrn.cPrinter && sollte man zur wiederholten Verwendung
speichern
oPrn = NULL


oListener = NEWOBJECT("reportlistener")
oListener.PRINTJOBNAME = "mein PrintJobName"
oListener.LISTENERTYPE = 3 && nur Rendern
REPORT FORM (lcReport) OBJECT oListener

DELETE FILE (lcReport)+".FRX"
DELETE FILE (lcReport)+".FRT"


oOutput = NEWOBJECT("myOutputPage")
oOutput.oListener = m.oListener
* Ausgabe nur erste Seite
* mit Vorgabe Drucker
oOutput.OUTPUTPAGE(lcDevMode,;
1,;
1,;
.F.)
* Ausgabe ab Seite 2 bis Ende
* ohne Vorgabe Drucker
IF oListener.OUTPUTPAGECOUNT>1
oOutput.OUTPUTPAGE("",;
2,;
oListener.OUTPUTPAGECOUNT,;
.F.) && .T. druckt ohne Prompt
ENDIF
oOutput = NULL
oListener = NULL

*** Ende Beispiel


DEFINE CLASS GetPrnDC AS CUSTOM

cPrinter = ""
lAll = .F.
lQuiet = .F.
lReturnDC = .T.
nCopies = 1
nPageFrom = 1
nPageTo = 1
nPageMin = 1
nPageMax = 1

PROCEDURE INIT
* API-Funktionen deklarieren
DECLARE RtlMoveMemory IN kernel32 AS Mem2Str;
STRING @DEST, INTEGER Src, INTEGER nLength
DECLARE RtlMoveMemory IN kernel32 AS Str2Mem;
INTEGER DEST, STRING @Src, INTEGER nLength
DECLARE INTEGER GlobalLock IN kernel32 INTEGER HMEM
DECLARE INTEGER GlobalUnlock IN kernel32 INTEGER HMEM
DECLARE INTEGER GlobalSize IN kernel32 INTEGER HMEM
DECLARE INTEGER GlobalAlloc IN kernel32 INTEGER wFlags, INTEGER dwBytes
DECLARE INTEGER PrintDlg IN comdlg32 STRING @ lppd
ENDPROC

PROCEDURE getdc
* returns device context of printer
#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_ENABLEPRINTHOOK 0x00001000
#DEFINE PD_ENABLESETUPHOOK 0x00002000
#DEFINE PD_ENABLEPRINTTEMPLATE 0x00004000
#DEFINE PD_ENABLESETUPTEMPLATE 0x00008000
#DEFINE PD_ENABLEPRINTTEMPLATEHANDLE 0x00010000
#DEFINE PD_ENABLESETUPTEMPLATEHANDLE 0x00020000
#DEFINE PD_USEDEVMODECOPIES 0x00040000
#DEFINE PD_USEDEVMODECOPIESANDCOLLATE 0x00040000
#DEFINE PD_DISABLEPRINTTOFILE 0x00080000
#DEFINE PD_HIDEPRINTTOFILE 0x00100000
#DEFINE PD_NONETWORKBUTTON 0x00200000

LOCAL lcStruct, lnFlags, lnFromPage, lnToPage, lnMinPage, lnMaxPage,
lnCopies
lnFlags = PD_NOSELECTION
IF THIS.lReturnDC
lnFlags = lnFlags + PD_RETURNDC
ENDIF
IF THIS.lQuiet
lnFlags = lnFlags + PD_RETURNDEFAULT
ENDIF
IF NOT THIS.lAll
lnFlags = lnFlags + PD_PAGENUMS
ENDIF
IF NOT EMPTY(THIS.cPrinter)
lnFlags = lnFlags + PD_USEDEVMODECOPIESANDCOLLATE
ENDIF

* Struktur ist 66 Byte lang
lcStruct = BINTOC(66,"4RS") + REPLICATE(CHR(0), 16) +;
BINTOC(lnFlags,"4RS") + ;
BINTOC(THIS.nPageFrom,"2RS")+BINTOC(THIS.nPageTo,"2RS") +;
BINTOC(THIS.nPageMin,"2RS")+BINTOC(THIS.nPageMax,"2RS") +;
BINTOC(THIS.nCopies,"2RS")+;
REPLICATE(CHR(0), 32)
IF NOT EMPTY(THIS.cPrinter) && Druckervoreinstellung vorhanden ?
lcStruct = STUFF(lcStruct,9,4,BINTOC(THIS.str2adr(THIS.cPrinter),"4RS"))
ENDIF

IF PrintDlg(@lcStruct) <> 0

LOCAL lcBuffer, lnBufsize, hBuffer, hhBuffer
lcBuffer = ""
hBuffer = CTOBIN(SUBSTR(lcStruct,9,4),"4RS")
IF hBuffer <> 0
lnBufsize = GlobalSize(hBuffer)
hhBuffer = GlobalLock(hBuffer)
IF hhBuffer <> 0
lcBuffer = REPLICATE(CHR(0), lnBufsize)
Mem2Str(@lcBuffer, hhBuffer, lnBufsize)
ENDIF
GlobalUnlock(hBuffer)
THIS.cPrinter = lcBuffer
ENDIF

THIS.nPageFrom = CTOBIN(SUBSTR(lcStruct,25,2),"2RS")
THIS.nPageTo = CTOBIN(SUBSTR(lcStruct,27,2),"2RS")
THIS.nPageMin = CTOBIN(SUBSTR(lcStruct,29,2),"2RS")
THIS.nPageMax = CTOBIN(SUBSTR(lcStruct,31,2),"2RS")
THIS.nCopies = ASC(SUBSTR(lcBuffer,55,1))
IF BITAND(CTOBIN(SUBSTR(lcStruct,21,4),"4RS"),3)=0 && alles drucken
THIS.nPageFrom = THIS.nPageMin
THIS.nPageTo = THIS.nPageMax
ENDIF

RETURN CTOBIN(SUBSTR(lcStruct, 17,4),"4RS")
ENDIF
RETURN 0

ENDPROC

PROCEDURE str2adr
LPARAMETERS cString AS STRING
#DEFINE GMEM_MOVEABLE 2
LOCAL hBuffer, hhBuffer
hBuffer = GlobalAlloc(GMEM_MOVEABLE, LEN(cString))
hhBuffer = GlobalLock(hBuffer)
= Str2Mem(hhBuffer, @cString, LEN(cString))
= GlobalUnlock(hBuffer)
RETURN (hBuffer)
ENDPROC

ENDDEFINE

DEFINE CLASS myOutputpage AS CUSTOM

oListener = NULL

PROCEDURE INIT

DECLARE INTEGER CreateDC IN gdi32;
STRING lpszDriver,;
STRING lpszDevice,;
INTEGER lpszOutput,;
INTEGER lpInitData
DECLARE INTEGER DeleteDC IN gdi32;
INTEGER hDC

DECLARE INTEGER StartDoc IN gdi32;
INTEGER hdc,;
STRING @ lpdi
DECLARE INTEGER StartPage IN gdi32;
INTEGER hdc
DECLARE INTEGER EndPage IN gdi32;
INTEGER hdc
DECLARE INTEGER EndDoc IN gdi32;
INTEGER hdc

DECLARE INTEGER GetDeviceCaps IN gdi32;
INTEGER hdc,;
INTEGER nIndex

DECLARE RtlMoveMemory IN kernel32 AS Str2Mem;
INTEGER DEST, STRING @Src, INTEGER nLength

DECLARE INTEGER GlobalLock IN kernel32 INTEGER HMEM
DECLARE INTEGER GlobalUnlock IN kernel32 INTEGER HMEM
DECLARE INTEGER GlobalSize IN kernel32 INTEGER HMEM
DECLARE INTEGER GlobalAlloc IN kernel32 INTEGER wFlags, INTEGER dwBytes
DECLARE INTEGER GlobalFree IN kernel32 INTEGER HMEM

ENDPROC

PROCEDURE OUTPUTPAGE
LPARAMETERS tcDevMode, tnPageFrom, tnPageTo, tlQuiet
#DEFINE GMEM_MOVEABLE 2
#DEFINE GMEM_FIXED 0

LOCAL lcJobName, lhDC, lnRatio, lnWidth, lnHeight, hhBuffer
LOCAL oPrn, nFrom, nTo, nCopies, lcPrinter

WITH THIS.oListener
* Printer-Handle erzeugen
lcJobName = .PRINTJOBNAME + CHR(0)
oPrn = NEWOBJECT("GetPrnDC")
oPrn.cPrinter = tcDevMode
oPrn.lQuiet = tlQuiet
oPrn.nPageFrom = tnPageFrom
oPrn.nPageTo = tnPageTo
oPrn.nPageMin = 1
oPrn.nPageMax = .OUTPUTPAGECOUNT
IF tlQuiet
* da PrnDlg() keinen DC liefert, wenn kein Dialog gewünscht ist, muss
CreateDC aufgerufen werden
lcPrinter = LEFT(tcDevMode,32)
IF AT(lcPrinter, CHR(0))>0
lcPrinter = LEFT(lcPrinter, AT(lcPrinter, CHR(0))-1)
ENDIF
LOCAL hhBuffer
hhBuffer = GlobalAlloc(GMEM_FIXED, LEN(tcDevMode))
= Str2Mem(hhBuffer, @tcDevMode, LEN(tcDevMode))
* hhBuffer zeigt jetzt auf die DevMode-Struktur
lhDC = CreateDC("WINSPOOL",lcPrinter,0,hhBuffer)
= GlobalFree(hhBuffer)
ELSE
lhDC=oPrn.getdc()
ENDIF
IF lhDC<>0
nFrom = oPrn.nPageFrom
nTo = oPrn.nPageTo
nCopies = oPrn.nCopies

#DEFINE LOGPIXELSX 88 && Logical pixels/inch in X
#DEFINE LOGPIXELSY 90 && Logical pixels/inch in Y
#DEFINE PHYSICALWIDTH 110 && Physical Width in device units
#DEFINE PHYSICALHEIGHT 111 && Physical Height in device units
#DEFINE PHYSICALOFFSETX 112 && Physical Printable Area x margin
#DEFINE PHYSICALOFFSETY 113 && Physical Printable Area y margin
* wegen verzerrter Ausgabe bei unterschiedlicher hor./vert. Auflösung des
Druckers
lnRatio=GetDeviceCaps(lhDC,LOGPIXELSX)/GetDeviceCaps(lhDC,LOGPIXELSY)
lnWidth=GetDeviceCaps(lhDC,PHYSICALWIDTH)
lnHeight=GetDeviceCaps(lhDC,PHYSICALHEIGHT)*lnRatio
lnLeft=GetDeviceCaps(lhDC,PHYSICALOFFSETX)
lnTop=GetDeviceCaps(lhDC,PHYSICALOFFSETY)

hhBuffer = GlobalAlloc(GMEM_FIXED, LEN(lcJobName))
= Str2Mem(hhBuffer, @lcJobName, LEN(lcJobName))
*!* typedef struct {
*!* int cbSize; 20 Bytes
*!* LPCTSTR lpszDocName; PrintJobName
*!* LPCTSTR lpszOutput; Ausgabe in Datei
*!* LPCTSTR lpszDatatype;
*!* DWORD fwType;
*!* } DOCINFO, *LPDOCINFO;

StartDoc(lhDC,BINTOC(20,"4RS")+BINTOC(hhBuffer,"4RS")+REPLICATE(CHR(0),12))
FOR i= oPrn.nPageFrom TO oPrn.nPageTo
= StartPage(lhDC)
* Ausgabe um den linken und oberen Rand zurückschieben
.OUTPUTPAGE(i,lhDC,0,-lnLeft,-lnTop,lnWidth,lnHeight)
= EndPage(lhDC)
ENDFOR
= EndDoc(lhDC)
DeleteDC(lhDC)
= GlobalFree(hhBuffer)
ENDIF
oPrn = NULL
ENDWITH

ENDPROC

ENDDEFINE

Ähnliche fragen