Ir al contenido


Foto

[MULTILENGUAJE] Cancelar los trabajos de impresión desde código


  • Por favor identifícate para responder
2 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 28 mayo 2023 - 05:41

En esta ocasión quiero mostrar cómo cancelar los trabajos de impresión de una determinada impresora, se cancelarán los trabajos de la cola de Windows pero no los que estén ya en el buffer de la impresora.

El ejemplo en cuestión muestra código usando la API de Windows.

 

Estas son las funciones de la API de Windows usadas:

OpenPrinter para encontrar el Handle de la impresora
GetPrinter para encontrar el número de trabajos de impresión de esa impresora
EnumJobs para tener un array con todos los trabajos de impresión pendientes de la impresora
SetJob para, en este caso, calcelar un trabajo de impresión.

EnumJobs devuelve un puntero a un array estilo c, que es un puntero al primer elemento del array. En delphi tenemos que inventar un cast para lo que defino TAJOB_INFO_2 y PAJOB_INFO_2. Con ello el puntero devuelto lo convertimos directamante a un array y tranbajamos como lo haríamos en C.
    

Este código es de mucha utilidad cuando se lanzan un gran número de trabajos, de varias hojas y en un momento dado se quiere cancelar todo desde nuestra aplicación para evitar saturar una impresora o evitar el gasto innecesario de papel, sin necesidad de abrir la cola de impresión desde Windows.

 

La versión sobrecargada CancelPrintJobs() es para trabajar directamente con la impresora seleccionada por defecto en nuestra aplicación, nos ahorra encontrar y escribir su nombre.
 
 


delphi
  1. uses
  2.   Windows, Printers, Winspool; //.......
  3.  
  4. type
  5.  
  6.   LPPRINTER_INFO_2 = ^PRINTER_INFO_2;
  7.   TAJOB_INFO_2     = array [0..0] of JOB_INFO_2;
  8.   PAJOB_INFO_2     = ^TAJOB_INFO_2;
  9.  
  10. //......................
  11.  
  12.  
  13. function CancelPrintJobs(PrinterName: String): boolean; overload;
  14. var
  15.   hPrinter:     THandle;
  16.   BytesNeeded:  DWORD;
  17.   BytesUsed:    DWORD;
  18.   jobCount:     DWORD;
  19.   pPrinterInfo: LPPRINTER_INFO_2;
  20.   pJobsInfo:    PAJOB_INFO_2;
  21.   i: integer;
  22. begin
  23.   hPrinter:= 0;
  24.   BytesNeeded:= 0;
  25.   BytesUsed:= 0;
  26.   Result:= false;
  27.  
  28.   // Abre la impresora
  29.   if OpenPrinter(PCHAR(PrinterName), hPrinter, nil) then
  30.   begin
  31.     // Obtiene el número de trabajos de impresión en cola
  32.     GetPrinter(hPrinter, 2, nil, 0, @BytesNeeded);
  33.     GetMem(pPrinterInfo, BytesNeeded);
  34.     if GetPrinter(hPrinter, 2, pPrinterInfo, BytesNeeded, @BytesUsed) then
  35.     begin
  36.       jobCount:= pPrinterInfo.cJobs;
  37.       // Obtiene la información de los trabajos de impresión
  38.       EnumJobs(hPrinter, 0, jobCount, 2, nil, 0, BytesNeeded, BytesUsed);
  39.       GetMem(pJobsInfo, BytesNeeded);
  40.       if EnumJobs(hPrinter, 0, jobCount, 2, pJobsInfo, BytesNeeded, BytesUsed, BytesUsed)then
  41.       begin
  42.         // Cancela cada trabajo de impresión en cola
  43.         Result:= true;
  44.         for i:= 0 to jobCount-1 do
  45.           Result:= Result and SetJob(hPrinter, pJobsInfo[i].JobId, 0, nil, JOB_CONTROL_CANCEL);
  46.       end;
  47.     end;
  48.   end;
  49.   FreeMem(pPrinterInfo);
  50.   FreeMem(pJobsInfo);
  51.   ClosePrinter(hPrinter);
  52. end;
  53.  
  54.  
  55.  
  56. function CancelPrintJobs(): boolean; overload;
  57. var
  58.   PrinterName: String;
  59. begin
  60.   PrinterName:= Printer.Printers.Strings[Printer.PrinterIndex];
  61.   Result:= CancelPrintJobs(PrinterName);
  62. end;

 



