FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour oPrn:SetCopies(2) / Original y Copia
Posts: 1144
Joined: Mon Feb 05, 2007 07:15 PM
oPrn:SetCopies(2) / Original y Copia
Posted: Thu Mar 05, 2026 05:46 PM

Maestro Antonio :
Se puede implementar en la clase nativa de tPrinter de Fivewin For Harbour esta función ?
Saber que copia se está imprimiendo,
La idea sería agregar una variable de instancia nCurrentCopy a la clase TPrinter:

// En la clase TPrinter se agregaría:
DATA nCurrentCopy   INIT 0
DATA nTotalCopies   INIT 1

METHOD SetCopies( nCopies ) INLINE ;
    ( ::nTotalCopies  := nCopies, ;
      ::nCurrentCopy  := 0,       ;
      PrnSetCopies( nCopies ),    ;
      ::Rebuild() )

Y un método que maneje el ciclo internamente:

METHOD PrintCopies( bBlock )
   LOCAL nCopia
   FOR nCopia := 1 TO ::nTotalCopies
      ::nCurrentCopy := nCopia
      Eval( bBlock, Self, nCopia )
   NEXT
RETURN Self
oPrn:SetCopies(2)
oPrn:PrintCopies( {|oPrn, nCopia|;
    IIF( nCopia == 1,;
         oPrn:Say("ORIGINAL"),;
         oPrn:Say("COPIA " + LTrim(Str(nCopia))) ) } )

Maestro usted sabe como hacerlo
Gracias!!!
Saludos !!!

Cesar Cortes Cruz

SysCtrl Software

Mexico



' Sin +- FWH es mejor "
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: oPrn:SetCopies(2) / Original y Copia
Posted: Thu Mar 05, 2026 08:29 PM

Querido César,

Aqui tienes el análisis de deepwiki al respecto. Te agradezco tu opinión:

Sí, se puede implementar, pero hay un detalle importante a considerar sobre cómo funciona actualmente SetCopies en TPrinter.

Estado actual de la clase TPrinter

El método SetCopies actual delega las copias al driver de Windows mediante PrnSetCopies(): 0-cite-0

Esto llama internamente a la API de Windows para establecer dmCopies en el DEVMODE: 0-cite-1

El problema es que cuando Windows gestiona las copias a nivel de driver, la aplicación envía el documento una sola vez y el driver produce N copias idénticas. La aplicación no tiene visibilidad sobre qué copia se está imprimiendo, porque ni siquiera participa en la duplicación.

La clase NO tiene nCurrentCopy ni nTotalCopies

La definición actual de DATA en TPrinter no incluye esas variables: 0-cite-2

También existe PrnGetCopies() que lee dmCopies del DEVMODE, pero sólo devuelve el número total configurado, no la copia actual: 0-cite-3

Consideración clave para la implementación

Tu propuesta es conceptualmente correcta, pero hay un conflicto: si SetCopies sigue llamando a PrnSetCopies() y además haces el loop en PrintCopies, obtendrás copias duplicadas (N copias del driver x N iteraciones del loop).

La solución correcta sería que PrintCopies gestione las copias a nivel de aplicación y no use PrnSetCopies para el driver, o bien que ponga PrnSetCopies(1) para que el driver sólo envíe 1 copia por iteración. Algo así:

Code (harbour): Select all Collapse
// Nuevas DATA
DATA nCurrentCopy   INIT 0
DATA nTotalCopies   INIT 1

// Nuevo método PrintCopies - gestiona copias a nivel aplicación
METHOD PrintCopies( bBlock ) CLASS TPrinter
   LOCAL nCopia
   // Asegurar que el driver sólo imprime 1 copia por iteración
   PrnSetCopies( 1 )
   ::Rebuild()
   FOR nCopia := 1 TO ::nTotalCopies
      ::nCurrentCopy := nCopia
      Eval( bBlock, Self, nCopia )
   NEXT
   ::nCurrentCopy := 0
RETURN Self

De esta forma, cada iteración del FOR genera un documento/página completo que pasa por StartPage()/EndPage() controlado por el bloque de código, y puedes diferenciar el contenido entre "ORIGINAL" y "COPIA".

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: oPrn:SetCopies(2) / Original y Copia
Posted: Thu Mar 05, 2026 08:35 PM

Además propone estos cambios:

Add nCurrentCopy tracking to TPrinter class In the repository FiveTechSoft/fwh, modify source/classes/printer.prg to add copy-tracking functionality to the TPrinter class:

Add two new DATA members after line 145 (after ACCESS cName INLINE ::cDocument):

DATA nCurrentCopy INIT 0 DATA nTotalCopies INIT 1 Modify the existing SetCopies method (currently at line 341-343) to also store nTotalCopies:

METHOD SetCopies( nCopies ) INLINE ; ( ::nTotalCopies := nCopies, ; PrnSetCopies( nCopies ),; ::Rebuild() ) Add a new PrintCopies method declaration in the class definition (before ENDCLASS at line 399):

METHOD PrintCopies( bBlock ) Add the method implementation after ENDCLASS (e.g., after the Rebuild method or at the end of the file, near other method implementations):

