简体   繁体   English

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

[英]Cannot get the correct printer status

I am using Delphi 10.3 to create a program that prints labels with barcodes.我正在使用 Delphi 10.3 创建一个打印带有条形码的标签的程序。 I do not want the printer to queue multiple jobs instead i want to start printing the next job after the previous is finished and receive ready status from the printer.我不希望打印机将多个作业排队,而是我想在前一个作业完成后开始打印下一个作业并从打印机接收就绪状态。 The status of the printer is always ready, even if it is offline!打印机的状态始终处于就绪状态,即使它处于脱机状态!

I use this functions to get the status of the printer:我使用这个函数来获取打印机的状态:

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;

And then on a certain event i check for printer status using this code:然后在某个事件中,我使用以下代码检查打印机状态:

  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;

After this code i start the printing process and everything is in a loop for all the copies i need to print.在此代码之后,我开始打印过程,并且对于我需要打印的所有副本,一切都在循环中。

I am using a TSC-TPP 2410M printer and it never gives printing status although it queues the jobs.我使用的是 TSC-TPP 2410M 打印机,尽管它对作业进行排队,但它从不提供打印状态。 So the code never goes inside the while because i am always getting 0 printer status.所以代码永远不会进入,因为我总是得到 0 打印机状态。

Is there any way to disable the queue or to make the app wait for the printer to stop printing and then execute the next print job?有什么方法可以禁用队列或让应用程序等待打印机停止打印然后执行下一个打印作业? Any thoughts?有什么想法吗?

EDIT: After some suggestions from @BlurrySterk i discovered that the printer emits PRINTER_STATUS_PRINTING when the number of jobs in the queue get to 10. After printing all of them it gets ready again.编辑:在@BlurrySterk 提出一些建议后,我发现当队列中的作业数量达到 10 时,打印机会发出 PRINTER_STATUS_PRINTING。在打印完所有作业后,它会再次准备好。

It seems that there are limits to the WinAPI, as mentioned in the comments.如评论中所述,WinAPI 似乎存在限制。

Because the previous printer is dead now, we bought a TSC ME240.因为以前的打印机现在已经死了,我们买了一台 TSC ME240。 There is a programming manual for TSPL/2 commands in this link .链接中有 TSPL/2 命令的编程手册。

To solve the problem i connected the printer to the network and send TSPL/2 commands through a tcp socket.为了解决这个问题,我将打印机连接到网络并通过 tcp 套接字发送 TSPL/2 命令。

I needed this code to get the status我需要这段代码来获取状态

  // 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;

The printer is responding and the job is done.打印机正在响应并且作业已完成。 Thanks for all the effort guys/girls.感谢所有努力的男孩/女孩。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM