Delphi 打印到通用文本驱动程序(Intermec PM4i)?

Posted

技术标签:

【中文标题】Delphi 打印到通用文本驱动程序(Intermec PM4i)?【英文标题】:Delphi printing to Generic text driver (Intermec PM4i)? 【发布时间】:2014-11-08 05:43:13 【问题描述】:

(edit这个问题很少有人反对。我不知道原因,仍然看不出它有什么问题。如果反对者可以评论他们希望看到的更好的东西,我可以编辑这个书面或缺乏有价值的信息,我没有提供)。

我有 Intermec PM4i 标签打印机和通用文本打印驱动程序。我可以从记事本或 Delphi 调用 ShellExecute('printto',..) shellapi 函数打印文本文件脚本。

我发现了一些原始打印示例,但没有一个有效。 Delphi 应用程序如何在没有 shellapi 功能的情况下打印到 Generic_text_driver?这不是支持 GDI printer.canvas 的驱动程序。

我已经尝试过“一切”,甚至是传统的 PASSTHROUGH 打印示例。唯一的工作方法是 Notepad.exe 或 shellexecute('printto', 'tempfile.txt',...) 我猜这是在内部使用记事本。我可以看到记事本打印对话框在屏幕上闪烁。我想直接从 Delphi 应用程序控制它。

这个 printFileToGeneric 不起作用。

// https://groups.google.com/forum/#!topic/borland.public.delphi.winapi/viHjsTf5EqA
Procedure PrintFileToGeneric(Const sFileName, printerName, docName: string; ejectPage: boolean);
Const
  BufSize = 16384;
Var
  Count : Integer;
  BytesWritten: DWORD;
  hPrinter: THandle;
  DocInfo: TDocInfo1;
  f: file;
  Buffer: Pointer;
  ch: Char;
Begin
  If not WinSpool.OpenPrinter(PChar(printerName), hPrinter, nil) Then
    raise Exception.Create('Printer not found');

  Try
    DocInfo.pDocName := PChar(docName);
    DocInfo.pOutputFile := nil;
    DocInfo.pDatatype := 'RAW';
    If StartDocPrinter(hPrinter, 1, @DocInfo) = 0 Then
      Raise Exception.Create('StartDocPrinter failed');

    Try
      If not StartPagePrinter(hPrinter) Then
        Raise Exception.Create('StartPagePrinter failed');

      System.Assign(f, sFileName);
      Try
        Reset(f, 1);
        GetMem(Buffer, BufSize);
        Try
          While not eof(f) Do Begin
            Blockread(f, Buffer^, BufSize, Count);
            If Count > 0 Then Begin
              If not WritePrinter(hPrinter, Buffer, Count, BytesWritten) Then
                Raise Exception.Create('WritePrinter failed');
            End;
          End;
        Finally
          If ejectPage Then Begin
            ch:= #12;
            WritePrinter( hPrinter, @ch, 1, BytesWritten );
          End;
          FreeMem(Buffer, BufSize);
        End;
      Finally
        EndPagePrinter(hPrinter);
        System.Closefile( f );
      End;
    Finally
      EndDocPrinter(hPrinter);
    End;
  Finally
    WinSpool.ClosePrinter(hPrinter);
  End;
End;

以下 prtRaw 帮助器实用程序示例不起作用。

prtRaw.StartRawPrintJob/StartRawPrintPage/PrintRawData/EndRawPrintPage/EndRawPrintJob
http://www.swissdelphicenter.ch/torry/showcode.php?id=940

下面的 AssignPrn 方法不起作用。

function testPrintText(params: TStrings): Integer;
var
  stemp:String;
  idx: Integer;
  pOutput: TextFile;