METHOD PrintCopies( bBlock ) CLASS TPrinter LOCAL nCopia // Set driver copies to 1 so copies are managed at application level PrnSetCopies( 1 ) ::Rebuild() FOR nCopia := 1 TO ::nTotalCopies ::nCurrentCopy := nCopia Eval( bBlock, Self, nCopia ) NEXT ::nCurrentCopy := 0 RETURN Self The key design decision: PrintCopies sets PrnSetCopies(1) before the loop to prevent the Windows driver from also making copies (which would result in nTotalCopies * nDriverCopies total output). The application-level loop allows the user to customize each copy's content (e.g., "ORIGINAL" vs "COPIA 2").

Also update the documentation file docs/reference/classes/TPrinter.md:

Add nCurrentCopy and nTotalCopies to the Key Properties table Add PrintCopies( bBlock ) to the Key Methods table with description "Iterates over copies allowing per-copy customization via code block"

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: oPrn:SetCopies(2) / Original y Copia
Posted: Thu Mar 05, 2026 08:39 PM

Hay que probarlo para asegurarnos que no rompemos compatibilidad con código FWH de aplicaciones existentes :idea:

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: oPrn:SetCopies(2) / Original y Copia
Posted: Thu Mar 05, 2026 08:53 PM

El agente Devin de Deepwiki ha preparado un pull request con los cambios necesarios y recomendaciones:

Add copy-tracking functionality to TPrinter class
Summary
Adds application-level copy management to TPrinter, enabling per-copy content customization (e.g., printing "ORIGINAL" on copy 1 and "COPIA 2" on copy 2).

Changes:

Two new DATA members (nCurrentCopy, nTotalCopies) for tracking copy state
Modified SetCopies to persist nTotalCopies alongside the driver-level PrnSetCopies call
New PrintCopies( bBlock ) method that sets driver copies to 1 (to prevent driver × app copy multiplication), then iterates nTotalCopies times, evaluating the user-supplied code block with (Self, nCopia) on each iteration
Review & Testing Checklist for Human
Verify post-PrintCopies state is acceptable: After PrintCopies completes, the driver is left at 1 copy while nTotalCopies retains the original value. Confirm this doesn't cause issues if the user prints again without calling SetCopies again.
Test SetCopies + PrintCopies interaction end-to-end: Call SetCopies(3) then PrintCopies(...) and verify exactly 3 application-level copies are produced (not 3×3 from driver).
Confirm no conflict with existing nCopies property: The docs mention an existing nCopies property — verify nTotalCopies is the intended separate tracking mechanism and doesn't shadow or conflict.
Compile and run with the Harbour/FiveWin toolchain to verify syntax correctness (no compiler available in this environment to validate).
Suggested test:

oPrn:SetCopies( 3 )
oPrn:PrintCopies( {|oPrn, nCopy|
oPrn:StartPage()
oPrn:Say( 100, 100, If( nCopy == 1, "ORIGINAL", "COPIA " + hb_ntos( nCopy ) ) )
oPrn:EndPage()
} )
Notes
Devin Session
Requested by: @FiveTechSoft
Mention @copilot in a comment to make changes to this pull request.
@devin-ai-integration
@FiveTechSoft
Add copy-tracking functionality to TPrinter class
557d049
@devin-ai-integration devin-ai-integration bot assigned FiveTechSoft 12 minutes ago
@devin-ai-integration
Author
devin-ai-integration bot
commented
12 minutes ago
🤖 Devin AI Engineer
I'll be helping with this pull request! Here's what you should know:

I will automatically:

Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
Look at CI failures and help fix them
⚙️ Control Options:

Disable automatic comment and CI monitoring
Merge info
No conflicts with base branch
Merging can be performed automatically.

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: oPrn:SetCopies(2) / Original y Copia
Posted: Thu Mar 05, 2026 09:03 PM


regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM
Re: oPrn:SetCopies(2) / Original y Copia
Posted: Thu Mar 05, 2026 09:07 PM

Basicamente los cambios que propone son estos:

   DATA nCurrentCopy   INIT 0
   DATA nTotalCopies    INIT 1

METHOD SetCopies( nCopies ) INLINE ;
                ( ::nTotalCopies := nCopies, ;
                  PrnSetCopies( nCopies ),;
                  ::Rebuild()            )

METHOD PrintCopies( bBlock )

METHOD PrintCopies( bBlock ) CLASS TPrinter

   LOCAL nCopia

   // Set driver copies to 1 so copies are managed at application level
   PrnSetCopies( 1 )
   ::Rebuild()

   FOR nCopia := 1 TO ::nTotalCopies
      ::nCurrentCopy := nCopia
      Eval( bBlock, Self, nCopia )
   NEXT

   ::nCurrentCopy := 0

RETURN Self

Podrías probar estos cambios en tprinter.prg y verificar que todo te funciona bien ? :idea:

Muchas gracias!

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 1144
Joined: Mon Feb 05, 2007 07:15 PM
Re: oPrn:SetCopies(2) / Original y Copia
Posted: Fri Mar 06, 2026 12:21 AM

Ok. Maestro pruebo y aviso!

Cesar Cortes Cruz

SysCtrl Software

Mexico



' Sin +- FWH es mejor "

Continue the discussion