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.BeginDoc
、Printer.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)?的主要内容,如果未能解决你的问题,请参考以下文章