Saludos.


  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 28 mayo 2023 - 05:43

La versión C/C++ de esta función sería esta:

 

Nótese que uso las versiones "A" de la API para forzar a no uso de UNICODE. Si se desea UNICODE hay que eliminar esas "A" de las funciones y estructuras, también se debería eliminar AnsiString para sustituirlo por String.


cpp
  1. #include <Windows.h>
  2. #include <Winspool.h>
  3.  
  4.  
  5.  
  6. BOOL CancelPrintJobs(char* PrinterName)
  7. {
  8.   HANDLE hPrinter   = 0;
  9.   DWORD BytesNeeded = 0;
  10.   DWORD BytesUsed   = 0;
  11.   DWORD jobCount;
  12.   PRINTER_INFO_2A *pPrinterInfo;
  13.   JOB_INFO_2* pJobsInfo;
  14.   BOOL Error = false;
  15.  
  16.   // Abre la impresora
  17.   if(!OpenPrinterA(PrinterName, &hPrinter, 0))
  18.     return false;
  19.  
  20.   // Obtiene el número de trabajos de impresión en cola
  21.   GetPrinterA(hPrinter, 2, NULL, 0, &BytesNeeded);
  22.   pPrinterInfo = (PRINTER_INFO_2A*)new BYTE[BytesNeeded];
  23.   if(!GetPrinterA(hPrinter, 2, (LPSTR)pPrinterInfo, BytesNeeded, &BytesUsed)){
  24.     delete [] pPrinterInfo;
  25.     ClosePrinter(hPrinter);
  26.     return FALSE;
  27.   }
  28.   jobCount = pPrinterInfo->cJobs;
  29.  
  30.   // Obtiene la información de los trabajos de impresión
  31.   EnumJobs(hPrinter, 0, jobCount, 2, NULL, 0, &BytesNeeded, &BytesUsed);
  32.   pJobsInfo = (JOB_INFO_2*)new BYTE[BytesNeeded];
  33.   if(!EnumJobsA(hPrinter, 0, jobCount, 2, (LPBYTE)pJobsInfo, BytesNeeded, &BytesUsed, &BytesUsed)){
  34.     ClosePrinter(hPrinter);
  35.     delete [] pJobsInfo;
  36.     return false;
  37.   }
  38.  
  39.   // Cancela cada trabajo de impresión en cola
  40.   for(DWORD i = 0; i < jobCount; ++i)
  41.     Error |= !SetJobA(hPrinter, pJobsInfo[i].JobId, 0, NULL, JOB_CONTROL_CANCEL);
  42.  
  43.   // Limpia la memoria y cierra la impresora
  44.   delete [] pPrinterInfo;
  45.   delete [] pJobsInfo;
  46.   ClosePrinter(hPrinter);
  47.   return !Error;
  48. }
  49. //---------------------------------------------------------------------------
  50.  
  51. #include <vcl.h>
  52. BOOL CancelPrintJobs()
  53. {
  54. AnsiString PrinterName = Printer()->Printers->Strings[Printer()->PrinterIndex];
  55. return CancelPrintJobs(PrinterName.c_str());
  56. }
  57. //---------------------------------------------------------------------------

Saludos.


  • 0

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 29 mayo 2023 - 08:32

Excelente utilería. y por supuesto muy necesaria.

 

(y)

 

Saludos


  • 0




IP.Board spam blocked by CleanTalk.