Delphi 将命令直接发送到打印机的正确方法!

Delphi 将命令直接发送到打印机的正确方法!,delphi,printing,epson,Delphi,Printing,Epson,好的,我是这样做的: procedure TMainWindow.btnRawPrintClick(Sender: TObject); begin BeginPrint; SendStr(#27#69); SendStr('MyData'); SendStr(#10); EndPrint; end; procedure TMainWindow.SendStr(Text: String); var i: Integer; data : Array of Char; b

好的,我是这样做的:

procedure TMainWindow.btnRawPrintClick(Sender: TObject);
begin
  BeginPrint;
  SendStr(#27#69);
  SendStr('MyData');
  SendStr(#10);
  EndPrint;
end;

procedure TMainWindow.SendStr(Text: String);
var
  i: Integer;
  data : Array of Char;
begin
  for i := 1 to Length(Text) do
  begin
    SetLength(data,i);
    data[Pred(i)] := Text[i];
  end;

  if (PrintRawData(printHandle,
                   data,
                   Length(data)) < 0) then begin
    ShowMessage('PrintRawData Failed');
    EndRawPrintPage(printHandle);
    EndRawPrintJob(printHandle);
    exit;
  end;
end;

procedure TMainWindow.BeginPrint;
begin
  printHandle := StartRawPrintJob('EPSON TM-T70 Receipt','ESDPRT001','Test Document');

  if printHandle < 0 then
  begin
    ShowMessage('StartRawPrintJob Failed!');
    exit;
  end;

  if (StartRawPrintPage(printHandle) < 0) then begin
    ShowMessage('StartRawPrintPage Failed!');
    EndRawPrintJob(printHandle);
    exit;
  end;
end;

procedure TMainWindow.EndPrint;
begin
  if (EndRawPrintPage(printHandle) < 0) then begin
    ShowMessage('EndRawPrintPage Failed');
    EndRawPrintJob(printHandle);
    exit;
  end;

  if (EndRawPrintJob(printHandle) < 0) then begin
    ShowMessage('EndRawPrintJob Failed');
    exit;
  end;
end;
procedure TMainWindow.btnRawPrintClick(发送方:ToObject);
开始
开始打印;
SendStr(#27#69);
SendStr(“MyData”);
SendStr(#10);
尾迹;
结束;
过程TMainWindow.SendStr(文本:字符串);
变量
i:整数;
数据:字符数组;
开始
对于i:=1到长度(文本)do
开始
设置长度(数据,i);
数据[Pred(i)]:=文本[i];
结束;
如果(PrintRawData)(printHandle,
数据,
长度(数据))<0)然后开始
ShowMessage(“PrintRawData失败”);
EndRawPrintPage(打印手柄);
EndRawPrintJob(打印句柄);
出口
结束;
结束;
程序TMainWindow.BeginPrint;
开始
printHandle:=StartRawPrintJob('EPSON TM-T70收据'、'ESDPRT001'、'测试文件');
如果printHandle<0,则
开始
ShowMessage('StartRawPrintJob失败!');
出口
结束;
如果(StartRawPrintPage(printHandle)<0),则开始
ShowMessage('StartRawPrintPage失败!');
EndRawPrintJob(打印句柄);
出口
结束;
结束;
程序TMainWindow.EndPrint;
开始
如果(EndRawPrintPage(printHandle)<0),则开始
ShowMessage('EndRawPrintPage失败');
EndRawPrintJob(打印句柄);
出口
结束;
如果(EndRawPrintJob(printHandle)<0),则开始
ShowMessage('EndRawPrintJob失败');
出口
结束;
结束;
此外,我还更改了我从中获取的一些代码:

函数PrintRawData(hPrn:THandle;
缓冲区:指针;
NumBytes:SpoolInt):整数;
{$IFDEF WIN32}
变量
BytesWrite:德沃德;
{$ENDIF}
开始

NumBytes:=NumBytes*2// 你使用了错误的函数。使用,将PASSTHROUGH标志作为第二个参数传递。这会将未经处理的原始转义码直接发送到打印机


Joe Hecht(以前来自Borland)几次发布了一个单元,使这变得更容易。我在这里找到了。

由于Ansi和Unicode字符之间的更改,您当前的代码正在以错误的格式向打印机发送数据。您正在使用的打印机显然能够容忍一定数量的错误,这就是为什么您的一些命令可以工作的原因,但有一个限制

在您的Delphi版本中,
Char
相当于
WideChar
,因此将
Char
代码改为使用
AnsiChar
,这样您就可以按照打印机的要求发送单字节字符。您的
PrintRawData
函数以前没有问题。你找错钱了。打印机不希望接收双字节Unicode字符,但这就是您所做的更改

还原原始的
PrintRawData
代码后,将
SendStr
函数更改为:

procedure TMainWindow.SendStr(const Text: string);
var
  data: AnsiString;
begin
  data := Text;

  if (PrintRawData(printHandle,
                   PAnsiChar(data),
                   Length(data)) < 0) then begin
    ShowMessage('PrintRawData Failed');
    EndRawPrintPage(printHandle);
    EndRawPrintJob(printHandle);
  end;
end;
过程TMainWindow.SendStr(常量文本:字符串);
变量
资料来源:AnsiString;
开始
数据:=文本;
如果(PrintRawData)(printHandle,
PAnsiChar(数据),
长度(数据))<0)然后开始
ShowMessage(“PrintRawData失败”);
EndRawPrintPage(打印手柄);
EndRawPrintJob(打印句柄);
结束;
结束;
我对代码做了以下更改:

  • Char
    数组替换为
    AnsiString
  • 与使用循环一次增加一个字符的数据数组不同,使用单个赋值语句进行Unicode到Ansi的转换,并让RTL负责转换
  • 键入将数据字符串强制转换为
    PAnsiChar
    ,以传递到
    PrintRawData
  • 除非需要修改字符串参数的内容,否则将其作为常量传递
  • 当函数已经完成时,不需要显式的
    exit
    语句

  • 你是怎样把代码送到打印机的?直接到LPT1:还是其他方法?您是否已启用打印机调试模式以查看正在发送的十六进制数?您将发送什么来代替
    ESC
    ?对于大多数较旧的爱普生打印机,它是ASCII字符#27。是的,我发送#27而不是ESC。我使用WinAPI WritePrinter函数发送命令!谢谢你的帖子。我更新了我的帖子,添加了一些代码。但是,我不理解将PASSTHROUGH标志作为第二个参数。第二个参数是什么函数?你能再解释一下吗?Peacelyk,Ken指的是Windows API函数。@Peacelyk:对不起。我忘了在我的原始答案中提供MSDN上转义的链接。我现在已经更新了。肯,np。我一定要检查一下。迂腐的一点:我喜欢注释行数据:=文本来表示“Unicode到ansi的转换在这里发生”,因为这是一种潜在的有损转换。虽然这段代码可能会解决问题,但几句解释将对当前和未来的读者有很大帮助。
    procedure TMainWindow.SendStr(const Text: string);
    var
      data: AnsiString;
    begin
      data := Text;
    
      if (PrintRawData(printHandle,
                       PAnsiChar(data),
                       Length(data)) < 0) then begin
        ShowMessage('PrintRawData Failed');
        EndRawPrintPage(printHandle);
        EndRawPrintJob(printHandle);
      end;
    end;
    
    Procedure StrLstYazdir(pYazilacakListe: TStringList; pYazici: String);
    var
      hPrn: THandle;
      yazilacakVeri: AnsiString;
      intA: Integer;
    begin
      hPrn := StartRawPrintJob(PChar(pYazici), '', 'Varakim');
      if (Integer(hPrn) < 0) then
      Begin
        ShowMessage('StartRawPrintJob Hatalı');
        Exit;
      End;
    
      if (StartRawPrintPage(hPrn) < 0) then
      Begin
        ShowMessage('StartRawPrintPage Hatalı');
        EndRawPrintJob(hPrn);
        Exit;
      end;
    
      For intA := 0 to pYazilacakListe.Count - 1 do
      Begin
        yazilacakVeri := pYazilacakListe[intA] + #13 + #10;
    
        if (PrintRawData(hPrn, PAnsiChar(yazilacakVeri), Length(yazilacakVeri)) < 0)
        then
        begin
          ShowMessage('PrintRawData Hatalı');
          EndRawPrintPage(hPrn);
          EndRawPrintJob(hPrn);
          Exit;
        End;
      End;
      if (EndRawPrintPage(hPrn) < 0) then
      begin
        ShowMessage('EndRawPrintPage Hatalı');
        EndRawPrintJob(hPrn);
        Exit;
      End;
    
      if (EndRawPrintJob(hPrn) < 0) then
      begin
        ShowMessage('EndRawPrintJob Hatalı');
        Exit;
      End;
    End;
    
    StrLstYazdir(Memo1.Lines ,'Lexmark Forms Printer 2491')