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.
uses Windows, Printers, Winspool; //....... type LPPRINTER_INFO_2 = ^PRINTER_INFO_2; TAJOB_INFO_2 = array [0..0] of JOB_INFO_2; PAJOB_INFO_2 = ^TAJOB_INFO_2; //...................... function CancelPrintJobs(PrinterName: String): boolean; overload; var hPrinter: THandle; BytesNeeded: DWORD; BytesUsed: DWORD; jobCount: DWORD; pPrinterInfo: LPPRINTER_INFO_2; pJobsInfo: PAJOB_INFO_2; i: integer; begin hPrinter:= 0; BytesNeeded:= 0; BytesUsed:= 0; Result:= false; // Abre la impresora if OpenPrinter(PCHAR(PrinterName), hPrinter, nil) then begin // Obtiene el número de trabajos de impresión en cola GetPrinter(hPrinter, 2, nil, 0, @BytesNeeded); GetMem(pPrinterInfo, BytesNeeded); if GetPrinter(hPrinter, 2, pPrinterInfo, BytesNeeded, @BytesUsed) then begin jobCount:= pPrinterInfo.cJobs; // Obtiene la información de los trabajos de impresión EnumJobs(hPrinter, 0, jobCount, 2, nil, 0, BytesNeeded, BytesUsed); GetMem(pJobsInfo, BytesNeeded); if EnumJobs(hPrinter, 0, jobCount, 2, pJobsInfo, BytesNeeded, BytesUsed, BytesUsed)then begin // Cancela cada trabajo de impresión en cola Result:= true; for i:= 0 to jobCount-1 do Result:= Result and SetJob(hPrinter, pJobsInfo[i].JobId, 0, nil, JOB_CONTROL_CANCEL); end; end; end; FreeMem(pPrinterInfo); FreeMem(pJobsInfo); ClosePrinter(hPrinter); end; function CancelPrintJobs(): boolean; overload; var PrinterName: String; begin PrinterName:= Printer.Printers.Strings[Printer.PrinterIndex]; Result:= CancelPrintJobs(PrinterName); end;
Saludos.