C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)
来源:互联网 发布:网络推广金融好做么 编辑:程序博客网 时间:2024/06/11 04:16
在批量打印商品标签时一般都要加上条码或图片,而这类应用大多是使用斑马打印机,所以我也遇到了怎么打印的问题。
一种办法是用标签设计软件做好模板,在标签设计软件中打印,这种办法不用写代码,但对我来说觉得不能接受,所以尝试代码解决问题。
网上搜索一番,找不到什么资料,基本都是说发送ZPL、EPL指令到打印机,而且还是COM/LPT口连接打印机。后来研究.net的打印类库,发现是用绘图方式打印至打印机的,也叫GDI打印,于是思路有了点突破,那我可以用报表工具画好标签,运行报表时,把结果输出位图,再发送至打印机。
后来又找到一种更好的办法,利用标签设计软件做好模板,打印至本地文件,把其中的ZPL、EPL指令拷贝出来,替换其中动态变化的内容为变量名,做成一个模板文本,在代码中动态替换变量,再把指令输出至打印机。
折腾了几天,终于把这两种思路都实现了,顺便解决了USB接口打印机的ZPL、EPL指令发送问题。
今天有点困,改天再详细讲解一下这两种思路的具体实现。
==============================================================================================================
如何获取标签设计软件输出至打印的ZPL指令?安装好打印机驱动,修改打印机端口,新建一个打印机端口,类型为本地端口,端口名称设置为C:\printer.log,再用标签设计软件打印一次,此文件中就有ZPL指令了。
==============================================================================================================
2012-06-02:发布代码ZebraPrintHelper.cs。
==============================================================================================================
2013-01-17:发布代码ZebraPrintHelper.cs,修正BUG,新增TCP打印支持Zebra无线打印QL320+系列打印机。已经生产环境实际应用,支持POS小票、吊牌、洗水唛、条码、文本混合标签打印。因涉及公司源码,只能截图VS解决方案给大家看。
==============================================================================================================
ZebraPrintHelper类代码:
using System;using System.Collections.Generic;using System.Drawing;using System.Drawing.Imaging;using System.IO;using System.IO.Ports;using System.Net.Sockets;using System.Runtime.InteropServices;using System.Text;namespace Umisky.BarcodePrint.Core { /// <summary> /// 斑马打印助手,支持LPT/COM/USB/TCP四种模式,适用于标签、票据、条码打印。 /// </summary> public static class ZebraPrintHelper { #region 定义私有字段 /// <summary> /// 线程锁,防止多线程调用。 /// </summary> private static object SyncRoot = new object(); /// <summary> /// ZPL压缩字典 /// </summary> private static List<KeyValue> compressDictionary = new List<KeyValue>(); #endregion #region 定义属性 public static float TcpLabelMaxHeightCM { get; set; } public static int TcpPrinterDPI { get; set; } public static string TcpIpAddress { get; set; } public static int TcpPort { get; set; } public static int Copies { get; set; } public static int Port { get; set; } public static string PrinterName { get; set; } public static bool IsWriteLog { get; set; } public static DeviceType PrinterType { get; set; } public static ProgrammingLanguage PrinterProgrammingLanguage { get; set; } /// <summary> /// 日志保存目录,WEB应用注意不能放在BIN目录下。 /// </summary> public static string LogsDirectory { get; set; } public static byte[] GraphBuffer { get; set; } private static int GraphWidth { get; set; } private static int GraphHeight { get; set; } private static int RowSize { get { return (((GraphWidth) + 31) >> 5) << 2; } } private static int RowRealBytesCount { get { if ((GraphWidth % 8) > 0) { return GraphWidth / 8 + 1; } else { return GraphWidth / 8; } } } #endregion #region 静态构造方法 static ZebraPrintHelper() { initCompressCode(); Port = 1; GraphBuffer = new byte[0]; IsWriteLog = false; LogsDirectory = "logs"; PrinterProgrammingLanguage = ProgrammingLanguage.ZPL; } private static void initCompressCode() { //G H I J K L M N O P Q R S T U V W X Y 对应1,2,3,4……18,19。 //g h i j k l m n o p q r s t u v w x y z 对应20,40,60,80……340,360,380,400。 for (int i = 0; i < 19; i++) { compressDictionary.Add(new KeyValue() { Key = Convert.ToChar(71 + i), Value = i + 1 }); } for (int i = 0; i < 20; i++) { compressDictionary.Add(new KeyValue() { Key = Convert.ToChar(103 + i), Value = (i + 1) * 20 }); } } #endregion #region 日志记录方法 private static void WriteLog(string text, LogType logType) { string endTag = string.Format("\r\n{0}\r\n", new string('=', 80)); string path = string.Format("{0}\\{1}-{2}.log", LogsDirectory, DateTime.Now.ToString("yyyy-MM-dd"), logType); if (!Directory.Exists(LogsDirectory)) { Directory.CreateDirectory(LogsDirectory); } if (logType == LogType.Error) { File.AppendAllText(path, string.Format("{0}{1}", text, endTag), Encoding.UTF8); } if (logType == LogType.Print) { File.AppendAllText(path, string.Format("{0}{1}", text, endTag), Encoding.UTF8); } } private static void WriteLog(byte[] bytes, LogType logType) { string endTag = string.Format("\r\n{0}\r\n", new string('=', 80)); string path = string.Format("{0}\\{1}-{2}.log", LogsDirectory, DateTime.Now.ToString("yyyy-MM-dd"), logType); if (!Directory.Exists(LogsDirectory)) { Directory.CreateDirectory(LogsDirectory); } if (logType == LogType.Error) { File.AppendAllText(path, string.Format("{0}{1}", Encoding.UTF8.GetString(bytes), endTag), Encoding.UTF8); } if (logType == LogType.Print) { File.AppendAllText(path, string.Format("{0}{1}", Encoding.UTF8.GetString(bytes), endTag), Encoding.UTF8); } } #endregion #region 封装方法,方便调用。 public static bool PrintWithCOM(string cmd, int port, bool isWriteLog) { PrinterType = DeviceType.COM; Port = port; IsWriteLog = isWriteLog; return PrintCommand(cmd); } public static bool PrintWithCOM(byte[] bytes, int port, bool isWriteLog) { PrinterType = DeviceType.COM; Port = port; IsWriteLog = isWriteLog; return PrintGraphics(bytes); } public static bool PrintWithLPT(string cmd, int port, bool isWriteLog) { PrinterType = DeviceType.LPT; Port = port; IsWriteLog = isWriteLog; return PrintCommand(cmd); } public static bool PrintWithLPT(byte[] bytes, int port, bool isWriteLog) { PrinterType = DeviceType.LPT; Port = port; IsWriteLog = isWriteLog; return PrintGraphics(bytes); } public static bool PrintWithTCP(string cmd, bool isWriteLog) { PrinterType = DeviceType.TCP; IsWriteLog = isWriteLog; return PrintCommand(cmd); } public static bool PrintWithTCP(byte[] bytes, bool isWriteLog) { PrinterType = DeviceType.TCP; IsWriteLog = isWriteLog; return PrintGraphics(bytes); } public static bool PrintWithDRV(string cmd, string printerName, bool isWriteLog) { PrinterType = DeviceType.DRV; PrinterName = printerName; IsWriteLog = isWriteLog; return PrintCommand(cmd); } public static bool PrintWithDRV(byte[] bytes, string printerName, bool isWriteLog) { PrinterType = DeviceType.DRV; PrinterName = printerName; IsWriteLog = isWriteLog; return PrintGraphics(bytes); } #endregion #region 打印ZPL、EPL、CPCL、TCP指令 public static bool PrintCommand(string cmd) { lock (SyncRoot) { bool result = false; try { switch (PrinterType) { case DeviceType.COM: result = comPrint(Encoding.Default.GetBytes(cmd)); break; case DeviceType.LPT: result = lptPrint(Encoding.Default.GetBytes(cmd)); break; case DeviceType.DRV: result = drvPrint(Encoding.Default.GetBytes(cmd)); break; case DeviceType.TCP: result = tcpPrint(Encoding.Default.GetBytes(cmd)); break; } if (!string.IsNullOrEmpty(cmd) && IsWriteLog) { WriteLog(cmd, LogType.Print); } } catch (Exception ex) { //记录日志 if (IsWriteLog) { WriteLog(string.Format("{0} => {1}\r\n{2}", DateTime.Now, ex.Message, ex), LogType.Error); } throw new Exception(ex.Message, ex); } finally { GraphBuffer = new byte[0]; } return result; } } #endregion #region 打印图像 public static bool PrintGraphics(byte[] graph) { lock (SyncRoot) { bool result = false; try { GraphBuffer = graph; byte[] cmdBytes = new byte[0]; switch (PrinterProgrammingLanguage) { case ProgrammingLanguage.ZPL: cmdBytes = getZPLBytes(); break; case ProgrammingLanguage.EPL: cmdBytes = getEPLBytes(); break; case ProgrammingLanguage.CPCL: cmdBytes = getCPCLBytes(); break; } switch (PrinterType) { case DeviceType.COM: result = comPrint(cmdBytes); break; case DeviceType.LPT: result = lptPrint(cmdBytes); break; case DeviceType.DRV: result = drvPrint(cmdBytes); break; case DeviceType.TCP: result = tcpPrint(cmdBytes); break; } if (cmdBytes.Length > 0 && IsWriteLog) { WriteLog(cmdBytes, LogType.Print); } } catch (Exception ex) { //记录日志 if (IsWriteLog) { WriteLog(string.Format("{0} => {1}\r\n{2}", DateTime.Now, ex.Message, ex), LogType.Error); } throw new Exception(ex.Message, ex); } finally { GraphBuffer = new byte[0]; } return result; } } #endregion #region 打印指令 private static bool drvPrint(byte[] cmdBytes) { bool result = false; try { if (!string.IsNullOrEmpty(PrinterName)) { result = WinDrvPort.SendBytesToPrinter(PrinterName, cmdBytes); } } catch (Exception ex) { throw new Exception(ex.Message, ex); } return result; } private static bool comPrint(byte[] cmdBytes) { bool result = false; SerialPort com = new SerialPort(string.Format("{0}{1}", PrinterType, Port), 9600, Parity.None, 8, StopBits.One); try { com.Open(); com.Write(cmdBytes, 0, cmdBytes.Length); result = true; } catch (Exception ex) { throw new Exception(ex.Message, ex); } finally { if (com.IsOpen) { com.Close(); } } return result; } private static bool lptPrint(byte[] cmdBytes) { return LptPort.Write(string.Format("{0}{1}", PrinterType, Port), cmdBytes); } private static bool tcpPrint(byte[] cmdBytes) { bool result = false; TcpClient tcp = null; try { tcp = TimeoutSocket.Connect(string.Empty, TcpIpAddress, TcpPort, 1000); tcp.SendTimeout = 1000; tcp.ReceiveTimeout = 1000; if (tcp.Connected) { tcp.Client.Send(cmdBytes); result = true; } } catch (Exception ex) { throw new Exception("打印失败,请检查打印机或网络设置。", ex); } finally { if (tcp != null) { if (tcp.Client != null) { tcp.Client.Close(); tcp.Client = null; } tcp.Close(); tcp = null; } } return result; } #endregion #region 生成ZPL图像打印指令 private static byte[] getZPLBytes() { byte[] bmpData = getBitmapData(); int bmpDataLength = bmpData.Length; for (int i = 0; i < bmpDataLength; i++) { bmpData[i] ^= 0xFF; } string textBitmap = string.Empty, copiesString = string.Empty; string textHex = BitConverter.ToString(bmpData).Replace("-", string.Empty); textBitmap = CompressLZ77(textHex); for (int i = 0; i < Copies; i++) { copiesString += "^XA^FO0,0^XGR:IMAGE.GRF,1,1^FS^XZ"; } string text = string.Format("~DGR:IMAGE.GRF,{0},{1},{2}{3}^IDR:IMAGE.GRF", GraphHeight * RowRealBytesCount, RowRealBytesCount, textBitmap, copiesString); return Encoding.UTF8.GetBytes(text); } #endregion #region 生成EPL图像打印指令 private static byte[] getEPLBytes() { byte[] buffer = getBitmapData(); string text = string.Format("N\r\nGW{0},{1},{2},{3},{4}\r\nP{5},1\r\n", 0, 0, RowRealBytesCount, GraphHeight, Encoding.GetEncoding("iso-8859-1").GetString(buffer), Copies); return Encoding.GetEncoding("iso-8859-1").GetBytes(text); } #endregion #region 生成CPCL图像打印指令 public static byte[] getCPCLBytes() { //GRAPHICS Commands //Bit-mapped graphics can be printed by using graphics commands. ASCII hex (hexadecimal) is //used for expanded graphics data (see example). Data size can be reduced to one-half by utilizing the //COMPRESSED-GRAPHICS commands with the equivalent binary character(s) of the hex data. When //using CG, a single 8 bit character is sent for every 8 bits of graphics data. When using EG two characters //(16 bits) are used to transmit 8 bits of graphics data, making EG only half as efficient. Since this data is //character data, however, it can be easier to handle and transmit than binary data. //Format: //{command} {width} {height} {x} {y} {data} //where: //{command}: Choose from the following: //EXPANDED-GRAPHICS (or EG): Prints expanded graphics horizontally. //VEXPANDED-GRAPHICS (or VEG): Prints expanded graphics vertically. //COMPRESSED-GRAPHICS (or CG): Prints compressed graphics horizontally. //VCOMPRESSED-GRAPHICS (or VCG): Prints compressed graphics vertically. //{width}: Byte-width of image. //{height} Dot-height of image. //{x}: Horizontal starting position. //{y}: Vertical starting position. //{data}: Graphics data. //Graphics command example //Input: //! 0 200 200 210 1 //EG 2 16 90 45 F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F //F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F //FORM //PRINT byte[] bmpData = getBitmapData(); int bmpDataLength = bmpData.Length; for (int i = 0; i < bmpDataLength; i++) { bmpData[i] ^= 0xFF; } string textHex = BitConverter.ToString(bmpData).Replace("-", string.Empty); string text = string.Format("! {0} {1} {2} {3} {4}\r\nEG {5} {6} {7} {8} {9}\r\nFORM\r\nPRINT\r\n", 0, //水平偏移量 TcpPrinterDPI, //横向DPI TcpPrinterDPI, //纵向DPI (int)(TcpLabelMaxHeightCM / 2.54f * TcpPrinterDPI), //标签最大像素高度=DPI*标签纸高度(英寸) Copies, //份数 RowRealBytesCount, //图像的字节宽度 GraphHeight, //图像的像素高度 0, //横向的开始位置 0, //纵向的开始位置 textHex ); return Encoding.UTF8.GetBytes(text); } #endregion #region 获取单色位图数据 /// <summary> /// /// </summary> /// <param name="pimage"></param> /// <returns></returns> public static Bitmap ConvertToGrayscale(Bitmap pimage) { Bitmap source = null; // If original bitmap is not already in 32 BPP, ARGB format, then convert if (pimage.PixelFormat != PixelFormat.Format32bppArgb) { source = new Bitmap(pimage.Width, pimage.Height, PixelFormat.Format32bppArgb); source.SetResolution(pimage.HorizontalResolution, pimage.VerticalResolution); using (Graphics g = Graphics.FromImage(source)) { g.DrawImageUnscaled(pimage, 0, 0); } } else { source = pimage; } // Lock source bitmap in memory BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); // Copy image data to binary array int imageSize = sourceData.Stride * sourceData.Height; byte[] sourceBuffer = new byte[imageSize]; Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize); // Unlock source bitmap source.UnlockBits(sourceData); // Create destination bitmap Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed); // Lock destination bitmap in memory BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); // Create destination buffer imageSize = destinationData.Stride * destinationData.Height; byte[] destinationBuffer = new byte[imageSize]; int sourceIndex = 0; int destinationIndex = 0; int pixelTotal = 0; byte destinationValue = 0; int pixelValue = 128; int height = source.Height; int width = source.Width; int threshold = 500; // Iterate lines for (int y = 0; y < height; y++) { sourceIndex = y * sourceData.Stride; destinationIndex = y * destinationData.Stride; destinationValue = 0; pixelValue = 128; // Iterate pixels for (int x = 0; x < width; x++) { // Compute pixel brightness (i.e. total of Red, Green, and Blue values) pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3]; if (pixelTotal > threshold) { destinationValue += (byte)pixelValue; } if (pixelValue == 1) { destinationBuffer[destinationIndex] = destinationValue; destinationIndex++; destinationValue = 0; pixelValue = 128; } else { pixelValue >>= 1; } sourceIndex += 4; } if (pixelValue != 128) { destinationBuffer[destinationIndex] = destinationValue; } } // Copy binary image data to destination bitmap Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize); // Unlock destination bitmap destination.UnlockBits(destinationData); // Dispose of source if not originally supplied bitmap if (source != pimage) { source.Dispose(); } // Return return destination; } /// <summary> /// 获取单色位图数据(1bpp),不含文件头、信息头、调色板三类数据。 /// </summary> /// <returns></returns> private static byte[] getBitmapData() { MemoryStream srcStream = new MemoryStream(); MemoryStream dstStream = new MemoryStream(); Bitmap srcBmp = null; Bitmap dstBmp = null; byte[] srcBuffer = null; byte[] dstBuffer = null; byte[] result = null; try { srcStream = new MemoryStream(GraphBuffer); srcBmp = Bitmap.FromStream(srcStream) as Bitmap; srcBuffer = srcStream.ToArray(); GraphWidth = srcBmp.Width; GraphHeight = srcBmp.Height; //dstBmp = srcBmp.Clone(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), PixelFormat.Format1bppIndexed); dstBmp = ConvertToGrayscale(srcBmp); dstBmp.Save(dstStream, ImageFormat.Bmp); dstBuffer = dstStream.ToArray(); int bfOffBits = BitConverter.ToInt32(dstBuffer, 10); result = new byte[GraphHeight * RowRealBytesCount]; //读取时需要反向读取每行字节实现上下翻转的效果,打印机打印顺序需要这样读取。 for (int i = 0; i < GraphHeight; i++) { Array.Copy(dstBuffer, bfOffBits + (GraphHeight - 1 - i) * RowSize, result, i * RowRealBytesCount, RowRealBytesCount); } } catch (Exception ex) { throw new Exception(ex.Message, ex); } finally { if (srcStream != null) { srcStream.Dispose(); srcStream = null; } if (dstStream != null) { dstStream.Dispose(); dstStream = null; } if (srcBmp != null) { srcBmp.Dispose(); srcBmp = null; } if (dstBmp != null) { dstBmp.Dispose(); dstBmp = null; } } return result; } #endregion #region LZ77图像字节流压缩方法 public static string CompressLZ77(string text) { //将转成16进制的文本进行压缩 string result = string.Empty; char[] arrChar = text.ToCharArray(); int count = 1; for (int i = 1; i < text.Length; i++) { if (arrChar[i - 1] == arrChar[i]) { count++; } else { result += convertNumber(count) + arrChar[i - 1]; count = 1; } if (i == text.Length - 1) { result += convertNumber(count) + arrChar[i]; } } return result; } public static string DecompressLZ77(string text) { string result = string.Empty; char[] arrChar = text.ToCharArray(); int count = 0; for (int i = 0; i < arrChar.Length; i++) { if (isHexChar(arrChar[i])) { //十六进制值 result += new string(arrChar[i], count == 0 ? 1 : count); count = 0; } else { //压缩码 int value = GetCompressValue(arrChar[i]); count += value; } } return result; } private static int GetCompressValue(char c) { int result = 0; for (int i = 0; i < compressDictionary.Count; i++) { if (c == compressDictionary[i].Key) { result = compressDictionary[i].Value; } } return result; } private static bool isHexChar(char c) { return c > 47 && c < 58 || c > 64 && c < 71 || c > 96 && c < 103; } private static string convertNumber(int count) { //将连续的数字转换成LZ77压缩代码,如000可用I0表示。 string result = string.Empty; if (count > 1) { while (count > 0) { for (int i = compressDictionary.Count - 1; i >= 0; i--) { if (count >= compressDictionary[i].Value) { result += compressDictionary[i].Key; count -= compressDictionary[i].Value; break; } } } } return result; } #endregion }}
调用例子代码:
private void BackgroundWorkerPrint_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; int i = 0, nextRemainder = 0, count = this._listBarcodeData.Count; bool flag = true; float pageWidth, pageHeight; int dpiX, dpiY, perPaperFactor; string reportPath = string.Format(@"{0}/Reports/{1}", Application.StartupPath, this._modelType); PrintLog printLog = new PrintLog() { Operater = LoginName }; PrinterSettings printerSettings = new PrinterSettings() { PrinterName = PrintParam, Copies = 1 }; using (StreamReader tr = new StreamReader(this.ModelFilePath)) { XElement xe = XDocument.Load(tr).Root.Elements() .Elements(XName.Get("ModelType")).First(x => x.Value == this._modelType).Parent; pageWidth = float.Parse(xe.Elements(XName.Get("PageWidth")).First().Value); pageHeight = float.Parse(xe.Elements(XName.Get("PageHeight")).First().Value); dpiX = int.Parse(xe.Elements(XName.Get("DotPerInchX")).First().Value); dpiY = int.Parse(xe.Elements(XName.Get("DotPerInchY")).First().Value); perPaperFactor = int.Parse(xe.Elements(XName.Get("PerPaperFactor")).First().Value); this._no = int.Parse(xe.Elements(XName.Get("NO")).First().Value); } using (LocalReportHelper printHelper = new LocalReportHelper(reportPath)) { printHelper.PrintTypeNO = this._no; printHelper.PrintLogInformation = printLog; printHelper.ExportImageDeviceInfo.DpiX = dpiX; printHelper.ExportImageDeviceInfo.DpiY = dpiY; printHelper.ExportImageDeviceInfo.PageWidth = pageWidth; printHelper.ExportImageDeviceInfo.PageHeight = pageHeight; foreach (BarcodeData bdCurrent in this._listBarcodeData) { if (worker.CancellationPending == true) { e.Cancel = true; break; } else { try { DataSet dsCurrent = this.GetDataForPrinterByBarcode(bdCurrent.Barcode, bdCurrent.IncreaseType); DataSet dsNext = null, dsPrevious = dsCurrent.Copy(); int amount = this._printType == 0 ? 1 : bdCurrent.Amount - nextRemainder; int copies = amount / perPaperFactor; int remainder = nextRemainder = amount % perPaperFactor; Action<DataSet, int, string, int> actPrint = (ds, duplicates, barcodes, amountForLog) => { printHelper.PrintLogInformation.Barcode = barcodes; printHelper.PrintLogInformation.Amount = amountForLog; if (this.PrintType == 0 && DeviceType == DeviceType.DRV) { printerSettings.Copies = (short)duplicates; printHelper.WindowsDriverPrint(printerSettings, dpiX, ds); } else { printHelper.OriginalPrint(DeviceType, ds, duplicates, PrintParam); } }; if (copies > 0) { int amountForCopy = copies; if (perPaperFactor > 1) { DataSet dsCurrentCopy = dsCurrent.CopyForBarcode(); dsCurrent.Merge(dsCurrentCopy); amountForCopy = copies * perPaperFactor; } actPrint.Invoke(dsCurrent, copies, bdCurrent.Barcode, amountForCopy); } if (remainder > 0) { int nextIndex = i + 1; string barcodes = bdCurrent.Barcode; if (nextIndex < count) { BarcodeData bdNext = this._listBarcodeData[nextIndex]; dsNext = this.GetDataForPrinterByBarcode(bdNext.Barcode, bdNext.IncreaseType); dsPrevious.Merge(dsNext); barcodes += "," + bdNext.Barcode; } actPrint.Invoke(dsPrevious, 1, barcodes, 1); } worker.ReportProgress(i++, string.Format("正在生成 {0} 并输送往打印机...", bdCurrent.Barcode)); if (this._printType == 0) { count = 1; flag = true; break; } } catch (Exception ex) { flag = false; e.Result = ex.Message; break; } } } if (!e.Cancel && flag) { e.Result = string.Format("打印操作成功完成,共处理条码 {0} 条", count); } } }
LocalReportHelper类代码:
using System;using System.Configuration;using System.Data;using System.Drawing;using System.Drawing.Imaging;using System.Drawing.Printing;using System.IO;using System.Text;using System.Windows.Forms;using Microsoft.Reporting.WinForms;using Umisky.BarcodePrint.Core;namespace Umisky.BarcodePrint.Codes { public class LocalReportHelper : IDisposable { #region Properties public String LocalReportPath { get; set; } public LocalReport LocalReportInstance { get; private set; } public GraphDeviceInfo ExportImageDeviceInfo { get; set; } public PrintLog PrintLogInformation { get; set; } public int PrintTypeNO { get; set; } #endregion private Stream _stream; private int _bmpDPI; private DataSet _ds; public LocalReportHelper(String reportPath) : this(reportPath, new GraphDeviceInfo() { ColorDepth = 1, DpiX = 203, DpiY = 203, PageWidth = 8f, PageHeight = 12.2f, MarginTop = 0.2f }) { } public LocalReportHelper(String reportPath, GraphDeviceInfo deviceInfo) { this._bmpDPI = 96; this.LocalReportPath = reportPath; this.ExportImageDeviceInfo = deviceInfo; this.LocalReportInstance = new LocalReport() { ReportPath = reportPath }; this.LocalReportInstance.SubreportProcessing += new SubreportProcessingEventHandler(LocalReportInstance_SubreportProcessing); } private void LocalReportInstance_SubreportProcessing(object sender, SubreportProcessingEventArgs e) { foreach (DataTable dt in this._ds.Tables) { e.DataSources.Add(new ReportDataSource(dt.TableName, dt)); } } public void Dispose() { this.ExportImageDeviceInfo = null; this.LocalReportInstance = null; this.LocalReportPath = null; this._ds = null; } public void AddReportParameter(string paramName, string value) { this.LocalReportInstance.SetParameters(new ReportParameter(paramName, value)); } #region Export hang title image by reporting services private void AddWashIcones() { this.LocalReportInstance.EnableExternalImages = true; this.LocalReportInstance.SetParameters(new ReportParameter("AppPath", Application.StartupPath)); } private void AddBarcodesAssembly() { this.LocalReportInstance.AddTrustedCodeModuleInCurrentAppDomain(ConfigurationManager.AppSettings["BarcodesAssembly"]); } private Stream CreateStreamCallBack(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek) { string tempFolderPath = string.Concat(Environment.GetEnvironmentVariable("TEMP"), "/"); this._stream = new FileStream(string.Concat(tempFolderPath, name, ".", fileNameExtension), FileMode.Create); return this._stream; } private void Export() { if (string.IsNullOrEmpty(this.LocalReportPath) || this.LocalReportInstance == null || this.ExportImageDeviceInfo == null) { throw new InvalidExpressionException("Invalid parameters"); } if (this.PrintTypeNO >= -1 || this.PrintTypeNO == -3) { this.AddBarcodesAssembly(); if (this.PrintTypeNO >= 0) { this.AddWashIcones(); } } if (this.PrintTypeNO >= 0) { this.LocalReportInstance.DataSources.Clear(); foreach (DataTable dt in this._ds.Tables) { this.LocalReportInstance.DataSources.Add(new ReportDataSource(dt.TableName, dt)); } } this.LocalReportInstance.Refresh(); if (this._stream != null) { this._stream.Close(); this._stream = null; } Warning[] warnings; this.LocalReportInstance.Render( "Image", this.ExportImageDeviceInfo.ToString(), PageCountMode.Actual, CreateStreamCallBack, out warnings); this._stream.Position = 0; } private void SaveLog() { using (Bitmap image = (Bitmap)Image.FromStream(this._stream)) { image.SetResolution(96, 96); using (MemoryStream ms = new MemoryStream()) { image.Save(ms, ImageFormat.Jpeg); this.PrintLogInformation.BarcodeImage = ms.ToArray(); } } LogHelper.AddLog(this.PrintLogInformation); if (this._stream != null) { this._stream.Close(); this._stream = null; } } #endregion #region Windows driver print private void PrintPage(object sender, PrintPageEventArgs ev) { Bitmap bmp = (Bitmap)Image.FromStream(this._stream); bmp.SetResolution(this._bmpDPI, this._bmpDPI); ev.Graphics.DrawImage(bmp, 0, 0); ev.HasMorePages = false; } /// <summary> /// Print by windows driver /// </summary> /// <param name="printerSettings">.net framework PrinterSettings class, including some printer information</param> /// <param name="bmpDPI">the bitmap image resoluation, dots per inch</param> public void WindowsDriverPrint(PrinterSettings printerSettings, int bmpDPI, DataSet ds) { this._ds = ds; this.Export(); if (this._stream == null) { return; } this._bmpDPI = bmpDPI; PrintDocument printDoc = new PrintDocument(); printDoc.DocumentName = "条码打印"; printDoc.PrinterSettings = printerSettings; printDoc.PrintController = new StandardPrintController(); if (!printDoc.PrinterSettings.IsValid) { if (this._stream != null) { this._stream.Close(); this._stream = null; } MessageBox.Show("Printer found errors, Please contact your administrators!", "Print Error"); return; } printDoc.PrintPage += new PrintPageEventHandler(PrintPage); printDoc.Print(); this.SaveLog(); } #endregion #region Original print /// <summary> /// Send the file to the printer or use the printer command /// </summary> /// <param name="deviceType">The port(LPT,COM,DRV) which the device connecting</param> /// <param name="copies">Total number for print</param> /// <param name="ds">The report datasource</param> /// <param name="printParam">Print parameters</param> /// <param name="printLanguage">The built-in printer programming language, you can choose EPL or ZPL</param> public void OriginalPrint(DeviceType deviceType, DataSet ds, int copies = 1, string printParam = null, ProgrammingLanguage printLanguage = ProgrammingLanguage.ZPL) { this._ds = ds; this.Export(); if (this._stream == null) { return; } int port = 1; int.TryParse(printParam, out port); int length = (int)this._stream.Length; byte[] bytes = new byte[length]; this._stream.Read(bytes, 0, length); ZebraPrintHelper.Copies = copies; ZebraPrintHelper.PrinterType = deviceType; ZebraPrintHelper.PrinterName = printParam; ZebraPrintHelper.Port = port; ZebraPrintHelper.PrinterProgrammingLanguage = printLanguage; ZebraPrintHelper.PrintGraphics(bytes); this.SaveLog(); } #endregion }}
- C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)
- C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)
- C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)
- C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)
- C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)
- C#调用斑马打印机打印条码标签(支持COM/LPT/USB/ZPL/EPL/Bitmap)
- C#调用斑马打印机打印条码标签(支持COM/LPT/USB/ZPL/EPL/Bitmap)
- C#调用斑马打印机打印条码标签(支持COM/LPT/USB/ZPL/EPL/Bitmap)
- 分享 斑马条码打印机EPL打印控件,js c# silverlight 可使用,
- delphi:斑马打印机ZPL指令打印中文及二维码
- C#通过LPT控制打印机——txt文档读取指令打印条码
- Delphi 调用打印指令ZPL--USB
- delphi:斑马打印机ZPL指令打印中文及二维码,补充说明
- C# LPT操作打印条码
- C#直接发送打印机命令到打印机及ZPL常用打印命令 - 条码打印机
- C#条码打印与ZPL
- java调用条码打印机指令进行打印
- Delphi调用打印机的ZPL指令来打印数据
- JUnit 3.8 演示递归删除文件目录的 测试类程序 .
- Linux文件权限
- 【编程语言】C++应用程序性能优化 笔记(一)
- JAVA文件合并操作效率研究
- 《算法导论》学习笔记--第十二章 二叉查找树
- C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)
- android自定义控件
- windows设置系统时间
- usermod 使用参考
- 【经验】申请联合培养博士出国
- some links
- javascript实现图片折角效果
- vs 常用快捷键
- C51中关键字对应的功能