zoukankan      html  css  js  c++  java
  • C#直接发送打印机命令到打印机及ZPL常用打印命令

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace BarCodeLibrary
    {
        public class ZebraGesigner
        {
            [StructLayout(LayoutKind.Sequential)]
            private struct OVERLAPPED
            {
                int Internal;
                int InternalHigh;
                int Offset;
                int OffSetHigh;
                int hEvent;
            }
            [DllImport("kernel32.dll")]
            private static extern int CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
            [DllImport("kernel32.dll")]
            private static extern bool WriteFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToWriter, out int lpNumberOfBytesWriten, out OVERLAPPED lpOverLapped);
            [DllImport("kernel32.dll")]
            private static extern bool CloseHandle(int hObject);
            [DllImport("fnthex32.dll")]
            public static extern int GETFONTHEX(string barcodeText,string fontName,int orient,int height,int width,int isBold,int isItalic,StringBuilder returnBarcodeCMD);
            private int iHandle;
            //打开LPT 端口
            public bool Open()
            {
                iHandle = CreateFile("lpt1", 0x40000000, 0, 0, 3, 0, 0);
                if (iHandle != -1)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            //打印函数,参数为打印机的命令或者其他文本!
            public bool Write(string MyString)
            {
                if (iHandle != -1)
                {
                    int i;
                    OVERLAPPED x;
                    byte[] mybyte = System.Text.Encoding.Default.GetBytes(MyString);
                    return WriteFile(iHandle, mybyte, mybyte.Length, out i, out x);
                }
                else
                {
                    throw new Exception("端口未打开~!");
                }
            }
         //关闭打印端口
            public bool Close()
            {
                return CloseHandle(iHandle);
            }
        }
    }
    vate void button1_Click(object sender, EventArgs e)  
     {  
         ZebraGesigner zb = new ZebraGesigner();  
         string mycommanglines = System.IO.File.ReadAllText("print.txt");//print.txt里写了条码机的命令  
         zb.Open();  
         zb.Write(mycommanglines);  
         zb.Close();  
    }
    /*
        ^XA                   ^XA指令块的开始     
        ^MD30                 ^MD是设置色带颜色的深度,取值范围从-30到30,上面的示意指令将颜色调到了最深.          
        ^LH60,10              ^LH是设置条码纸的边距的,这个东西在实际操作上来回试几次即可.
        ^FO20,10              ^FO是设置条码左上角的位置的,这个对程序员应该很容易理解. 0,0代表完全不留边距.
        ^ACN,18,10            ^ACN是设置字体的.因为在条码下方会显示该条码的内容,所以要设一下字体.这个跟条码无关.
        ^BY1.4,3,50           ^BY是设置条码样式的,1.4是条码的缩放级别,3是条码中粗细柱的比例,50是条码高度.
        ^BCN,,Y,N              ^BC是打印code128的指令,具体参数详见ZPL的说明书(百度云盘)
        ^FD01008D004Q-0^FS    ^FD设置要打印的内容, ^FS表示换行.
        ^XZ                   ^XZ指令块的开始    
    */
    StringBuilder builder = new StringBuilder();
    builder.AppendLine("^XA");
    builder.AppendLine("^MD30");
    builder.AppendLine("^LH60,10");
    builder.AppendLine("^FO20,10");
    builder.AppendLine("^ACN,18,10");
    builder.AppendLine("^BY1.4,3,50");
    builder.AppendLine("^BCN,,Y,N");
    builder.AppendLine("^FD01008D004Q-0^FS");
    builder.AppendLine("^XZ");
    在实践中, 常常会需要一次横打两张, 其实可以把一排的两张想像成一张, 连续执行两个打印命令, 把第二个FO的横坐标设置得大一些就行了. 
    例如:
    ^XA 
    ^FO20,10
    ^FD001^FS 
    ^FO60,10
    ^FD002^FS 
    ^XZ
    第一对FO/FD命令打印左侧, 第二对FO/FD命令打印右侧.
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Drawing;
    using System.Drawing.Printing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace ZPLPrinter
    {
        class RawPrinterHelper
        {
            // Structure and API declarions:
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            public class DOCINFOA
            {
                [MarshalAs(UnmanagedType.LPStr)]
                public string pDocName;
                [MarshalAs(UnmanagedType.LPStr)]
                public string pOutputFile;
                [MarshalAs(UnmanagedType.LPStr)]
                public string pDataType;
            }
            [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
    
            [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool ClosePrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
    
            [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool EndDocPrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool StartPagePrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool EndPagePrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
    
            // SendBytesToPrinter()
            // When the function is given a printer name and an unmanaged array
            // of bytes, the function sends those bytes to the print queue.
            // Returns true on success, false on failure.
            public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
            {
                Int32 dwError = 0, dwWritten = 0;
                IntPtr hPrinter = new IntPtr(0);
                DOCINFOA di = new DOCINFOA();
                bool bSuccess = false; // Assume failure unless you specifically succeed.
    
                di.pDocName = "My C#.NET RAW Document";
                di.pDataType = "RAW";
    
                // Open the printer.
                if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
                {
                    // Start a document.
                    if (StartDocPrinter(hPrinter, 1, di))
                    {
                        // Start a page.
                        if (StartPagePrinter(hPrinter))
                        {
                            // Write your bytes.
                            bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                            EndPagePrinter(hPrinter);
                        }
                        EndDocPrinter(hPrinter);
                    }
                    ClosePrinter(hPrinter);
                }
                // If you did not succeed, GetLastError may give more information
                // about why not.
                if (bSuccess == false)
                {
                    dwError = Marshal.GetLastWin32Error();
                }
                return bSuccess;
            }
    
            public static bool SendFileToPrinter(string szPrinterName, string szFileName)
            {
                // Open the file.
                FileStream fs = new FileStream(szFileName, FileMode.Open);
                // Create a BinaryReader on the file.
                BinaryReader br = new BinaryReader(fs);
                // Dim an array of bytes big enough to hold the file's contents.
                Byte[] bytes = new Byte[fs.Length];
                bool bSuccess = false;
                // Your unmanaged pointer.
                IntPtr pUnmanagedBytes = new IntPtr(0);
                int nLength;
    
                nLength = Convert.ToInt32(fs.Length);
                // Read the contents of the file into the array.
                bytes = br.ReadBytes(nLength);
                // Allocate some unmanaged memory for those bytes.
                pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
                // Copy the managed byte array into the unmanaged array.
                Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
                // Send the unmanaged bytes to the printer.
                bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
                // Free the unmanaged memory that you allocated earlier.
                Marshal.FreeCoTaskMem(pUnmanagedBytes);
                return bSuccess;
            }
    
            public static bool SendStringToPrinter(string szPrinterName, string szString)
            {
                IntPtr pBytes;
                Int32 dwCount;
                // How many characters are in the string?
                dwCount = szString.Length;
                // Assume that the printer is expecting ANSI text, and then convert
                // the string to ANSI text.
                pBytes = Marshal.StringToCoTaskMemAnsi(szString);
                // Send the converted ANSI string to the printer.
                SendBytesToPrinter(szPrinterName, pBytes, dwCount);
                Marshal.FreeCoTaskMem(pBytes);
                return true;
            }
        }
    }
        public string Print(string stuNo, string liuBookNo, string suoBookNum, string stuName)
        {
            if (string.IsNullOrEmpty(liuBookNo) || string.IsNullOrEmpty(suoBookNum))
            {
                return "参数错误,打印失败!";
            }
            StringBuilder tiaomaStr = new StringBuilder();
            tiaomaStr.AppendLine();
            tiaomaStr.AppendLine("N");
            tiaomaStr.AppendLine("B0,10,0,1,2,3,100,B,$" + suoBookNum + "$");
            tiaomaStr.AppendLine("A2050,10,5,9,1,1,N,$" + liuBookNo + "$");
            tiaomaStr.AppendLine("A0,160,0,8,1,1,N,$未知$");
            tiaomaStr.AppendLine("A0,210,0,8,1,1,N,$捐书人:" + stuName + "$");
            tiaomaStr.AppendLine("D15");
            tiaomaStr.AppendLine("P1");
            FileStream fs = null;
            try
            {
                string path = Server.MapPath("~/BooksManagement\File\tiaoma.txt");
                fs = new FileStream(path, FileMode.Create, FileAccess.Write);
                StreamWriter sw = new StreamWriter(fs, Encoding.Default);//ANSI编码格式
                if (File.Exists(path))
                {
                    sw.Write(tiaomaStr.ToString().Replace('$', '"'));
                    tiaomaStr.Clear();
                    sw.Flush();
                    sw.Close();
                    if (RunCmd("COPY " + path + " LPT1"))
                        return string.Empty;
                    else
                        return "参数错误,打印失败!";
                }
            }
            catch
            {
            }
            finally
            {
                fs.Close();
            }
            return "参数错误,打印失败!";
        }
    
        private bool RunCmd(string command)
        {
            //实例一个Process类,启动一个独立进程
            Process p = new Process();
            //Process类有一个StartInfo属性,這個是ProcessStartInfo类,包括了一些属性和方法,下面我們用到了他的几个属性:
            p.StartInfo.FileName = "cmd.exe";//设定程序名
            p.StartInfo.Arguments = "/c " + command;//设定程式执行参数
            p.StartInfo.UseShellExecute = false;//关闭Shell的使用
            p.StartInfo.RedirectStandardInput = true;//重定向标准输入
            p.StartInfo.RedirectStandardOutput = true;//重定向标准输出
            p.StartInfo.RedirectStandardError = true;//重定向错误输出
            p.StartInfo.CreateNoWindow = true;//设置不显示窗口
            //p.StandardInput.WriteLine(command);//也可以用这种方式输入要执行的命令
            //p.StandardInput.WriteLine("exit");//不过要记得加上Exit要不然下一行程式执行的時候会当机
            try
            {
                p.Start();//开始进程
                return true;
            }
            catch
            {
            }
            finally
            {
                if (p != null)
                    p.Close();
            }
            return false;
        }
            /*
                 中文或其它复杂设计成图片,然后用ZPL命令发送给条码打印机打印             
                //定义字体  
                Font drawFont = new Font("Arial", 10, FontStyle.Bold, GraphicsUnit.Millimeter);
                //生成图片
                Bitmap img = CreateImage("出厂日期:" + DateTime.Now, drawFont);
                var imgCode = ConvertImageToCode(img);
                var t = ((img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)) * img.Size.Height).ToString(); //图形中的总字节数
                var w = (img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)).ToString(); //每行的字节数
                string zpl = string.Format("~DGR:imgName.GRF,{0},{1},{2}", t, w, imgCode); //发送给打印机
            */
    
            /// <summary>
            /// 生成Bitmap
            /// </summary>
            /// <param name="data">字符串</param>
            /// <param name="f">文本格式</param>
            /// <returns></returns>
            protected Bitmap CreateImage(string data, Font f)
            {
                if (string.IsNullOrEmpty(data))
                    return null;
                var txt = new TextBox();
                txt.Text = data;
                txt.Font = f;
                //txt.PreferredSize.Height只能取到一行的高度(连边距) 
                //所以需要乘以行数, 但是必须先减掉边距, 乘了以后,再把边距加上. 
                //5是目测的边距 
                var image = new Bitmap(txt.PreferredSize.Width, (txt.PreferredSize.Height - 5) * txt.Lines.Length + 5);
                var g = Graphics.FromImage(image);
                var b = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Black, Color.Black, 1.2f, true);
                g.Clear(System.Drawing.Color.White);
                g.DrawString(data, f, b, 1, 1);
                return image;
            }
    
            /// <summary>
            /// 序列化图片
            /// </summary>
            /// <param name="img">Bitmap</param>
            /// <returns></returns>
            protected string ConvertImageToCode(Bitmap img)
            {
                var sb = new StringBuilder();
                long clr = 0, n = 0;
                int b = 0;
                for (int i = 0; i < img.Size.Height; i++)
                {
                    for (int j = 0; j < img.Size.Width; j++)
                    {
                        b = b * 2;
                        clr = img.GetPixel(j, i).ToArgb();
                        string s = clr.ToString("X");
    
                        if (s.Substring(s.Length - 6, 6).CompareTo("BBBBBB") < 0)
                        {
                            b++;
                        }
                        n++;
                        if (j == (img.Size.Width - 1))
                        {
                            if (n < 8)
                            {
                                b = b * (2 ^ (8 - (int)n));
    
                                sb.Append(b.ToString("X").PadLeft(2, '0'));
                                b = 0;
                                n = 0;
                            }
                        }
                        if (n >= 8)
                        {
                            sb.Append(b.ToString("X").PadLeft(2, '0'));
                            b = 0;
                            n = 0;
                        }
                    }
                    sb.Append(System.Environment.NewLine);
                }
                return sb.ToString();
            } 

  • 相关阅读:
    DDD~大话目录
    基于DDD的.NET开发框架-DDD经典分层
    补习知识:Entity Framework Code First属性映射约定
    一个官翻教程集合:ASP.NET Core 和 EF Core 系列教程
    补知识:EntityFramework Core映射关系详解
    关于this的问题
    promise
    js的类型转换
    不要在块内声明一个函数
    let和var
  • 原文地址:https://www.cnblogs.com/smartsmile/p/6234217.html
Copyright © 2011-2022 走看看