1 private void btnPrinter_Click(object sender, EventArgs e)
2 {
3
4 #region ESC 热敏图像点阵像素点读取打印
5
6 //Bitmap bitmap = new Bitmap(@"D:\450X100.bmp");
7 //NetPOSPrinter netPOSPrinter = new NetPOSPrinter();
8 //netPOSPrinter.PrintPic(bitmap);
9
10 #endregion
11
12 #region EPL USB 打印
13 //Bitmap img = new Bitmap(@"D:\450X100.bmp");
14 //ZebraPrintHelper.PrinterType = DeviceType.DRV;
15 //ZebraPrintHelper.PrinterProgrammingLanguage = ProgrammingLanguage.EPL;
16 //ZebraPrintHelper.PrinterName = "ZDesigner GK888t (EPL)";
17 //byte[] imgByte = ImageToByte.ImgToByt(img);
18 //ZebraPrintHelper.PrintGraphics(imgByte);
19
20 #endregion
21
22 #region ZPL II 打印指令
23 //^XA^CFD
24 //^POI
25 //^LH330,10
26 //^FO50,50
27 //^FDSMARTDIGITAL^FS
28 //^FO50,75
29 //^FD021-51871630^FS
30 //^XZ
31
32 //StringBuilder sb = new StringBuilder();
33 //sb.Append("^XA^CFD");
34 //sb.Append("^POI");
35 //sb.Append("^LH330,10");
36 //sb.Append("^FO50,50");
37 //sb.Append("^FDSMARTDIGITAL^FS");
38 //sb.Append("^FO50,75");
39 //sb.Append("^FD021-51871630^FS");
40 //sb.Append("^XZ");
41
42 //byte[] cmd = Encoding.Default.GetBytes(sb.ToString());
43
44 #endregion
45
46 #region EPL USB 指令打印
47 ZebraPrintHelper.PrinterProgrammingLanguage = ProgrammingLanguage.EPL;
48 ZebraPrintHelper.PrinterName = "ZDesigner GK888t (EPL)";
49 ZebraPrintHelper.PrinterType = DeviceType.DRV;
50
51 string cmd = "N" + "\r\n" +
52 "Q400,025" + "\n\r" +
53 "A140,45,0,8,1,1,N,\"古典黄芥沫调味酱\"" + "\r\n" +
54 "A140,90,0,8,1,1,N,\"规格:\"" + "\r\n" +
55 "A240,95,0,4,1,1,N,\"" + "100ML/瓶" + "\"" + "\r\n" +
56 "A140,135,0,8,1,1,N,\"生产日期:\"" + "\r\n" +
57 "A300,140,0,4,1,1,N,\"" + "2015-10-02" + "\"" + "\r\n" +
58 "B140,180,0,1,3,2,100,B,\"" + "8957891234567895789588535" + "\"" + "\r\n" +
59 "P1" + "\r\n";
60
61 ZebraPrintHelper.PrintCommand(cmd.ToString());
62 #endregion
63 }
1 using Microsoft.Win32.SafeHandles;
2 using System;
3 using System.Collections.Generic;
4 using System.Drawing;
5 using System.Drawing.Imaging;
6 using System.IO;
7 using System.IO.Ports;
8 using System.Net;
9 using System.Net.Sockets;
10 using System.Runtime.InteropServices;
11 using System.Text;
12
13 namespace ZebraLibrary
14 {
15 /// <summary>
16 /// 斑马打印助手,支持LPT/COM/USB/TCP四种模式,适用于标签、票据、条码打印。
17 /// </summary>
18 public static class ZebraPrintHelper
19 {
20 #region 定义API方法
21
22 #region 写打印口(LPT)方法
23 private const short FILE_ATTRIBUTE_NORMAL = 0x80;
24 private const short INVALID_HANDLE_VALUE = -1;
25 private const uint GENERIC_READ = 0x80000000;
26 private const uint GENERIC_WRITE = 0x40000000;
27 private const uint CREATE_NEW = 1;
28 private const uint CREATE_ALWAYS = 2;
29 private const uint OPEN_EXISTING = 3;
30 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
31 private static extern SafeFileHandle CreateFile(string strFileName,
32 uint dwDesiredAccess,
33 uint dwShareMode,
34 IntPtr intptrSecurityAttributes,
35 uint dwCreationDisposition,
36 uint dwFlagsAndAttributes,
37 IntPtr intptrTemplateFile);
38 #endregion
39
40 [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
41 public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string printerName, out IntPtr intptrPrinter, IntPtr intptrPrintDocument);
42
43 [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
44 public static extern bool ClosePrinter(IntPtr intptrPrinter);
45
46 [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
47 public static extern bool StartDocPrinter(IntPtr intptrPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DocInfo docInfo);
48
49 [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
50 public static extern bool EndDocPrinter(IntPtr intptrPrinter);
51
52 [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
53 public static extern bool StartPagePrinter(IntPtr intptrPrinter);
54
55 [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
56 public static extern bool EndPagePrinter(IntPtr intptrPrinter);
57
58 [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
59 public static extern bool WritePrinter(IntPtr intptrPrinter, IntPtr intptrBytes, Int32 count, out Int32 written);
60 #endregion
61
62 #region 定义私有字段
63
64 /// <summary>
65 /// 线程锁,防止多线程调用。
66 /// </summary>
67 private static object SyncRoot = new object();
68
69 /// <summary>
70 /// 字节流传递时采用的字符编码
71 /// </summary>
72 private static readonly Encoding TransferFormat = Encoding.GetEncoding("iso-8859-1");
73
74 #endregion
75
76 #region 定义属性
77 public static int Port { get; set; }
78 public static string PrinterName { get; set; }
79 public static bool IsWriteLog { get; set; }
80 public static DeviceType PrinterType { get; set; }
81 public static ProgrammingLanguage PrinterProgrammingLanguage { get; set; }
82
83 public static float TcpLabelMaxHeightCM { get; set; }
84 public static int TcpPrinterDPI { get; set; }
85 public static string TcpIpAddress { get; set; }
86 public static int TcpPort { get; set; }
87 public static int Copies { get; set; }
88
89 /// <summary>
90 /// 日志保存目录,WEB应用注意不能放在BIN目录下。
91 /// </summary>
92 public static string LogsDirectory { get; set; }
93
94 private static byte[] GraphBuffer { get; set; }
95 private static int GraphWidth { get; set; }
96 private static int GraphHeight { get; set; }
97
98 private static int RowSize
99 {
100 get
101 {
102 return (((GraphWidth) + 31) >> 5) << 2;
103 }
104 }
105
106 private static int RowRealBytesCount
107 {
108 get
109 {
110 if ((GraphWidth % 8) > 0)
111 {
112 return GraphWidth / 8 + 1;
113 }
114 else
115 {
116 return GraphWidth / 8;
117 }
118 }
119 }
120 #endregion
121
122 #region 静态构造方法
123 static ZebraPrintHelper()
124 {
125 GraphBuffer = new byte[0];
126 IsWriteLog = false;
127 LogsDirectory = "logs";
128 }
129 #endregion
130
131 #region 定义发送原始数据到打印机的方法
132 private static bool SendBytesToPrinter(string printerName, IntPtr intptrBytes, Int32 count)
133 {
134 Int32 error = 0, written = 0;
135 IntPtr intptrPrinter = new IntPtr(0);
136 DocInfo docInfo = new DocInfo();
137 bool bSuccess = false;
138
139 docInfo.DocName = ".NET RAW Document";
140 docInfo.DataType = "RAW";
141
142 // Open the printer.
143 if (OpenPrinter(printerName.Normalize(), out intptrPrinter, IntPtr.Zero))
144 {
145 // Start a document.
146 if (StartDocPrinter(intptrPrinter, 1, docInfo))
147 {
148 // Start a page.
149 if (StartPagePrinter(intptrPrinter))
150 {
151 // Write your bytes.
152 bSuccess = WritePrinter(intptrPrinter, intptrBytes, count, out written);
153 EndPagePrinter(intptrPrinter);
154 }
155 EndDocPrinter(intptrPrinter);
156 }
157 ClosePrinter(intptrPrinter);
158 }
159 // If you did not succeed, GetLastError may give more information
160 // about why not.
161 if (bSuccess == false)
162 {
163 error = Marshal.GetLastWin32Error();
164 }
165 return bSuccess;
166 }
167
168 public static bool SendFileToPrinter(string printerName, string fileName)
169 {
170 // Open the file.
171 FileStream fs = new FileStream(fileName, FileMode.Open);
172 // Create a BinaryReader on the file.
173 BinaryReader br = new BinaryReader(fs);
174 // Dim an array of bytes big enough to hold the file's contents.
175 Byte[] bytes = new Byte[fs.Length];
176 bool bSuccess = false;
177 // Your unmanaged pointer.
178 IntPtr pUnmanagedBytes = new IntPtr(0);
179 int nLength;
180
181 nLength = Convert.ToInt32(fs.Length);
182 // Read the contents of the file into the array.
183 bytes = br.ReadBytes(nLength);
184 // Allocate some unmanaged memory for those bytes.
185 pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
186 // Copy the managed byte array into the unmanaged array.
187 Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
188 // Send the unmanaged bytes to the printer.
189 bSuccess = SendBytesToPrinter(printerName, pUnmanagedBytes, nLength);
190 // Free the unmanaged memory that you allocated earlier.
191 Marshal.FreeCoTaskMem(pUnmanagedBytes);
192 return bSuccess;
193 }
194
195 public static bool SendBytesToPrinter(string printerName, byte[] bytes)
196 {
197 bool bSuccess = false;
198 IntPtr pUnmanagedBytes = new IntPtr(0);
199 int nLength = bytes.Length;
200 // Allocate some unmanaged memory for those bytes.
201 pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
202 // Copy the managed byte array into the unmanaged array.
203 Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
204 // Send the unmanaged bytes to the printer.
205 bSuccess = SendBytesToPrinter(printerName, pUnmanagedBytes, nLength);
206 // Free the unmanaged memory that you allocated earlier.
207 Marshal.FreeCoTaskMem(pUnmanagedBytes);
208 return bSuccess;
209 }
210
211 public static bool SendStringToPrinter(string printerName, string text)
212 {
213 IntPtr pBytes;
214 Int32 dwCount;
215 // How many characters are in the string?
216 dwCount = (text.Length + 1) * Marshal.SystemMaxDBCSCharSize;
217 // Assume that the printer is expecting ANSI text, and then convert
218 // the string to ANSI text.
219 pBytes = Marshal.StringToCoTaskMemAnsi(text);
220 // Send the converted ANSI string to the printer.
221 SendBytesToPrinter(printerName, pBytes, dwCount);
222 Marshal.FreeCoTaskMem(pBytes);
223 return true;
224 }
225 #endregion
226
227 #region 日志记录方法
228 private static void WriteLog(string text, LogType logType)
229 {
230 string endTag = string.Format("\r\n{0}\r\n", new string('=', 80));
231 string path = string.Format("{0}\\{1}-{2}.log", LogsDirectory, DateTime.Now.ToString("yyyy-MM-dd"), logType);
232 if (!Directory.Exists(LogsDirectory))
233 {
234 Directory.CreateDirectory(LogsDirectory);
235 }
236 if (logType == LogType.Error)
237 {
238 File.AppendAllText(path, string.Format("{0}{1}", text, endTag), Encoding.Default);
239 }
240 if (logType == LogType.Print)
241 {
242 if (text.StartsWith("N\r\nGW"))
243 {
244 using (FileStream fs = new FileStream(path, FileMode.Append))
245 {
246 byte[] bytes = TransferFormat.GetBytes(text);
247 byte[] tag = TransferFormat.GetBytes(endTag);
248 fs.Write(bytes, 0, bytes.Length);
249 fs.Write(tag, 0, tag.Length);
250 fs.Close();
251 }
252 }
253 else
254 {
255 File.AppendAllText(path, string.Format("{0}{1}", text, endTag), Encoding.Default);
256 }
257 }
258 }
259
260 private static void WriteLog(byte[] bytes, LogType logType)
261 {
262 string endTag = string.Format("\r\n{0}\r\n", new string('=', 80));
263 string path = string.Format("{0}\\{1}-{2}.log", LogsDirectory, DateTime.Now.ToString("yyyy-MM-dd"), logType);
264 if (!Directory.Exists(LogsDirectory))
265 {
266 Directory.CreateDirectory(LogsDirectory);
267 }
268 if (logType == LogType.Error)
269 {
270 File.AppendAllText(path, string.Format("{0}{1}", Encoding.Default.GetString(bytes), endTag), Encoding.Default);
271 }
272 if (logType == LogType.Print)
273 {
274 string transferFormat = TransferFormat.GetString(bytes);
275 if (transferFormat.StartsWith("N\r\nGW"))
276 {
277 using (FileStream fs = new FileStream(path, FileMode.Append))
278 {
279 byte[] tag = TransferFormat.GetBytes(endTag);
280 fs.Write(bytes, 0, bytes.Length);
281 fs.Write(tag, 0, tag.Length);
282 fs.Close();
283 }
284 }
285 else
286 {
287 File.AppendAllText(path, string.Format("{0}{1}", Encoding.Default.GetString(bytes), endTag), Encoding.Default);
288 }
289 }
290 }
291 #endregion
292
293 #region 封装方法,方便调用。
294 public static bool PrintWithCOM(string cmd, int port, bool isWriteLog)
295 {
296 PrinterType = DeviceType.COM;
297 Port = port;
298 IsWriteLog = isWriteLog;
299 return PrintCommand(cmd);
300 }
301
302 public static bool PrintWithCOM(byte[] bytes, int port, bool isWriteLog, ProgrammingLanguage progLanguage)
303 {
304 PrinterType = DeviceType.COM;
305 Port = port;
306 IsWriteLog = isWriteLog;
307 PrinterProgrammingLanguage = progLanguage;
308 return PrintGraphics(bytes);
309 }
310
311 public static bool PrintWithLPT(string cmd, int port, bool isWriteLog)
312 {
313 PrinterType = DeviceType.LPT;
314 Port = port;
315 IsWriteLog = isWriteLog;
316 return PrintCommand(cmd);
317 }
318
319 public static bool PrintWithLPT(byte[] bytes, int port, bool isWriteLog, ProgrammingLanguage progLanguage)
320 {
321 PrinterType = DeviceType.LPT;
322 Port = port;
323 IsWriteLog = isWriteLog;
324 PrinterProgrammingLanguage = progLanguage;
325 return PrintGraphics(bytes);
326 }
327
328 public static bool PrintWithDRV(string cmd, string printerName, bool isWriteLog)
329 {
330 PrinterType = DeviceType.DRV;
331 PrinterName = printerName;
332 IsWriteLog = isWriteLog;
333 return PrintCommand(cmd);
334 }
335
336 public static bool PrintWithDRV(byte[] bytes, string printerName, bool isWriteLog, ProgrammingLanguage progLanguage)
337 {
338 PrinterType = DeviceType.DRV;
339 PrinterName = printerName;
340 IsWriteLog = isWriteLog;
341 PrinterProgrammingLanguage = progLanguage;
342 return PrintGraphics(bytes);
343 }
344 #endregion
345
346 #region 打印ZPL、EPL指令
347 public static bool PrintCommand(string cmd)
348 {
349 lock (SyncRoot)
350 {
351 bool result = false;
352 try
353 {
354 switch (PrinterType)
355 {
356 case DeviceType.COM:
357 result = comPrint(Encoding.Default.GetBytes(cmd));
358 break;
359 case DeviceType.LPT:
360 result = lptPrint(Encoding.Default.GetBytes(cmd));
361 break;
362 case DeviceType.DRV:
363 result = drvPrint(Encoding.Default.GetBytes(cmd));
364 break;
365 case DeviceType.TCP:
366 result = tcpPrint(Encoding.Default.GetBytes(cmd));
367 break;
368 }
369 if (!string.IsNullOrEmpty(cmd) && IsWriteLog)
370 {
371 WriteLog(cmd, LogType.Print);
372 }
373 }
374 catch (Exception ex)
375 {
376 //记录日志
377 if (IsWriteLog)
378 {
379 WriteLog(string.Format("{0} => {1}\r\n{2}", DateTime.Now, ex.Message, ex), LogType.Error);
380 }
381 }
382 finally
383 {
384 GraphBuffer = new byte[0];
385 }
386 return result;
387 }
388 }
389 #endregion
390
391 #region 打印图像字节流
392 public static bool PrintGraphics(byte[] graph)
393 {
394 lock (SyncRoot)
395 {
396 bool result = false;
397 try
398 {
399 GraphBuffer = graph;
400 byte[] cmdBytes = new byte[0];
401 if (PrinterProgrammingLanguage == ProgrammingLanguage.ZPL)
402 {
403 cmdBytes = getZPLBytes();
404 }
405 if (PrinterProgrammingLanguage == ProgrammingLanguage.EPL)
406 {
407 cmdBytes = getEPLBytes();
408 }
409 if (PrinterProgrammingLanguage == ProgrammingLanguage.CPCL)
410 {
411 cmdBytes = getCPCLBytes();
412 }
413 switch (PrinterType)
414 {
415 case DeviceType.COM:
416 result = comPrint(cmdBytes);
417 break;
418 case DeviceType.LPT:
419 result = lptPrint(cmdBytes);
420 break;
421 case DeviceType.DRV:
422 result = drvPrint(cmdBytes);
423 break;
424 case DeviceType.TCP:
425 result = tcpPrint(cmdBytes);
426 break;
427 }
428 if (cmdBytes.Length > 0 && IsWriteLog)
429 {
430 WriteLog(cmdBytes, LogType.Print);
431 }
432 }
433 catch (Exception ex)
434 {
435 //记录日志
436 if (IsWriteLog)
437 {
438 WriteLog(string.Format("{0} => {1}\r\n{2}", DateTime.Now, ex.Message, ex), LogType.Error);
439 }
440 }
441 finally
442 {
443 GraphBuffer = new byte[0];
444 }
445 return result;
446 }
447 }
448 #endregion
449
450 #region COM/LPT/DRV三种模式打印方法
451 private static bool drvPrint(byte[] cmdBytes)
452 {
453 bool result = false;
454 try
455 {
456 if (!string.IsNullOrEmpty(PrinterName))
457 {
458 result = SendBytesToPrinter(PrinterName, cmdBytes);
459 }
460 }
461 catch (Exception ex)
462 {
463 throw ex;
464 }
465 return result;
466 }
467
468 private static bool comPrint(byte[] cmdBytes)
469 {
470 bool result = false;
471 SerialPort com = new SerialPort(string.Format("{0}{1}", PrinterType, Port), 9600, Parity.None, 8, StopBits.One);
472 try
473 {
474 com.Open();
475 com.Write(cmdBytes, 0, cmdBytes.Length);
476 result = true;
477 }
478 catch (Exception ex)
479 {
480 throw ex;
481 }
482 finally
483 {
484 if (com.IsOpen)
485 {
486 com.Close();
487 }
488 }
489 return result;
490 }
491
492 private static bool lptPrint(byte[] cmdBytes)
493 {
494 bool result = false;
495 FileStream fileStream = null;
496 StreamWriter streamWriter = null;
497 SafeFileHandle handle = null;
498 try
499 {
500 handle = CreateFile(string.Format("{0}{1}", PrinterType, Port), GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
501 if (!handle.IsInvalid)
502 {
503 fileStream = new FileStream(handle, FileAccess.ReadWrite);
504 streamWriter = new StreamWriter(fileStream, Encoding.Default);
505 streamWriter.Write(cmdBytes);
506 result = true;
507 }
508 }
509 catch (Exception ex)
510 {
511 throw ex;
512 }
513 finally
514 {
515 if (fileStream != null)
516 {
517 fileStream.Close();
518 fileStream = null;
519 }
520 if (streamWriter != null)
521 {
522 streamWriter.Close();
523 streamWriter = null;
524 }
525 if (handle != null)
526 {
527 handle.Close();
528 handle = null;
529 }
530 }
531 return result;
532 }
533
534 private static bool tcpPrint(byte[] cmdBytes)
535 {
536 bool result = false;
537 TcpClient tcp = null;
538 try
539 {
540 IPAddress ip = IPAddress.Parse(TcpIpAddress);
541 IPEndPoint iport = new IPEndPoint(ip, TcpPort);//9100为小票打印机指定端口
542 tcp = new TcpClient(iport);
543 tcp.SendTimeout = 1000;
544 tcp.ReceiveTimeout = 1000;
545 if (tcp.Connected)
546 {
547 tcp.Client.Send(cmdBytes);
548 result = true;
549 }
550 }
551 catch (Exception ex)
552 {
553 throw new Exception("打印失败,请检查打印机或网络设置。", ex);
554 }
555 finally
556 {
557 if (tcp != null)
558 {
559 if (tcp.Client != null)
560 {
561 tcp.Client.Close();
562 tcp.Client = null;
563 }
564 tcp.Close();
565 tcp = null;
566 }
567 }
568 return result;
569 }
570 #endregion
571
572 #region 生成ZPL图像打印指令
573 private static byte[] getZPLBytes()
574 {
575 byte[] result = new byte[0];
576 byte[] bmpData = getBitmapData();
577 string textBitmap = string.Empty;
578 string textHex = BitConverter.ToString(bmpData).Replace("-", string.Empty);
579 for (int i = 0; i < GraphHeight; i++)
580 {
581 textBitmap += textHex.Substring(i * RowRealBytesCount * 2, RowRealBytesCount * 2) + "\r\n";
582 }
583 string text = string.Format("~DGR:IMAGE.GRF,{0},{1},\r\n{2}^XGR:IMAGE.GRF,1,1^FS\r\n^IDR:IMAGE.GRF\r\n",
584 GraphHeight * RowRealBytesCount,
585 RowRealBytesCount,
586 textBitmap);
587 result = Encoding.Default.GetBytes(text);
588 return result;
589 }
590 #endregion
591
592 #region 生成EPL图像打印指令
593 private static byte[] getEPLBytes()
594 {
595 byte[] result = new byte[0];
596 byte[] buffer = getBitmapData();
597 string text = string.Format("N\r\nGW{0},{1},{2},{3},{4}\r\nP\r\n",
598 0,
599 0,
600 RowRealBytesCount,
601 GraphHeight,
602 TransferFormat.GetString(buffer));
603 result = TransferFormat.GetBytes(text);
604 return result;
605 }
606 #endregion
607
608 #region 生成CPCL图像打印指令
609 public static byte[] getCPCLBytes()
610 {
611 //GRAPHICS Commands
612 //Bit-mapped graphics can be printed by using graphics commands. ASCII hex (hexadecimal) is
613 //used for expanded graphics data (see example). Data size can be reduced to one-half by utilizing the
614 //COMPRESSED-GRAPHICS commands with the equivalent binary character(s) of the hex data. When
615 //using CG, a single 8 bit character is sent for every 8 bits of graphics data. When using EG two characters
616 //(16 bits) are used to transmit 8 bits of graphics data, making EG only half as efficient. Since this data is
617 //character data, however, it can be easier to handle and transmit than binary data.
618 //Format:
619 //{command} {width} {height} {x} {y} {data}
620 //where:
621 //{command}: Choose from the following:
622 //EXPANDED-GRAPHICS (or EG): Prints expanded graphics horizontally.
623 //VEXPANDED-GRAPHICS (or VEG): Prints expanded graphics vertically.
624 //COMPRESSED-GRAPHICS (or CG): Prints compressed graphics horizontally.
625 //VCOMPRESSED-GRAPHICS (or VCG): Prints compressed graphics vertically.
626 //{width}: Byte-width of image.
627 //{height} Dot-height of image.
628 //{x}: Horizontal starting position.
629 //{y}: Vertical starting position.
630 //{data}: Graphics data.
631 //Graphics command example
632 //Input:
633 //! 0 200 200 210 1
634 //EG 2 16 90 45 F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F
635 //F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F
636 //FORM
637 //PRINT
638
639 byte[] bmpData = getBitmapData();
640 int bmpDataLength = bmpData.Length;
641 for (int i = 0; i < bmpDataLength; i++)
642 {
643 bmpData[i] ^= 0xFF;
644 }
645 string textHex = BitConverter.ToString(bmpData).Replace("-", string.Empty);
646 string text = string.Format("! {0} {1} {2} {3} {4}\r\nEG {5} {6} {7} {8} {9}\r\nFORM\r\nPRINT\r\n",
647 0, //水平偏移量
648 TcpPrinterDPI, //横向DPI
649 TcpPrinterDPI, //纵向DPI
650 (int)(TcpLabelMaxHeightCM / 2.54f * TcpPrinterDPI), //标签最大像素高度=DPI*标签纸高度(英寸)
651 Copies, //份数
652 RowRealBytesCount, //图像的字节宽度
653 GraphHeight, //图像的像素高度
654 0, //横向的开始位置
655 0, //纵向的开始位置
656 textHex
657 );
658 return Encoding.UTF8.GetBytes(text);
659 }
660 #endregion
661
662 #region 获取单色位图数据
663 /// <summary>
664 /// 获取单色位图数据(1bpp),不含文件头、信息头、调色板三类数据。
665 /// </summary>
666 /// <returns></returns>
667 private static byte[] getBitmapData()
668 {
669 MemoryStream srcStream = new MemoryStream();
670 MemoryStream dstStream = new MemoryStream();
671 Bitmap srcBmp = null;
672 Bitmap dstBmp = null;
673 byte[] srcBuffer = null;
674 byte[] dstBuffer = null;
675 byte[] result = null;
676 try
677 {
678 srcStream = new MemoryStream(GraphBuffer);
679 srcBmp = Bitmap.FromStream(srcStream) as Bitmap;
680 srcBuffer = srcStream.ToArray();
681 GraphWidth = srcBmp.Width;
682 GraphHeight = srcBmp.Height;
683 dstBmp = srcBmp.Clone(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), PixelFormat.Format1bppIndexed);
684 dstBmp.Save(dstStream, ImageFormat.Bmp);
685 dstBuffer = dstStream.ToArray();
686
687 int bfSize = BitConverter.ToInt32(dstBuffer, 2);
688 int bfOffBits = BitConverter.ToInt32(dstBuffer, 10);
689 int bitmapDataLength = bfSize - bfOffBits;
690 result = new byte[GraphHeight * RowRealBytesCount];
691
692 //读取时需要反向读取每行字节实现上下翻转的效果,打印机打印顺序需要这样读取。
693 for (int i = 0; i < GraphHeight; i++)
694 {
695 Array.Copy(dstBuffer, bfOffBits + (GraphHeight - 1 - i) * RowSize, result, i * RowRealBytesCount, RowRealBytesCount);
696 }
697 }
698 catch (Exception ex)
699 {
700 throw ex;
701 }
702 finally
703 {
704 if (srcStream != null)
705 {
706 srcStream.Dispose();
707 srcStream = null;
708 }
709 if (dstStream != null)
710 {
711 dstStream.Dispose();
712 dstStream = null;
713 }
714 if (srcBmp != null)
715 {
716 srcBmp.Dispose();
717 srcBmp = null;
718 }
719 if (dstBmp != null)
720 {
721 dstBmp.Dispose();
722 dstBmp = null;
723 }
724 }
725 return result;
726 }
727 #endregion
728
729 #region 扩展
730
731 #region CPCL命令打印24位bmp
732 private static string get24BitBmpData(string filePath)
733 {
734 Bitmap bmp = new Bitmap(filePath);
735 byte[] bitArray = { 128, 64, 32, 16, 8, 4, 2, 1 };
736 string imgTxt = "";
737 Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
738 BitmapData data = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
739 IntPtr firstPix = data.Scan0;
740
741 int rowByteCount = bmp.Width * 3;
742 int filledCount = data.Stride - rowByteCount;
743 int bytes = data.Stride * data.Height;//Math.Ceiling((double)bmp.Width / 8)
744 byte[] rgbValues = new byte[bytes];
745 System.Runtime.InteropServices.Marshal.Copy(firstPix, rgbValues, 0, bytes);
746
747 int printRowByteCount = Convert.ToInt32(Math.Ceiling((double)(bmp.Width) / 8));
748 int printRowByteFillCount = 4 - (printRowByteCount % 4);
749 //int bitFillCount = 8 - (bmp.Width % 8);
750 byte[] printData = new byte[(printRowByteCount + printRowByteFillCount) * bmp.Height];
751
752 int byteCount = 0;
753 int bitCount = 0;
754 int rowPoint = 0;
755 for (int i = 0; i < rgbValues.Length; i += 3)
756 {
757 int rgbValue = rgbValues[i] + rgbValues[i + 1] + rgbValues[i + 2];
758 if (rgbValue != (255 * 3))
759 {
760 printData[byteCount] = Convert.ToByte(printData[byteCount] | bitArray[bitCount]);
761 }
762 if (bitCount == 7)
763 {
764 bitCount = 0;
765 byteCount++;
766 }
767 else
768 {
769 bitCount++;
770 }
771 if ((rowPoint + 3) == rowByteCount)
772 {
773 rowPoint = 0;
774 if (bitCount > 0)
775 {
776 byteCount++;
777 }
778 bitCount = 0;
779 byteCount += printRowByteFillCount;
780 i = i + filledCount;
781 }
782 else
783 {
784 rowPoint += 3;
785 }
786 }
787
788 foreach (byte byteData in printData)
789 {
790 string hexStr = Convert.ToString(byteData, 16);
791 if (hexStr.Length == 1)
792 {
793 hexStr = '0' + hexStr;
794 }
795 imgTxt += hexStr;
796 }
797 bmp.UnlockBits(data);
798 return imgTxt.ToUpper();
799 }
800
801 public static void Printer(string bitbmpPath)
802 {
803 string CRNL = "\r\n";
804 string imgTxt = get24BitBmpData(bitbmpPath);
805 string cmddata = "! 0 200 200 300 1" + CRNL +
806 "EG " + 24 + " " + 50 + " 10 10 " + imgTxt + CRNL +
807 "FORM" + CRNL +
808 "PRINT" + CRNL;
809 try
810 {
811 string ipAddress = "192.168.1.212";
812 int port = 9100;
813
814 // Open connection
815 System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient();
816 client.Connect(ipAddress, port);
817
818 // Write CPCL String to connection
819 System.IO.StreamWriter writer =new System.IO.StreamWriter(client.GetStream());
820 writer.Write(cmddata);
821 writer.Flush();
822
823 // Close Connection
824 writer.Close();
825 client.Close();
826 }
827 catch (Exception)
828 {
829 // Catch Exception
830 }
831 }
832 #endregion
833
834 #endregion
835 }
836
837 #region 定义设备类型枚举
838 public enum DeviceType
839 {
840 COM = 0,
841 LPT = 1,
842 DRV = 2,
843 TCP = 3
844 }
845 #endregion
846
847 #region 定义打印机指令类型枚举
848 public enum ProgrammingLanguage
849 {
850 ZPL = 0,
851 EPL = 1,
852 CPCL = 2
853 }
854 #endregion
855
856 #region 定义日志类型枚举
857 public enum LogType
858 {
859 Print = 0,
860 Error = 1
861 }
862 #endregion
863
864 #region 定义打印文档信息类
865 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
866 public class DocInfo
867 {
868 [MarshalAs(UnmanagedType.LPStr)]
869 public string DocName;
870 [MarshalAs(UnmanagedType.LPStr)]
871 public string OutputFile;
872 [MarshalAs(UnmanagedType.LPStr)]
873 public string DataType;
874 }
875 #endregion
876
877 #region 定义图像设备信息类
878 public class DeviceInfo
879 {
880 #region 属性说明
881 /*
882 ColorDepth
883 图像输出支持的颜色范围的像素深度。有效值为 1、4、8、24 和 32。默认值为 24。仅对 TIFF 呈现支持 ColorDepth,对于其他图像输出格式报表服务器将忽略此设置。
884
885 注意:
886 对于此版本的 SQL Server,此设置的值将被忽略,且通常将 TIFF 图像呈现为 24 位。
887
888 Columns
889 要为报表设置的列数。此值将覆盖报表的原始设置。
890
891 ColumnSpacing
892 要为报表设置的列间距。此值将覆盖报表的原始设置。
893
894 DpiX
895 输出设备在 X 方向的分辨率。默认值为 96。
896
897 DpiY
898 输出设备在 Y 方向的分辨率。默认值为 96。
899
900 EndPage
901 要呈现的报表的最后一页。默认值为 StartPage 的值。
902
903 MarginBottom
904 要为报表设置的下边距值,以英寸为单位。您必须包含一个整数或小数值,后跟“in”(例如,1in)。此值将覆盖报表的原始设置。
905
906 MarginLeft
907 要为报表设置的左边距值,以英寸为单位。您必须包含一个整数或小数值,后跟“in”(例如,1in)。此值将覆盖报表的原始设置。
908
909 MarginRight
910 要为报表设置的右边距值,以英寸为单位。您必须包含一个整数或小数值,后跟“in”(例如,1in)。此值将覆盖报表的原始设置。
911
912 MarginTop
913 要为报表设置的上边距值,以英寸为单位。您必须包含一个整数或小数值,后跟“in”(例如,1in)。此值将覆盖报表的原始设置。
914
915 OutputFormat
916 图形设备接口 (GDI) 支持的输出格式之一:BMP、EMF、GIF、JPEG、PNG 或 TIFF。
917
918 PageHeight
919 要为报表设置的页高,以英寸为单位。您必须包含一个整数或小数值,后跟“in”(例如,11in)。此值将覆盖报表的原始设置。
920
921 PageWidth
922 要为报表设置的页宽,以英寸为单位。您必须包含一个整数或小数值,后跟“in”(例如,8.5in)。此值将覆盖报表的原始设置。
923
924 StartPage
925 要呈现的报告的第一页。值为 0 指示将呈现所有页。默认值为 1。
926 */
927 #endregion
928
929 public enum GDIOutputFormat { BMP, EMF, GIF, JPEG, PNG, TIFF }
930
931 public int ColorDepth { get; set; }
932 public int Columns { get; set; }
933 public int ColumnSpacing { get; set; }
934 public int DpiX { get; set; }
935 public int DpiY { get; set; }
936 public int EndPage { get; set; }
937 public int MarginBottom { get; set; }
938 public int MarginLeft { get; set; }
939 public int MarginRight { get; set; }
940 public int MarginTop { get; set; }
941 public GDIOutputFormat OutputFormat { get; set; }
942 public int PageHeight { get; set; }
943 public int PageWidth { get; set; }
944 public int StartPage { get; set; }
945
946 private const string xmlFormater = @"<DeviceInfo>
947 <ColorDepth>{0}</ColorDepth>
948 <Columns>{1}</Columns>
949 <ColumnSpacing>{2}</ColumnSpacing>
950 <DpiX>{3}</DpiX>
951 <DpiY>{4}</DpiY>
952 <EndPage>{5}</EndPage>
953 <MarginBottom>{6}</MarginBottom>
954 <MarginLeft>{7}</MarginLeft>
955 <MarginRight>{8}</MarginRight>
956 <MarginTop>{9}</MarginTop>
957 <OutputFormat>{10}</OutputFormat>
958 <PageHeight>{11}</PageHeight>
959 <PageWidth>{12}</PageWidth>
960 <StartPage>{13}</StartPage>
961 </DeviceInfo>";
962
963 public DeviceInfo()
964 {
965 this.ColorDepth = 24;
966 this.Columns = 0;
967 this.StartPage = 1;
968 this.EndPage = 1;
969 }
970
971 public string GetDeviceInfo()
972 {
973 string result = string.Format(xmlFormater,
974 this.ColorDepth,
975 this.Columns,
976 this.ColumnSpacing,
977 this.DpiX,
978 this.DpiY,
979 this.EndPage,
980 this.MarginBottom,
981 this.MarginLeft,
982 this.MarginRight,
983 this.MarginTop,
984 this.OutputFormat,
985 this.PageHeight,
986 this.PageWidth,
987 this.StartPage);
988 return result;
989 }
990
991 public string GetDeviceInfoForImage()
992 {
993 string result = string.Format("<DeviceInfo><StartPage>{0}</StartPage><EndPage>{1}</EndPage><OutputFormat>{2}</OutputFormat><DpiX>{3}</DpiX><DpiY>{4}</DpiY></DeviceInfo>",
994 this.StartPage,
995 this.EndPage,
996 this.OutputFormat,
997 this.DpiX,
998 this.DpiY);
999 return result;
1000 }
1001 }
1002 #endregion
1003 }