其實兩年前我做過此類東西, 但是當時既沒做筆記 , 後來又找不著代碼了, 於是乎, 上個月又要做條碼列印時, 整個地又重來了一遍.
在網上查資料時, 發現好幾款控制項, 下載下來一看, 體積之大遠超我想像, 用法也一點都不簡單, 很不滿, 其實ZPL語言相當簡單, 與其向項目中引入這麼一個不知道怎麼寫的控制項, 還不如自己寫幾行ZPL代碼.
ZPL(Zebra Programming Language) 是斑馬公司(做條碼印表機的公司)自己設計的語言, 由於斑馬印表機是如此普遍, 以至於據我所見所知, 條碼印表機全部都是斑馬的, 所以控制條碼印表機幾乎就變成了對ZPL的使用.
總的邏輯分為以下兩步:
(1)編寫ZPL指令
(2)把ZPL作為C#的字串, 由C#把它送至串連印表機的連接埠.
其中, 用C#把字串送並口的寫法是固定的, 這部分的代碼如下:
public class Printer{ [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] private struct OVERLAPPED { int Internal; int InternalHigh; int Offset; int OffSetHigh; int hEvent; } [System.Runtime.InteropServices.DllImport("kernel32.dll")] private static extern int CreateFile( string lpFileName, uint dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile ); [System.Runtime.InteropServices.DllImport("kernel32.dll")] private static extern bool WriteFile( int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, out OVERLAPPED lpOverlapped ); [System.Runtime.InteropServices.DllImport("kernel32.dll")] private static extern bool CloseHandle( int hObject ); private int iHandle; public bool Open() { iHandle = CreateFile("LPT1:", (uint)FileAccess.ReadWrite, 0, 0, (int)FileMode.Open, 0, 0); if (iHandle != -1) { return true; } else { return false; } } public bool Write(string Mystring) { if (iHandle != -1) { int i; OVERLAPPED x; byte[] mybyte = System.Text.Encoding.Default.GetBytes(Mystring); return WriteFile(iHandle, mybyte, mybyte.Length, out i, out x); } else { throw new Exception("連接埠未開啟!"); } } public bool Close() { return CloseHandle(iHandle); }}
這個類封裝了對並口的操作, 它的使用方法為:
var printer = new Printer();if (!printer.Open()){ GB.IO.SetError("未能串連印表機,請確認印表機是否安裝正確並接通電源。"); return;}printer.Write(cmd);if (!printer.Close()){ GB.IO.SetError("未能關閉與印表機之間的串連,這可能意味著嚴重的錯誤,請重啟電腦及印表機。"); return;}
其中, cmd即是構造好的ZPL指令.
現在來看一段示意ZPL指令.
^XA
^MD30
^LH60,10
^FO20,10
^ACN,18,10
^BY1.4,3,50
^BC,,Y,N
^FD01008D004Q-0^FS
^XZ
這是一段能夠實際執行的指令串, 下面逐行解釋.
第一句^XA和最後一句^XZ分別代表一個指令塊的開始和結束, 是固定的東西.
^MD是設定色帶顏色的深度, 取值範圍從-30到30, 上面的示意指令將顏色調到了最深.
^LH是設定條碼紙的邊距的, 這個東西在實際操作上來回試幾次即可.
^FO是設定條碼左上方的位置的, 這個對程式員應該很容易理解. 0,0 代表完全不留邊距.
^ACN是設定字型的. 因為在條碼下方會顯示該條碼的內容, 所以這裡要設一下字型. 這個字型跟條碼無關.
^BY是設定條碼樣式的, 這是最重要的一個東西, 1.4是條碼的縮放層級, 這個數值下打出的條碼很小, 3是條碼中粗細柱的比例, 50是條碼高度.
^BC是列印code128的指令, 具體參數詳見ZPL的說明書.
^FD設定要列印的內容, ^FS表示換行.
所以上述語句最終的效果就是列印出一個值為01008D004Q-0的條碼, 高度為50.
以上可以看出, ZPL的指令方式很簡單, 實際上, 如果列印要求不複雜的話, 基本上也就用得上上述的幾個指令了,
其它的指令雖然很多, 但是基本上可以無視.
其實即使要打圖形之類的東西, 也並不複雜, 例如GB可以列印出來一個邊框, GC列印一個圓圈等. 其它的自訂圖案需要先把圖案上傳至印表機,
指令部分只要選擇已上傳的圖案, 選擇方式跟上面的字型選擇類似, 也很簡單.
在實踐中, 常常會需要一次橫打兩張, 其實可以把一排的兩張想像成一張, 只要把FO的橫座標設定得大一些就行了.
具體的指令詳細解釋, 及要實現其它功能, 可下載 ZPL II Programming Guide, 這本書寫得非常詳細. (如連結不能下載, google書名即可)