begin
  Result:=0;    
    idx := getPrinterIndexByName( params.Values['printer'] );
    if (idx<0) then Raise Exception.Create('Printer not found');
    WriteLn('Use printer(text) ' + IntToStr(idx) + ' ' + Printer.Printers[idx] );

    Printer.PrinterIndex := idx;
    stemp := params.Values['jobname'];
    if (stemp='') then stemp:='rawtextprint';
    Printer.Title:=stemp;

    AssignPrn(pOutput);
    ReWrite(pOutput);

    stemp := 'INPUT ON'+#10;
    stemp := stemp + 'NASC 1252'+#10;
    stemp := stemp + 'BF OFF'+#10;
    stemp := stemp + 'PP 30,480:FT "Swiss 721 BT",8,0,100'+#10;
    stemp := stemp + 'PT "Test text 30,480 position ABC'+#10;
    Write(pOutput, stemp);
    //Write(pOutput, 'INPUT ON:');
    //Write(pOutput, 'NASC 1252:');
    //Write(pOutput, 'BF OFF:');
    //Write(pOutput, 'PP 30,480:FT "Swiss 721 BT",8,0,100:');
    //Write(pOutput, 'PT "Test text 30,480 position ABC":');
    //Write(pOutput, 'Text line 3 goes here#13#10');
    //Write(pOutput, 'Text line 4 goes here#13#10');    

    CloseFile(pOutput);
end;

这个 Printer.Canvas 没有打印任何东西,它应该已经打印了一些东西,因为记事本在内部使用 GDI 打印输出。这里缺少一些东西。

function testPrintGDI(params: TStrings): Integer;
var
  filename, docName:String;
  idx: Integer;
  lines: TStrings;
begin
  Result:=0;
  idx := getPrinterIndexByName( params.Values['printer'] );
  if (idx<0) then Raise Exception.Create('Printer not found');
  WriteLn('Use printer(gdi) ' + IntToStr(idx) + ' ' + Printer.Printers[idx] );
  docName := params.Values['jobname'];
  if (docName='') then docName:='rawtextprint';

  filename := params.values['input'];
  If Not FileExists(filename) then Raise Exception.Create('input file not found');

  Printer.PrinterIndex := idx;
  Printer.Title := docName;
  Printer.BeginDoc;
  lines := readTextLines(filename);
  try
    for idx := 0 to lines.Count-1 do begin
      Printer.Canvas.TextOut(10, 10*idx, lines[idx]);
    end;
  finally
    FreeAndNil(lines);
    Printer.EndDoc;
  end;
end;

只有三种有效的方法是从 Notepad.exe 打印、Delphi ShellExecute 调用或打开原始 TCP 套接字到 IP:PORT 地址并将文本行写入套接字输出流。

function testPrintPrintTo(params: TStrings): Integer;
var
  filename, printerName:String;
  idx: Integer;
  exInfo: TShellExecuteInfo;
  device,driver,port: array[0..255] of Char;
  hDeviceMode: THandle;
  timeout:Integer;
  //iRet: Cardinal;
begin
  Result:=0;

  idx := getPrinterIndexByName( params.Values['printer'] );
  if (idx<0) then Raise Exception.Create('Printer not found');
  WriteLn('Use printer(printto) ' + IntToStr(idx) + ' ' + Printer.Printers[idx] );

  filename := params.values['input'];
  If Not FileExists(filename) then Raise Exception.Create('input file not found');
  filename := uCommon.absoluteFilePath(filename);

  Printer.PrinterIndex := idx;
  Printer.GetPrinter(device, driver, port, hDeviceMode);
  printerName := Format('"%s" "%s" "%s"', [device, driver, port]);

  FillChar(exInfo, SizeOf(exInfo), 0);
  with exInfo do begin
    cbSize := SizeOf(exInfo);
    fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
    Wnd := 0;
    exInfo.lpVerb := 'printto';
    exInfo.lpParameters := PChar(printerName);
    lpFile := PChar(filename);
    lpDirectory := nil;
    nShow := SW_HIDE;
  end;
  WriteLn('printto ' + printerName);

  if Not ShellExecuteEx(@exInfo) then begin
    Raise Exception.Create('ShellExecuteEx failed');
    exit;
  end;

  try
    timeout := 30000;
    while WaitForSingleObject(exInfo.hProcess, 50) <> WAIT_OBJECT_0 do begin
      Writeln('wait timeout ' + IntToStr(timeout));
      dec(timeout, 50);
      if (timeout<1) then break;
    end;
  finally
    CloseHandle(exInfo.hProcess);
  end;

  iRet:=ShellExecute(0, 'printto',
      PChar(filename),
      PChar(printerName), //Printer.Printers[idx]),
      nil, //PChar(filepath),
      SW_HIDE  // SW_SHOWNORMAL
  );
  Writeln('printto return code ' + IntToStr(iRet)); // >32 OK 

