2011-05-09 484 views
2

好吧,這裏是我如何做到這一點:將命令直接發送到打印機的正確方法!

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 
    ... 

然而,有些東西是錯誤的,因爲某些命令(轉義序列)唐沒有按預期工作!

+1

過得好代碼到打印機嗎?直接LPT1:或其他方法?您是否啓用了打印機調試模式來查看您要發送的十六進制? – mj2008 2011-05-09 12:30:56

+0

你用什麼來代替'ESC'?對於大多數較舊的Epson打印機,它是ASCII字符#27。 – 2011-05-09 12:31:03

+0

是的,我發送#27而不是ESC。我使用win api WritePrinter函數發送命令! – Peacelyk 2011-05-09 13:05:55

回答

6

您正在使用錯誤的功能。使用Escape,傳遞PASSTHROUGH標誌作爲第二個參數。這將原始的未處理轉義碼直接發送到打印機。

Joe Hecht(Borland的前身)已經多次發佈了一個單元,這使得這更容易。我在這裏找到了unit PrtRaw

+0

感謝您的回覆。我更新了我的帖子,添加了一些代碼。但是,我不明白傳遞PASSTHROUGH標誌作爲第二個參數。第二個參數是什麼函數?你能解釋一下嗎? – Peacelyk 2011-05-09 14:56:34

+0

Peacelyk,Ken指的是['Escape'](http:// msdn。microsoft.com/en-us/library/dd162701.aspx)Windows API函數。 – 2011-05-09 15:43:47

+0

@Peacelyk:對不起。我忘了在我的原始答案中提供MSDN上的Escape鏈接。我現在更新了它。 – 2011-05-09 17:15:09

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. AnsiString更換Char陣列。
  2. 而不是使用循環一次一個字符地生成數據數組,使用單個賦值語句執行Unicode到Ansi的轉換,並讓RTL處理轉換。
  3. 鍵入數據字符串到PAnsiChar傳遞到PrintRawData
  4. 將字符串參數傳遞爲const,除非您需要修改其內容。
  5. 當函數已經完成時,不需要明確的exit語句。
+0

迂腐點:我喜歡評論行數據:=文字說「Unicode到ansi轉換髮生在這裏」,因爲它是一個潛在的有損轉換。 – 2011-05-09 23:12:50

0
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') 
+2

雖然這段代碼可能會解決這個問題,但幾句解釋對當前和未來的讀者會有很大的幫助。 – Thom 2015-05-11 11:28:27