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

时间:2011-05-09 11:55:00

标签: 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;
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;

我还改变了我从here获取的一些代码:

function PrintRawData(hPrn : THandle;
                      Buffer : pointer;
                      NumBytes : SpoolInt) : integer;
{$IFDEF WIN32}
var
  BytesWritten : DWORD;
 {$ENDIF}
begin
  NumBytes := NumBytes * 2;    //<-- I added this line
  ...

然而,由于某些命令(转义序列)无法按预期工作,因此出现了问题!

3 个答案:

答案 0 :(得分:6)

你使用了错误的功能。使用Escape,将PASSTHROUGH标志作为第二个参数传递。这会将原始未处理的转义码直接发送到打印机。

Joe Hecht(前身为Borland)已多次发布一个单元,这使得这更容易。我在这里找到unit PrtRaw

答案 1 :(得分:3)

由于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;

我对代码进行了以下更改:

  1. Char数组替换为AnsiString
  2. 不是使用循环一次一个字符地增加数据数组,而是使用单个赋值语句进行Unicode-to-Ansi转换,让RTL负责转换。
  3. 将数据字符串输入到PAnsiChar以传递给PrintRawData
  4. 将字符串参数作为const传递,除非您需要修改其内容。
  5. 当函数已经完成时,不需要显式的exit语句。

答案 2 :(得分:0)

<template name="locationView">
    <h1>{{name}}</h1>
</template>

用法:

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;