有没有办法在没有printer.BeginDoc / EndDoc的情况下向打印机发送命令?

时间:2014-05-27 02:52:38

标签: delphi printing

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

第一个问题:

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

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

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

第二个问题:

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

BufferIn和BufferOut也是PChar 我使用此功能带到打印机,我已经尝试此功能是工作(尝试测试打印)

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

有没有人有任何解决方案?

1 个答案:

答案 0 :(得分:2)

我会回答你的第一个问题 - 第二个问题应该转到这里的另一个帖子,并作为一个单独的问题提出。

您可以直接使用Print Spooler API(来自WinSpool.pas设备),在不使用BeginDoc / EndDoc的情况下向打印机发送内容。这是一个将文件直接打印到打印机的示例(几年前由TeamB的Peter Below发布在旧的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