打印机(条码)打印标签、条码的方式一种是通过驱动发送图形的方式(这时一般需要排版软件),另一种是无需驱动直接通过发送指令到打印机执行打印。这里就是采取第二种方式打印。下面把实现过程中遇到的问题和一些心得总结一下:本实例使用DataMax-i-4308打印机。
1. VS(2008)中存在Com口操作的控件,却未有现成的LPT端口控件,而相对COM口来说,LPT的速度要快,所以在打印的时候客户一般选择LPT通讯方式,经过网上的一些查阅,终于实现了LPT口的打印,其他品牌打印机原理类似,只是打印指令有所区别。
实现LPT端口指令打印的方式是采用Windows下的API函数CreateFile,该函数要实现并口操作,需要设置几个关键参数。函数原型为:
HANDLE WINAPI CreateFile( LPCTSTRlpFileName, DWORDdwDesiredAccess, DWORDdwShareMode, LPSECURITY_ATTRIBUTESlpSecurityAttributes, DWORDdwCreationDisposition, DWORDdwFlagsAndAttributes, HANDLEhTemplateFile);
LPT操作需要设置:
lpFileName应设为端口号;如"LPT1"或者"COM3"等;
dwDesiredAccess设为GENERIC_WRITE或者GENERIC_READ或者GENERIC_WRITE|GENERIC_READ。
dwCreationDisposition应设为OPEN_EXISTING。
hTemplateFile需要设为NULL或者0。
在C#中使用API需要做一个dll库的使用声明,例:
[DllImport("kernel32.dll ")]
private static extern int CreateFile( string lpFileName, uint dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
注:以上的宏需要自己定义,例:private const uint GENERIC_WRITE = 0x40000000; private const int OPEN_EXISTING = 3;
2. 使用CreateFile操作并口,然后使用CreateFile返回的句柄与并口通信。例:(我这里是写入数据到LPT1)
int hPort = CreateFile("LPT1", GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
System.IntPtr hPortP = new IntPtr(hPort);//定义一个IntPtr对象并初始化,用于对句柄操作。
SafeFileHandle sfHandle = new SafeFileHandle(hPortP, true);//因为用hPortP给出警告。
FileStream fs;
fs = new FileStream(sfHandle, FileAccess.Write,1);//利用安全句柄和写模式实例一个文件流。
StreamWriter writer = new StreamWriter(fs);//定义一个写入流进行向LPT1写入数据。
writer.AutoFlush = false;//不让自动清空
writer.WriteLine(sContent);//把数据(字符串)写入到LPT1。
writer.Flush();
writer.Close();
fs.Close();
CloseHandle(hPort);
3. DataMax的指令DPL与Zebra的指令ZPL不同,开始编写指令发送,总是遇到一些无法打印(识别)的问题。DPL看上去不如ZPL好理解,也许是很多人对ZPL比较熟悉的原因。其实总的来说指令都大同小异,只是语法标示不太一样。DPL指令在标签设置部分是以<STX>L做开始标示符的。每行语句以<CR>做结束符。开始学习时一直把<STX>当做一个字符串来理解,在网上差了一些资料,说是需要转化为16进制才行,然后拼命的将<STX>转化为16进制,再把十六进制的数字格式化为字符串,发送给打印机仍然是无反应。最后研究了下ASCII码,发现STX是一个控制字符。<>只是起到说明里面的内容是控制字符的意思,需要用16进制转义字符。例:
str = "\x02L\n" + "D11\n" + "1E0000000150100" + textBoxNum.Text +
dateTimePickerDate.Value.ToString("yyyyMMdd") + strFor + "\n";//输入的单位编号加日期加流水号组成条码内容。
str += "121100000000100Barcode E\n" + "E\n";
把这里的str赋值给上面的sContent就行了,具体的函数编写可以根据自己的习惯或者思维方式来写。实现的方式很多种,也可以自己定义一个类封装函数。