【问题标题】:Is there are any way to send command to printer without printer.BeginDoc/EndDoc?有没有什么方法可以在没有printer.BeginDoc/EndDoc 的情况下向打印机发送命令?
【发布时间】:2014-05-28 04:32:42
【问题描述】:

我有一台 HP 收据打印机 A799,它可以连接和控制一个抽屉 如果有任何打印信号发送到打印机,打印机将发送信号打开抽屉。 有两个问题。

第一个问题:

如果我在程序中添加了 Printer.BeginDoc 和 Printer.EndDoc,我可以成功地向打印机发送命令。(我尝试向打印机发送测试打印请求,它是成功的)

但问题是当我尝试发送查询命令(例如询问打印机将抽屉状态发送给我)时,它也将进纸一行并打开抽屉。

这个动作的原因是Printer.BeginDoc和Printer.EndDoc?我尝试从我的代码中删除它们,但是当我现在向打印机发送任何命令时,打印机和抽屉不会做任何事情。

第二个问题:

ExtEscape(Printer.Handle, PASSTHROUGH, SizeOf(BufferIN), @BufferIn, 4, @BufferOut)

BufferIn 和 BufferOut 也是 PChar 我用这个功能带到打印机上,我试过这个功能是有效的(尝试测试打印)

我尝试将查询命令发送到打印机,但之后 BufferOut 没有得到任何返回,它仍然是一个空 PChar。

有人有解决办法吗?

【问题讨论】:

    标签: delphi printing


    【解决方案1】:

    我将回答您的第一个问题 - 第二个问题应移至此处的单独帖子,并作为单独问题提出。

    您可以直接使用Print Spooler API(来自 WinSpool.pas 单元)将内容发送到打印机,而无需使用 BeginDoc/EndDoc。下面是一个将文件直接打印到打印机的示例(几年前由 TeamB 的 Peter Above 发布在旧 Borland/CodeGear Delphi 论坛之一):

    uses 
      WinSpool;
    
    procedure PrintFile(const sFileName: string);
    const
      BufSize = 16384;
    var
      Count, BytesWritten: integer;
      hPrinter: THandle;
      Device : array[0..255] of char;
      Driver : array[0..255] of char;
      Port   : array[0..255] of char;
      hDeviceMode: THandle;
      DocInfo: TDoc_Info_1;
      f: file;
      Buffer: Pointer;
    begin
      Printer.PrinterIndex := -1;
      Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
      if not WinSpool.OpenPrinter(@Device, hPrinter, nil) then exit;
      DocInfo.pDocName := 'MyDocument';
      DocInfo.pOutputFile := nil;
      DocInfo.pDatatype := 'RAW';
      if StartDocPrinter(hPrinter, 1, @DocInfo) = 0 then
      begin
        WinSpool.ClosePrinter(hPrinter);
        exit;
      end;
      if not StartPagePrinter(hPrinter) then
      begin
        EndDocPrinter(hPrinter);
        WinSpool.ClosePrinter(hPrinter);
        exit;
      end;
      System.Assign(f, sFileName);
      try
        Reset(f, 1);
        GetMem(Buffer, BufSize);
        while not eof(f) do
        begin
          Blockread(f, Buffer^, BufSize, Count);
          if Count > 0 then
          begin
            if not WritePrinter(hPrinter, Buffer, Count, BytesWritten) then
            begin
              EndPagePrinter(hPrinter);
              EndDocPrinter(hPrinter);
              WinSpool.ClosePrinter(hPrinter);
              FreeMem(Buffer, BufSize);
              exit;
            end;
          end;
        end;
        FreeMem(Buffer, BufSize);
        EndDocPrinter(hPrinter);
        WinSpool.ClosePrinter(hPrinter);
      finally
        System.Closefile( f );
      end;
    end;
    

    这是一个读取我找到的打印机状态的示例(再次由 TeamB 的 Peter 下面提供)- 它在 Delphi 2007 中进行了测试,因此可能需要对某些类型进行一些小的调整以用于更高版本的 Delphi:

    Uses WinSpool;
    
    function GetCurrentPrinterStatus: DWORD;
    var
      hPrinter: THandle;
      Device : array[0..255] of char;
      Driver : array[0..255] of char;
      Port   : array[0..255] of char;
      hDeviceMode: THandle;
      bytesNeeded, bytesWritten: Cardinal;
      pPI: PPrinterInfo2;
      Defaults: TPrinterDefaults;
    begin
      Assert( Printer.PrinterIndex >= 0 );
      Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
      FillChar( Defaults, Sizeof(Defaults), 0 );
      Defaults.DesiredAccess:= 
        PRINTER_ACCESS_ADMINISTER or PRINTER_ACCESS_USE;
      Win32Check(WinSpool.OpenPrinter(@Device, hPrinter, @Defaults ));
      try
        WinSpool.GetPrinter(
          hPrinter,
          2,
          Nil, 0, @bytesNeeded );
        GetMem( pPI, bytesNeeded );
        try
          Win32Check(WinSpool.GetPrinter(
            hPrinter, 2,
            pPI, bytesNeeded, @bytesNeeded ));
          Result := pPI^.Status;
        finally
          FreeMem( pPI );
        end;
      finally
        WinSpool.ClosePrinter( hPrinter );
      end;
    end;
    

    API 文档为您提供有关PRINTER_INFO_2 及其返回标志的更多信息。您可以使用以下方式检查特定标志:

    if (Status and PRINTER_STATUS_ERROR) <> 0 then
      // Printer is in error status
    

    【讨论】:

    • 我只想知道你在这段代码中使用的单位,因为类型 TDoc_Info_1 没有建立,还有打印机。
    • @Oussaki: TDoc_Info_1WinSpool 中(在我的代码中显示在两个块中 - 请参见每个块的第一行),PrinterPrinters 中,其中所有位于标准 Delphi 打印机代码的位置。
    • 好的,并且类型(TDoc_Info_1)在较新版本的Delphi中发生了变化,至少我使用的是XE7,所以改为TDocInfo1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 2018-12-25
    • 1970-01-01
    • 2017-11-17
    相关资源
    最近更新 更多