Page 1 of 1

oWnd:Hardcopy( nEscala, .t. ) y Windows 11

Posted: Fri Jan 30, 2026 3:37 pm
by FiveWiDi

Hola a todos,

A ver si alguien ha tenido alguna experiencia con el método HardCopy() de la clase Windows.Prg y Windows 11.

El caso es que en W10 imprime directamente sin problemas la ventana oWnd, pero en un nuevo usuario que tiene Windows 11, en vez de enviar directamente a impresora muestra una 'previsualización' (no es de la aplicación si no del sistema [Windows11]) en donde dice que no puede previsualizar y si pulsas imprimir genera una hoja en blanco.

Se les ocurrre algo al respecto?

Aprovecho, como harían para enviar directamente a impresora un PDF sin visualizar?
(Si se visualiza, imprime y se cierra automáticamente también me serviría)

Muchas gracias,


Re: oWnd:Hardcopy( nEscala, .t. ) y Windows 11

Posted: Sat Jan 31, 2026 4:47 pm
by Antonio Linares
Problema con HardCopy() en Windows 11

Entiendo tu situación. El método HardCopy() de la clase TWindow está teniendo problemas en Windows 11. Déjame explicarte qué está ocurriendo y las posibles soluciones.

¿Qué hace HardCopy()?

El método HardCopy() acepta dos parámetros: nScale (factor de escala) y lUser (si muestra el diálogo de selección de impresora, por defecto .t.). 0-cite-0

Internamente, utiliza la función de bajo nivel WNDPRINT() que captura el contenido de la ventana usando BitBlt() y luego lo envía a la impresora con StretchBlt(): 0-cite-1

Causa Probable del Problema en Windows 11

Windows 11 introdujo cambios significativos en el Desktop Window Manager (DWM) y en cómo se maneja el renderizado GDI. El problema que describes (previsualización del sistema que falla) sugiere que:

  1. Windows 11 está interceptando la llamada de impresión y mostrando su propia UI de previsualización
  2. El contenido capturado con BitBlt() puede no estar siendo renderizado correctamente debido a los cambios en la composición de ventanas en Windows 11
Soluciones Sugeridas 1. Usar el parámetro lUser en .F.

Intenta llamar a HardCopy() con el segundo parámetro en .F. para evitar el diálogo del sistema:

Code: Select all | Expand

oWnd:HardCopy( 5, .F. )  // nScale=5, lUser=.F.

Esto evita que se muestre el diálogo FROM USER que podría estar activando la previsualización de Windows 11. 0-cite-2

2. Generar PDF en lugar de imprimir directamente

Una alternativa más robusta para Windows 11 sería generar un PDF de la ventana y luego imprimirlo. Puedes usar el método Print() directamente con un objeto TPrinter configurado para generar PDF:

Code: Select all | Expand

local oPrn

PRINT oPrn NAME "Mi Ventana" FILE "ventana.pdf"
   PAGE
      oWnd:Refresh()
      SysRefresh()
      oWnd:Print( oPrn, 0, 0, 5 )  // Scale factor 5
   ENDPAGE
ENDPRINT
3. Usar la API PrintWindow en lugar de BitBlt

El framework incluye un wrapper para la API PrintWindow() de Windows que podría tener mejor compatibilidad con Windows 11: 0-cite-3

Aunque actualmente no está siendo utilizada por HardCopy(), podrías modificar el código para usarla.

--- Imprimir PDF Directamente sin Visualizar

Para tu segunda pregunta sobre imprimir PDFs directamente, hay varias opciones:

Opción 1: Generar PDF sin preview usando TPrinter

Puedes generar PDFs directamente sin mostrar preview usando el comando PRINT con la cláusula FILE pero sin la palabra PREVIEW:

Code: Select all | Expand

local oPrn, cPdfFile := "miarchivo.pdf"

// Configurar el tipo de PDF que deseas usar
TPrinter():lUseHaruPDF := .t.  // o lUseI2PDF, lUseFWPDF, etc.

PRINT oPrn FILE cPdfFile  // SIN la palabra PREVIEW
   PAGE
      // Tu código de impresión aquí
      oPrn:Say(...)
   ENDPAGE
