【发布时间】:2021-03-09 11:04:13
【问题描述】:
我正在使用 Delphi 10.3 创建一个打印带有条形码的标签的程序。我不希望打印机将多个作业排队,而是我想在前一个作业完成后开始打印下一个作业并从打印机接收就绪状态。打印机状态始终为就绪,即使处于离线状态!
我使用这个函数来获取打印机的状态:
function TPrintQRForm.GetCurrentPrinterHandle() : THandle;
var
Device, Driver, Port : Array[0..255] of Char;
hDeviceMode : THandle;
begin
Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
if not Winspool.OpenPrinter(@Device, Result, nil) then
begin
RaiseLastOSError();
end;
end;
function TPrintQRForm.GetCurrentPrinterInformation() : TPrinterInfo;
var
hPrinter : THandle;
pInfo : PPrinterInfo2;
bytesNeeded : DWORD;
begin
hPrinter := GetCurrentPrinterHandle();
try
Winspool.GetPrinter(hPrinter, 2, Nil, 0, @bytesNeeded);
pInfo := AllocMem(bytesNeeded);
try
Winspool.GetPrinter(hPrinter, 2, pInfo, bytesNeeded, @bytesNeeded);
Result.ServerName := pInfo^.pServerName;
Result.PrinterName := pInfo^.pPrinterName;
Result.ShareName := pInfo^.pShareName;
Result.PortName := pInfo^.pPortName;
Result.DriverName := pInfo^.pDriverName;
Result.Comment := pInfo^.pComment;
Result.Location := pInfo^.pLocation;
Result.DeviceMode := pInfo^.pDevMode;
Result.SepFile := pInfo^.pSepFile;
Result.PrintProcessor := pInfo^.pPrintProcessor;
Result.DataType := pInfo^.pDatatype;
Result.Parameters := pInfo^.pParameters;
Result.SecurityDescriptor := pInfo^.pSecurityDescriptor;
Result.Attributes := pInfo^.Attributes;
Result.DefaultPriority := pInfo^.DefaultPriority;
Result.StartTime := pInfo^.StartTime;
Result.UntilTime := pInfo^.UntilTime;
Result.Status := pInfo^.Status;
Result.Jobs := pInfo^.cJobs;
Result.AveragePPM := pInfo^.AveragePPM;
finally
FreeMem(pInfo);
end;
finally
ClosePrinter(hPrinter);
end;
end;
然后在某个事件中,我使用此代码检查打印机状态:
PrinterInfo := GetCurrentPrinterInformation();
while PrinterInfo.Status <> 0 do
begin
if PrinterInfo.Status = PRINTER_STATUS_PRINTING then
begin
// Get information about the selected printer
PrinterInfo := GetCurrentPrinterInformation();
// Process messages from the OS and do not freeze the UI
Application.ProcessMessages;
Continue;
end;
Case PrinterInfo.Status of
PRINTER_STATUS_PAUSED : ShowMessage('The printer is paused.');
PRINTER_STATUS_ERROR : ShowMessage('The printer is in an error state.');
PRINTER_STATUS_PENDING_DELETION : ShowMessage('The printer is being deleted.');
PRINTER_STATUS_PAPER_JAM : ShowMessage('Paper is jammed in the printer.');
PRINTER_STATUS_PAPER_OUT : ShowMessage('The printer is out of paper.');
PRINTER_STATUS_MANUAL_FEED : ShowMessage('The printer is in a manual feed state.');
PRINTER_STATUS_PAPER_PROBLEM : ShowMessage('The printer has a paper problem.');
PRINTER_STATUS_OFFLINE : ShowMessage('The printer is offline.');
PRINTER_STATUS_IO_ACTIVE : ShowMessage('The printer is in an active input/output state.');
PRINTER_STATUS_BUSY : ShowMessage('The printer is busy.');
PRINTER_STATUS_OUTPUT_BIN_FULL : ShowMessage('The printer''s output bin is full.');
PRINTER_STATUS_NOT_AVAILABLE : ShowMessage('The printer is not available for printing.');
PRINTER_STATUS_WAITING : ShowMessage('The printer is waiting.');
PRINTER_STATUS_PROCESSING : ShowMessage('The printer is processing a print job.');
PRINTER_STATUS_INITIALIZING : ShowMessage('The printer is initializing.');
PRINTER_STATUS_WARMING_UP : ShowMessage('The printer is warming up.');
PRINTER_STATUS_TONER_LOW : ShowMessage('The printer is low on toner.');
PRINTER_STATUS_NO_TONER : ShowMessage('The printer is out of toner.');
PRINTER_STATUS_PAGE_PUNT : ShowMessage('The printer cannot print the current page.');
PRINTER_STATUS_USER_INTERVENTION : ShowMessage('The printer has an error that requires the user to do something.');
PRINTER_STATUS_OUT_OF_MEMORY : ShowMessage('The printer has run out of memory.');
PRINTER_STATUS_DOOR_OPEN : ShowMessage('The printer door is open.');
PRINTER_STATUS_POWER_SAVE : ShowMessage('The printer is in power save mode.');
else
ShowMessage('The error is unknown');
end;
Exit;
end;
在这段代码之后,我开始打印过程,所有我需要打印的副本都在循环中。
我使用的是 TSC-TPP 2410M 打印机,尽管它对作业进行排队,但它从不提供打印状态。所以代码永远不会进入 while,因为我总是得到 0 打印机状态。
有什么方法可以禁用队列或让应用程序等待打印机停止打印然后执行下一个打印作业?有什么想法吗?
编辑:在@BlurrySterk 提出一些建议后,我发现当队列中的作业数达到 10 时,打印机会发出 PRINTER_STATUS_PRINTING。打印完所有作业后,它会再次准备好。
【问题讨论】:
-
我没有打印机的状态总是可用的。看看docs.microsoft.com/en-us/troubleshoot/windows/win32/…
-
感谢您的评论。我已经阅读了这篇文章,它说:“确定物理打印机的状态必须满足一个基本前提:假脱机程序必须尝试将打印作业发送到物理打印机。这是只有当端口监视器报告打印机的状态时。”。但我无法理解如何获取物理打印机状态... spooler 何时尝试打印?
-
打印作业到达打印队列后,后台打印程序将尝试打印。显然,指定打印作业必须立即打印还是仅在最后一页之后打印的 Windows 设置会影响这一点。但我怀疑作业通过队列的速度太快以至于状态没有改变。
-
我没有看到任何指定要获取信息的打印机的代码。我可以假设您正在测试的这台打印机实际上是 Windows 默认打印机吗?
-
Windows 管理打印机。用户决定他们是否使用打印后台处理程序。这不取决于你。为用户改变这一点是不友好的行为。您的应用程序需要管理权限才能在用户计算机上进行此配置更改。您不应更改用户的后台打印程序设置。如果这是针对您可以控制系统的嵌入式应用程序,则禁用打印后台处理程序似乎是您想要做的。