C#直接发送打印机命令到打印机及ZPL常用打印命令 - 条码打印机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
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();
        }

  

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();
        }

posted on   龍瀧尨呀  阅读(475)  评论(0编辑  收藏  举报

编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示