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 #endregion11 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 #endregion21 22 #region ZPL II 打印指令23 //^XA^CFD24 //^POI25 //^LH330,1026 //^FO50,5027 //^FDSMARTDIGITAL^FS28 //^FO50,7529 //^FD021-51871630^FS30 //^XZ31 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 #endregion45 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 #endregion63 }
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 /// 16 /// 斑马打印助手,支持LPT/COM/USB/TCP四种模式,适用于标签、票据、条码打印。 17 /// 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 /// 65 /// 线程锁,防止多线程调用。 66 /// 67 private static object SyncRoot = new object(); 68 69 /// 70 /// 字节流传递时采用的字符编码 71 /// 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 /// 90 /// 日志保存目录,WEB应用注意不能放在BIN目录下。 91 /// 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 /// 664 /// 获取单色位图数据(1bpp),不含文件头、信息头、调色板三类数据。 665 /// 666 /// 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 = @" 947 {0} 948 {1} 949 {2} 950 {3} 951 {4} 952 {5} 953 {6} 954 {7} 955 {8} 956 {9} 957 {10} 958 {11} 959 {12} 960 {13} 961 "; 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(" {0} {1} {2} {3} {4} ", 994 this.StartPage, 995 this.EndPage, 996 this.OutputFormat, 997 this.DpiX, 998 this.DpiY); 999 return result;1000 }1001 }1002 #endregion 1003 }