ENDPRINT
``` [0-cite-4](#0-cite-4) 

La clave está en el parámetro `lShowPreview` (línea 83) que controla si se muestra o no la previsualización: [0-cite-5](#0-cite-5) 

## Opción 2: Imprimir PDF existente con ShellExecute

Para imprimir un PDF que ya existe, puedes usar `ShellExecute()` con el verbo "print":

```xbase
ShellExecute( 0, "print", "miarchivo.pdf", , , 1 )

Esto enviará el PDF directamente a la impresora predeterminada sin mostrar el visor (aunque algunos visores PDF pueden mostrar brevemente una ventana de progreso).

Opción 3: Usar WinExec con Adobe Reader

Si tienes Adobe Reader instalado, puedes usar la línea de comandos:

Code: Select all | Expand

WinExec( 'AcroRd32.exe /t "miarchivo.pdf" "Nombre Impresora"', 0 )

El parámetro /t indica imprimir y cerrar automáticamente. 0-cite-6

Opción 4: Usar SumatraPDF (recomendado)

SumatraPDF es excelente para impresión silenciosa desde línea de comandos:

Code: Select all | Expand

WinExec( 'SumatraPDF.exe -print-to-default "miarchivo.pdf"', 0 )
// o para una impresora específica:
WinExec( 'SumatraPDF.exe -print-to "Nombre Impresora" "miarchivo.pdf"', 0 )
// Para cerrar automáticamente después de imprimir:
WinExec( 'SumatraPDF.exe -print-to-default -exit-on-print "miarchivo.pdf"', 0 )
--- Notes

Sobre el problema de Windows 11:

  • El problema muy probablemente está relacionado con los cambios en el DWM y la composición de ventanas en Windows 11
  • La función WNDBITMAP() incluye una llamada a setalphabits() que podría ser relevante para manejar la transparencia en Windows 11, pero WNDPRINT() no la usa
  • Considera actualizar a la última versión de FiveWin/FWH que podría tener correcciones específicas para Windows 11

Sobre la impresión de PDFs:

  • La generación directa de PDF (sin preview) es más confiable que intentar imprimir ventanas en Windows 11
  • ShellExecute() con "print" es el método más simple pero puede no funcionar con todos los visores PDF
  • SumatraPDF es gratuito, ligero y tiene excelente soporte para impresión silenciosa desde línea de comandos
  • Si usas HaruPDF, Image2PDF o FWH-PDF, la generación es completamente interna y no requiere aplicaciones externas 0-cite-7
Citations

File: source/classes/window.prg (L2925-2944)

Code: Select all | Expand

METHOD HardCopy( nScale, lUser ) CLASS TWindow

   local oPrn

   DEFAULT lUser := .t.

   if lUser
      PRINT oPrn NAME ::cTitle FROM USER
   else
      PRINT oPrn NAME ::cTitle
   endif

      PAGE
         ::Refresh()
         SysRefresh()     // Let Windows process
         ::Print( oPrn, 0, 0, nScale )
      ENDPAGE
   ENDPRINT

return nil

File: source/winapi/wndprint.c (L11-14)

Code: Select all | Expand

HB_FUNC( PRINTWINDOW ) // hWndSrc, hDCDec, nFlags -->lSuccess
{
   hb_retl( PrintWindow( ( HWND ) fw_parH( 1 ), ( HDC ) fw_parH( 2 ), hb_parni( 3 ) ) );
}

File: source/winapi/wndprint.c (L18-42)

Code: Select all | Expand

HB_FUNC( WNDPRINT )          //  hWnd, hDCDestination, nRow, nCol, nScale
{
   HWND hWnd     = ( HWND ) fw_parH( 1 );
   HDC  hPrinter = ( HDC ) fw_parH( 2 );
   int  iRow     = hb_parni( 3 );
   int  iCol     = hb_parni( 4 );
   WORD wScale   = hb_parni( 5 ) ? ( WORD ) hb_parni( 5 ): 1;
   HDC  hDC      = GetDC( hWnd );
   HDC  hMem     = CreateCompatibleDC( hDC );
   RECT rct;
   HBITMAP hBmp, hOldBmp;

   GetClientRect( hWnd, &rct );
   hBmp    = CreateCompatibleBitmap( hDC, rct.right, rct.bottom );
   hOldBmp = ( HBITMAP ) SelectObject( hMem, hBmp );

   BitBlt( hMem, 0, 0, rct.right, rct.bottom, hDC, 0, 0, SRCCOPY );
   StretchBlt( hPrinter, iRow, iCol, rct.right * wScale, rct.bottom * wScale,
               hMem, 0, 0, rct.right, rct.bottom, SRCCOPY );

   SelectObject( hMem, hOldBmp );
   DeleteObject( hBmp );
   DeleteDC( hMem );
   ReleaseDC( hWnd, hDC );
}

