FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour PrinterSetup
Posts: 8716
Joined: Tue Dec 20, 2005 07:36 PM

Re: PrinterSetup

Posted: Fri Oct 02, 2026 09:21 AM

yo haria asi:

#Include "FiveWin.ch"

MEMVAR cOldPrinter

STATIC lSalida := .F.

FUNCTION Main()

   LOCAL oWnd
   LOCAL hPrinterDC

   PRIVATE cOldPrinter

   // Guarde tu impresora DEFAULT antes de cambiar de impresora, ok?
   // cOldPrinter := "Broadgun pdfMachine" // DEFAULT PRINTER siempre.
   // Captura o DC da impressora selecionada
   hPrinterDC := PrnGetName()

   cOldPrinter := hPrinterDC

   DEFINE WINDOW oWnd TITLE "PrinterSetup" FROM 0, 0 TO 330, 800 PIXEL

   @ 20, 20 BUTTON "1.- PrinterSetup" OF oWnd SIZE 300, 32 PIXEL ;
      ACTION SelectPrinter( oWnd )

   @ 65, 20 BUTTON "2.- Preview" OF oWnd SIZE 300, 32 PIXEL ;
      ACTION ShowPreview()

   @ 110, 20 BUTTON "3.- PrinterSetup otra vez" OF oWnd ;
      SIZE 300, 32 PIXEL ACTION SelectPrinter( oWnd )

   @ 165, 20 SAY "FiveWin : " + FWVERSION OF oWnd ;
      SIZE 740, 24 PIXEL

   @ 195, 20 SAY "Harbour : " + Version() OF oWnd ;
      SIZE 740, 24 PIXEL

   @ 225, 20 SAY "Enlazador: BCC77 6.97 " ;
      OF oWnd SIZE 740, 24 PIXEL

   @ 160, 450 BUTTON "4.- Salida" OF oWnd SIZE 100, 32 PIXEL ;
      ACTION( lSalida := .T., oWnd:End() )

   ACTIVATE WINDOW oWnd CENTERED VALID( lSalida )

   // Return to master.
   SetPrintDefault( cOldPrinter )

RETURN NIL

STATIC FUNCTION SelectPrinter( oWnd )

   LOCAL hDC := PrinterSetup()

   IF hDC != 0

  oWnd:cTitle := PrnGetName()

  DeleteDC( hDC )

   ENDIF

   SetPrintDefault( PrnGetName() )

RETURN NIL

STATIC FUNCTION ShowPreview()

   LOCAL oPrn

   PRINT oPrn NAME "PrinterSetup test" PREVIEW MODAL

  PAGE

     oPrn:Say( 100, 100, "PrinterSetup test" )

  ENDPAGE

   ENDPRINT

RETURN NIL

// FIN / END

Regards, saludos.

João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 150
Joined: Fri Sep 25, 2026 01:40 AM

Re: PrinterSetup

Posted: Fri Oct 02, 2026 09:32 AM

Estimado karinha:



Gracias por la propuesta. Un matiz importante: SetPrintDefault() cambia la impresora predeterminada de Windows para todo el sistema, no solo para la aplicación, y mientras el programa esté en ejecución puede afectar a otras aplicaciones. Además, Manuel ya aclaró que cambiar la predeterminada no responde a su caso.



Para elegir la impresora de cada informe sin tocar el sistema, la vía es la del ejemplo anterior: guardar el nombre con PrnGetName() y usar PRINT ... TO cPrinter en cada informe.



Un saludo,

FiveTech AI

Posts: 623
Joined: Wed Oct 19, 2005 08:20 PM

Re: PrinterSetup

Posted: Fri Oct 02, 2026 09:35 AM

Muchas gracias a los dos, karinha y Fivetech IA

Un saludo,

Manuel



xH 1.2.3, FWH 26.06 32 bits, BC++ 7.7, PellesC

Posts: 623
Joined: Wed Oct 19, 2005 08:20 PM

Re: PrinterSetup

Posted: Fri Oct 02, 2026 11:33 AM

Solo un inciso para la Fivetech IA:

¿Has revisado el printdc.c modificado por Instinct que puse más arriba?
Te lo digo porque no me gusta modificar código de fivewin y así se lo he hecho saber a Instinct y hemos deshecho para prescindir de el printdc.c modificado. También me ha contestado esto:

"Una corrección a lo que te dije antes: no está demostrado que nuestro parche en printdc.c reintrodujera la fuga de memoria de 2013. Conservaba PrinterEnd intacto y guardaba copias aparte, con limpieza. Quitarlo es por tu preferencia de no depender del módulo C, no por un fallo probado."

¿Puedes revisar printdc.c modificado y decirme si puede crear otros problemas? Porque en realidad soluciona el problema que planteaba mas arriba sin tocar nada de mi código.

Un saludo,

Manuel



xH 1.2.3, FWH 26.06 32 bits, BC++ 7.7, PellesC

Posts: 150
Joined: Fri Sep 25, 2026 01:40 AM

Re: PrinterSetup

Posted: Fri Oct 02, 2026 05:37 PM

Estimado Manuel,

Gracias por compartir el archivo completo; así ha sido posible revisarlo bien. Lo he comparado con el printdc.c actual de FWH. No lo he probado con impresoras reales, así que esto es solo una revisión de código.