end;

【问题讨论】:

记事本打印到 gdi 打印机 所以我可以使用 Printer.Canvas.TextOut('...') delphi 函数来通用文本驱动程序(Intermec PM4i 标签打印机)。不调用任何图形绘制函数可以使其尽可能简单。回到办公室后会试试这个。 【参考方案1】:

您可以使用以下程序: 其中 LabelFile 是标签文件的完整路径,我们正在使用此代码并与通用文本驱动程序打印机一起使用,并且打印机被设置为默认打印机。 它适用于斑马打印机和windows xp操作系统。

希望对你有帮助。

function PrintLabel(LabelName: String): Boolean;
var
  EfsLabel,dummy: TextFile;
  ch : Char;
begin
try
try
   Result:= False;
   AssignFile(EfsLabel,LabelName);
   Reset(EfsLabel);
   Assignprn(dummy);
   ReWrite(Dummy);

   While not Eof(EfsLabel) do
   begin
    Read(EfsLabel, Ch);
    Write(dummy, Ch);
   end;

   Result:= True;

except
  Result:=False;
  LogMessage('Error Printing Label',[],LOG_ERROR);
end;

finally
CloseFile(EfsLabel);
CloseFile(dummy);
end;

end;

【讨论】:

如果这有帮助,请重新格式化您的代码(缩进!),否则很难查看。【参考方案2】:

您可以从记事本打印到这台打印机。使用标准 GDI 机制的记事本打印。如果记事本可以做到这一点,那么你也可以。使用Printer.BeginDocPrinter.Canvas等打印到这台打印机。

【讨论】:

我使用打印机组件 Printer.BeginDoc / Printer.Canvas.TextOut('test print') / Printer.EndDoc 从 Delphi 进行了测试。什么都没有打印。记事本正在使用generictext 打印驱动程序做一些额外的技巧。我放弃并实现了到打印机IP:9100的原始tcp套接字并手动发送专有的FingerPrint + DirectProtocol命令。 记事本没有做任何额外的花样。它只是一台 GDI 打印机。老实说,我无法想象你还在寻找什么。在我看来,你好像不想得到建议,而是想按照自己的方式去做。在这种情况下,为什么要问? 哇哦,为什么会有这种敌意?如您所见,我已经广泛尝试并提供了所有示例代码。你们中的一些人可能会觉得它很有价值。就是这样,(Delphi)Printer.canvas 无法通过generictext 驱动程序工作。记事本确实通过相同的驱动程序工作。我通过原始套接字 11.22.33.44:9100 提交了相同的文本文档,它可以工作。当然,我在德尔福代码中遗漏了一部分,但无法弄清楚。你试过这款标签打印机吗? 记事本设法使用 GDI 进行打印。我猜您尝试打印的代码有缺陷。

以上是关于Delphi 打印到通用文本驱动程序(Intermec PM4i)?的主要内容,如果未能解决你的问题,请参考以下文章

Delphi Excel导入 的通用程序

delphi CANVAS打印是啥

delphi中,如何读取一个目录中的所有文件?在线等……

delphi如何调用dll函数

Delphi Excel导入 的通用程序

如何在DELPHI中用程序控制报表打印要素的位置