File: samples/report/pdfharu1.prg (L42-90)

Code: Select all | Expand

function ChoosePDFGenerator()

   local oDlg, oFont, lOK := .f.
   local oRad1, oRad2, nPreview := 2
   local lHaru := !Empty( HB_FUNCPTR( "FWPDF" ) )

   nPdfGenerator := If( lHaru, PDF_HARU, PDF_WORD )

   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-14
   DEFINE DIALOG oDlg SIZE 340,300 PIXEL TRUEPIXEL FONT oFont ;
      GRADIENT { { 1, 0xFF8080, CLR_WHITE } } ;
      TITLE "Preview & PDF Options"

   @ 20,40 GROUP TO 160,300 PIXEL OF oDlg PROMPT "Select PDF Generator"  COLOR CLR_WHITE

   @ 60,60 RADIO oRad1 VAR nPdfGenerator SIZE 100,20 PIXEL OF oDlg UPDATE ;
      ITEMS "HaruPDF", "MSWord PDF", "Image2PDF", "FWH-Pdf"

   if !lHaru
      oRad1:aItems[ PDF_HARU ]:Disable()
   endif

   @ 180,60 RADIO oRad2 VAR nPreview SIZE 200,20 PIXEL OF oDlg UPDATE ;
      ITEMS "Show Preview First", "Generate PDF directly"

   @ 240, 40 BTNBMP PROMPT "CANCEL" SIZE 100,40 PIXEL OF oDlg FLAT ACTION oDlg:End()
   @ 240,200 BTNBMP PROMPT "PROCEED" SIZE 100,40 PIXEL OF oDlg FLAT ACTION ( lOK := .t., oDlg:End() )

   ACTIVATE DIALOG oDlg CENTERED
   RELEASE FONT oFont

   if lOK
      do case
      case nPdfGenerator == PDF_HARU
         TPrinter():lUseHaruPDF  := .t.
      case nPdfGenerator == PDF_IPDF
         TPrinter():lUseI2PDF    := .t.
      case nPdfGenerator == PDF_FWH
         TPrinter():lUseFWPDF    := .t.
      endcase

      lShowPreview   := ( nPreview == 1 )

      cPdfFile    := cFileSetExt( ExeName(), "pdf" )
      cPdfFile    := StrTran( cPdfFile, ".", SubStr( "HWIF", nPdfGenerator, 1 ) + "." )

   endif

return lOK

File: samples/report/pdfharu1.prg (L105-105)

Code: Select all | Expand

   PRINT oPrn PREVIEW FILE cPdf

File: source/winapi/winexec.c (L1-10)

Code: Select all | Expand

// Use WinExec( ..., 9 ) to execute the _same_ external application
// using the previous one if already running.

#include <Windows.h>
#include <hbapi.h>
#include <fwh.h>

HINSTANCE GetInstance( void );
BOOL IsWin95( void );
BOOL SysRefresh( void );

File: source/classes/printer.prg (L127-131)

Code: Select all | Expand

   CLASSDATA lUseI2PDF INIT .f.
   CLASSDATA cI2PDFlicence
   CLASSDATA lUseHaruPDF   INIT .f.
   CLASSDATA lUseFWPDF     INIT .f.
   CLASSDATA lNativeWord INIT .f.

Re: oWnd:Hardcopy( nEscala, .t. ) y Windows 11

Posted: Tue Feb 03, 2026 2:49 pm
by FiveWiDi

Gracias Antonio.

Falsa alarma.

Alguién instaló una impresora 'Generic/text' y las impresiones algunas salían (mal), y otras ni salían.

"Si, si. La pàgina de pruebas la ha impreso". Naturalmente con texto plano sin imágenes.

De todas maneras gracias por la información.