无法获得正确的打印机状态

Cannot get the correct printer status

我正在使用 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 打印机状态。

有什么方法可以禁用队列或让应用程序等待打印机停止打印然后执行下一个打印作业?有什么想法吗?

编辑: 在@BlurryStek 提出一些建议后,我发现当队列中的作业数量达到 10 时,打印机发出 PRINTER_STATUS_PRINTING。打印完所有他们又准备好了。

WinAPI 似乎有限制,如评论中所述。

因为之前的打印机已经不行了,所以买了一台TSC ME240。 link.

中有TSPL/2命令的编程手册

为了解决这个问题,我将打印机连接到网络并通过 tcp 套接字发送 TSPL/2 命令。

我需要此代码来获取状态

  // Create TCP Client
  TCPClient := TIdTCPClient.Create();

  // Connect to server
  TCPClient.Host := PrinterIP;
  TCPClient.Port := PrinterPort;
  TCPClient.Connect();

  // Set status string
  StatusString := #27 + '!?';

  // Send command
  TCPClient.Socket.WriteLn(StatusString);

  // Check status
  PrinterStatus := TCPClient.Socket.ReadByte;

打印机正在响应,作业已完成。感谢大家的努力guys/girls.