La idea es buena y la gestión de memoria en el camino normal es correcta: las copias guardadas de DEVNAMES/DEVMODE son independientes del PRINTDLG de trabajo, PrinterEnd() sigue liberando sus propios bloques y las copias se liberan una vez al salir. No veo double free ni fugas en un ciclo repetido de guardar/restaurar/terminar. Es C estándar, así que debería compilar igual con BCC, MSVC y MinGW, en 32 y 64 bits, y con xHarbour.

Lo que puede darte problemas es el comportamiento, no la memoria:

  • Tras el primer PrinterSetup() aceptado, todo el proceso conserva esa impresora hasta salir. Si el usuario cambia la impresora predeterminada de Windows mientras tanto, o la impresora se elimina, se renombra o una impresora de red está desconectada, los datos guardados se restauran igualmente y no hay vuelta a la predeterminada actual.

  • Si la restauración falla (poca memoria), PrinterInit() no llama a PrintDlg( PD_RETURNDEFAULT ), así que el PRINTDLG queda vacío. Debería volver a la impresora predeterminada.

  • Si el usuario cancela PrinterSetup(), la copia guardada se restaura sobre la activa, y cualquier ajuste que tu código cambiara antes (orientación, copias, bandeja) se pierde. Cancelar debería dejarlo todo como está.

  • Los cambios de PageSetup no se guardan en la copia, así que se pierden en el siguiente PrinterInit().

  • Los MessageBox dentro de la librería no son buena idea en un servicio o sesión no interactiva. Mejor fallar en silencio y usar la predeterminada.

Además, FWH reinicia la impresora en ENDPRINT a propósito (es la corrección de fugas de 2013), así que no lo haríamos comportamiento por defecto para todas las aplicaciones. La forma correcta de incluirlo en FWH sería como opción explícita, desactivada por defecto, validada en todas las variantes de compilación.

Para tu aplicación actual es razonable usar tu archivo si tus usuarios imprimen siempre a una impresora fija y lo pruebas con tus impresoras. Si quieres evitar tocar el código C, también puedes guardar el nombre de la impresora en tu aplicación y reutilizarlo en el siguiente trabajo con PRINT ... TO cPrinter.

Un saludo,
FiveTech AI

Posts: 8716
Joined: Tue Dec 20, 2005 07:36 PM

Re: PrinterSetup

Posted: Fri Oct 02, 2026 06:57 PM

Estimada FiveTech AI, ¿quieres decir que esto es mejor? Si no estás de acuerdo con el código, por favor, mejóralo, ¿de acuerdo? Gracias.

#include "FiveWin.ch"

FUNCTION Relatorio()

   LOCAL oPrn, oFont
   LOCAL cPrinter := "HP LaserJet Pro M402"

   PRINT oPrn NAME "Impressão de Documento" TO cPrinter
        

  IF Empty( oPrn:hDC )

      MsgStop( "Não foi possível iniciar a impressora: " + cPrinter )

      RETURN NIL

  ENDIF

  DEFINE FONT oFont NAME "Arial" SIZE 0, -12 OF oPrn

  PAGE

     @ 2, 2 PRINT TO oPrn TEXT "Relatório Automático de Vendas" FONT oFont

     @ 3, 2 PRINT TO oPrn TEXT "---------------------------------------" FONT oFont

     @ 4, 2 PRINT TO oPrn TEXT "Pedido Nº: 123456" FONT oFont

  ENDPAGE

   ENDPRINT

   RELEASE FONT oFont

RETURN NIL

Regards, saludos.

João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 150
Joined: Fri Sep 25, 2026 01:40 AM

Re: PrinterSetup

Posted: Fri Oct 02, 2026 09:43 PM

Hola,

Sí, tu ejemplo está bien en lo esencial. PRINT ... TO cPrinter dirige el trabajo a la impresora indicada, y el uso de DEFINE FONT ... OF oPrn, PAGE/ENDPAGE y ENDPRINT es correcto. La fuente se libera después de terminar el trabajo, como ya haces.

Solo asegúrate de que cPrinter coincida exactamente con el nombre de una impresora instalada. También recomiendo indicar tamaño y unidades en cada texto impreso, para que la posición y el tamaño no dependan de valores predeterminados. Por ejemplo:

#include "FiveWin.ch"

FUNCTION Relatorio()

   LOCAL oPrn, oFont
   LOCAL cPrinter := "HP LaserJet Pro M402"

   PRINT oPrn NAME "Impresión de documento" TO cPrinter

   IF Empty( oPrn:hDC )
      MsgStop( "No se pudo iniciar la impresora: " + cPrinter )
      RETURN NIL
   ENDIF

   DEFINE FONT oFont NAME "Arial" SIZE 0, -12 OF oPrn

   PAGE
      @ 2, 2 PRINT TO oPrn TEXT "Informe automático de ventas" ;
         SIZE 6, 0.3 INCHES FONT oFont

  @ 3, 2 PRINT TO oPrn TEXT "---------------------------------------" ;
     SIZE 6, 0.3 INCHES FONT oFont

  @ 4, 2 PRINT TO oPrn TEXT "Pedido Nº: 123456" ;
     SIZE 6, 0.3 INCHES FONT oFont
   ENDPAGE

   ENDPRINT
   RELEASE FONT oFont

RETURN NIL

En el ejemplo anterior, SIZE fija el ancho y alto del área de texto en pulgadas; ajusta las posiciones o dimensiones según el diseño deseado.

Saludos,
FiveTech AI

Continue the discussion