寫在前面

今天的主題是用Zebra斑馬打印機打印卡片標簽。

Zebra介紹

既然是賀卡,應該是非常漂亮的,但是這個Zebra打印機好像只能打印黑白的,所以就簡單制作了一下。

工業(yè)上在批量打印商品標簽時,一般都要加上條碼或圖片,一般使用Zebra斑馬打印機比較多。而C#調(diào)用斑馬打印機的方式也有很多種,包括串口COM、以太網(wǎng)TCP、并口LPT以及USB等,對于設計標簽的方式也有很多種方式,比如Zebra提供了一個設計軟件Zebra Designer,還可以使用第三方軟件如Bartender,當然我們還可以自己通過GDI+技術進行繪制。

本例采用的方式是利用GDI+進行繪制,然后將圖像轉(zhuǎn)換成字節(jié),通過DG和XG指令發(fā)送給打印機,通信使用的是打印機自帶的USB接口。

圖像繪制

首先通過GDI+繪制一張圖像,圖像的大小要根據(jù)實際標簽大小進行調(diào)試,繪制內(nèi)容可以是圖像、字符串等,或者是條形碼、二維碼都可以,其實條形碼及二維碼也是屬于圖像。

????????private?void?btn_Paint_Click(object?sender,?EventArgs?e) ????????{ ????????????//開始繪制圖片 ????????????int?imageWidth?=?900; ????????????int?imageHeight?=?600; ????????????bitmap?=?new?Bitmap(imageWidth,?imageHeight); ????????????//創(chuàng)建Graphics ????????????Graphics?graphics?=?Gra(bitmap); ????????????//呈現(xiàn)質(zhì)量 ????????????gra?=?Smoo; ????????????//背景色 ????????????gra); ????????????//字體 ????????????Font?myFont?=?new?Font("楷體",?32,?Fon); ????????????//文字顏色 ????????????Brush?brush?=?new?SolidBru); ????????????//調(diào)整間距 ????????????int?start?=?145;??????? ????????????int?gap?=?80; ????????????gra("祝全天下的母親——母親節(jié)快樂",?myFont,?brush,?50,?50); ????????????gra("《游子吟》【唐】孟郊",?myFont,?brush,?50,?start); ????????????gra("慈母手中線,游子身上衣",?myFont,?brush,?50,?start?+?gap); ????????????gra("臨行密密縫,意恐遲遲歸",?myFont,?brush,?50,?start?+?gap?*?2); ????????????gra("誰言寸草心,報得三春暉",?myFont,?brush,?50,?start?+?gap?*?3); ????????????gra("署名:"?+?(),?myFont,?brush,?50,?start?+?gap?*?4?+?20); ????????????//生成二維碼 ????????????Image?codeImage?=?BarCodeHel(";,?220,?220); ????????????Bitmap?pbitmap?=?new?Bitmap(codeImage); ????????????); ????????????gra(pbitmap,?630,?338,?220,?220); ????????????//顯示圖形 ?????????????=?bitmap; ????????}

編寫好代碼之后,將圖像用一個PictureBox控件顯示出來,結果如下:

圖像處理

生成圖像之后,接著將圖像轉(zhuǎn)換成字節(jié)數(shù)組或者字符串,便于后續(xù)直接發(fā)送給打印機,這里的代碼是在網(wǎng)上找的,

????public?static?string?BitmapToHex(Image?sourceBmp,?out?int?totalBytes,?out?int?rowBytes) ????????{ ????????????//?轉(zhuǎn)成單色圖 ????????????Bitmap?grayBmp?=?ConvertToGrayscale(sourceBmp?as?Bitmap); ????????????//?鎖定位圖數(shù)據(jù)???? ????????????Rectangle?rect?=?new?Rectangle(0,?0,?grayBmp.Width,?grayBmp.Height); ????????????BitmapData?bmpData?=?grayBmp.LockBits(rect,?ImageLockMode.ReadWrite,?grayBmp.PixelFormat); ????????????//?獲取位圖數(shù)據(jù)第一行的起始地址????? ????????????IntPtr?ptr?=?bm; ????????????//?定義數(shù)組以存放位圖的字節(jié)流數(shù)據(jù)?????? ????????????//?處理像素寬對應的字節(jié)數(shù),如不為8的倍數(shù),則對最后一個字節(jié)補0???? ????????????int?width?=?(in?/?8.0); ????????????//?獲取位圖實際的字節(jié)寬,這個值因為要考慮4的倍數(shù)關系,可能大于width?? ????????????int?stride?=?Ma); ????????????//?計算位圖數(shù)據(jù)實際所占的字節(jié)數(shù),并定義數(shù)組?????? ????????????int?bitmapDataLength?=?stride?*?grayBmp.Height; ????????????byte[]?ImgData?=?new?byte[bitmapDataLength]; ????????????//?從位圖文件復制圖像數(shù)據(jù)到數(shù)組,從實際圖像數(shù)據(jù)的第一行開始;因ptr指針而無需再考慮行倒序存儲的處理?????????? ????????????Sy(ptr,?ImgData,?0,?bitmapDataLength); ????????????//?計算異或操作數(shù),以處理包含圖像數(shù)據(jù)但又有補0操作的那個字節(jié)????????? ????????????byte?mask?=?0xFF; ????????????//?計算這個字節(jié)補0的個數(shù)??????? ????????????//int?offset?=?8?*?width?-?grayBmp.Width; ????????????int?offset?=?8?-??%?8); ????????????//offset?%=?8; ????????????offset?=?offset?%?8; ????????????//?按補0個數(shù)對0xFF做相應位數(shù)的左移位操作??????????? ????????????mask?<<=?(byte)offset; ????????????//?圖像反色處理???????? ????????????for?(int?j?=?0;?j?<?grayBmp.Height;?j++) ????????????{ ????????????????for?(int?i?=?0;?i?<?stride;?i++) ????????????????{ ????????????????????if?(i?<?width?-?1)?//無補0的圖像數(shù)據(jù) ????????????????????{ ????????????????????????ImgData[j?*?stride?+?i]?^=?0xFF; ????????????????????} ????????????????????else?if?(i?==?width?-?1)?//有像素的最后一個字節(jié),可能有補0??? ????????????????????{ ????????????????????????ImgData[j?*?stride?+?i]?^=?mask; ????????????????????} ????????????????????else??//為滿足行字節(jié)寬為4的倍數(shù)而最后補的字節(jié)???????? ????????????????????{ ????????????????????????ImgData[j?*?stride?+?i]?^=?0x00; ????????????????????} ????????????????} ????????????} ????????????//?將位圖數(shù)據(jù)轉(zhuǎn)換為16進制的ASCII字符?????????? ????????????string?zplString?=?Bi(ImgData); ????????????zplString?=?CompressLZ77("-",?)); ????????????totalBytes?=?bitmapDataLength; ????????????rowBytes?=?stride; ????????????return?zplString; ????????}

調(diào)用打印機

調(diào)用打印機使用的是win,這個庫里提供了很多操作打印機的方法。

????????????[DllImport("win;,?EntryPoint?=?"OpenPrinterA",?SetLastError?=?true,?CharSet?=?C,?ExactSpelling?=?true,?CallingConvention?=?CallingConven)] ????????????public?static?extern?bool?OpenPrinter([MarshalA)]?string?szPrinter,?out?IntPtr?hPrinter,?IntPtr?pd); ????????????[DllImport("win;,?EntryPoint?=?"ClosePrinter",?SetLastError?=?true,?ExactSpelling?=?true,?CallingConvention?=?CallingConven)] ????????????public?static?extern?bool?ClosePrinter(IntPtr?hPrinter); ????????????[DllImport("win;,?EntryPoint?=?"StartDocPrinterA",?SetLastError?=?true,?CharSet?=?C,?ExactSpelling?=?true,?CallingConvention?=?CallingConven)] ????????????public?static?extern?bool?StartDocPrinter(IntPtr?hPrinter,?Int32?level,?[In,?MarshalAuct)]?DOCINFOA?di); ????????????[DllImport("win;,?EntryPoint?=?"EndDocPrinter",?SetLastError?=?true,?ExactSpelling?=?true,?CallingConvention?=?CallingConven)] ????????????public?static?extern?bool?EndDocPrinter(IntPtr?hPrinter); ????????????[DllImport("win;,?EntryPoint?=?"StartPagePrinter",?SetLastError?=?true,?ExactSpelling?=?true,?CallingConvention?=?CallingConven)] ????????????public?static?extern?bool?StartPagePrinter(IntPtr?hPrinter); ????????????[DllImport("win;,?EntryPoint?=?"EndPagePrinter",?SetLastError?=?true,?ExactSpelling?=?true,?CallingConvention?=?CallingConven)] ????????????public?static?extern?bool?EndPagePrinter(IntPtr?hPrinter); ????????????[DllImport("win;,?EntryPoint?=?"WritePrinter",?SetLastError?=?true,?ExactSpelling?=?true,?CallingConvention?=?CallingConven)] ????????????public?static?extern?bool?WritePrinter(IntPtr?hPrinter,?IntPtr?pBytes,?Int32?dwCount,?out?Int32?dwWritten);

基于這些方法,封裝一個將字符串發(fā)送給打印機的方法:

????????????public??bool?SendStringToPrinter(string?szPrinterName,?string?szString) ????????????{ ????????????????try ????????????????{ ????????????????????IntPtr?pBytes; ????????????????????Int32?dwCount; ????????????????????//?獲取字符串長度?? ????????????????????dwCount?=?; ????????????????????//?將字符串復制到非托管?COM?任務分配的內(nèi)存非托管內(nèi)存塊,并轉(zhuǎn)換為?ANSI?文本 ????????????????????pBytes?=?Mar(szString); ????????????????????//?將已轉(zhuǎn)換的?ANSI?字符串發(fā)送到打印機 ????????????????????bool?res?=?SendBytesToPrinter(szPrinterName,?pBytes,?dwCount); ????????????????????//?釋放先前分配的非托管內(nèi)存 ????????????????????Mar(pBytes); ????????????????????return?res; ????????????????} ????????????????catch?(Win32Exception?ex) ????????????????{ ????????????????????WriteLog); ????????????????????return?false; ????????????????} ????????????}

最后在打印按鈕下,組織相關命令,調(diào)用這個方法即可:

????????private?void?btn_Print_Click(object?sender,?EventArgs?e) ????????{ ????????????int?total?=?0; ????????????int?row?=?0; ????????????string?hex?=?ZebraUni(bitmap,?out?total,?out?row);???????????????????? ????????????string?modecmd?=?"~DGR:ZLOGO.GRF,"?+?()?+?","?+?row.ToString()?+?","?+?hex;//將圖片生成模板指令 ????????????ZebraGe("ZDesigner?ZT210",?modecmd); ????????????string?cmd?=?"^XA^FO0,0^XGR:ZLOGO.GRF,1,1^FS^XZ";//調(diào)用該模板指令 ????????????ZebraGe("ZDesigner?ZT210",?cmd);//發(fā)送調(diào)用模板指令 ????????}

最終結果

下面這個就是最終打印的結果:

小彩蛋:你們掃掃二維碼看看是什么呢?

1.《關于禮品條怎么打印機,你需要知道這些用Zebra打印機制作一個節(jié)日賀卡》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡信息知識,僅代表作者本人觀點,與本網(wǎng)站無關,侵刪請聯(lián)系頁腳下方聯(lián)系方式。

2.《關于禮品條怎么打印機,你需要知道這些用Zebra打印機制作一個節(jié)日賀卡》僅供讀者參考,本網(wǎng)站未對該內(nèi)容進行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。

3.文章轉(zhuǎn)載時請保留本站內(nèi)容來源地址,http://f99ss.com/why/3116007.html