您的位置:首页 > 理论基础 > 计算机网络

C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)

2016-09-09 16:59 627 查看
在批量打印商品标签时一般都要加上条码或图片,而这类应用大多是使用斑马打印机,所以我也遇到了怎么打印的问题。

一种办法是用标签设计软件做好模板,在标签设计软件中打印,这种办法不用写代码,但对我来说觉得不能接受,所以尝试代码解决问题。

网上搜索一番,找不到什么资料,基本都是说发送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类代码:

[csharp] view
plain copy

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

}

}

调用例子代码:

[csharp] view
plain copy

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类代码:

[csharp] view
plain copy

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

}

}









内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