QT 驱动条码打印机(没有验证过)

这里的打印机是条码打印机,因为第一次接触这种设备,所以买了斑马的GK888t型条码打印机,据说ZPL语言就是斑马的杰作想必支持会好点。实际是,除了ZPL本身外,没有SDK,也没有DDK,所以,一切就只能靠搜索引擎帮忙了,这里感谢百度和谷歌啦。

写在开头:有些在网上找的内容忘了留网址,写该文时搜索相关内容补的网址,请原相关作者见谅。

粗略总结了6种方法,个人比较推荐第6第3种方法。如下:

1、直接打印(最简单)。

条码打印机可以当做普通打印机使用。所以,你用记事本、word等等只要有打印功能的,都可以打印。所以该方法就是使用Qt绘制图片、path什么的,然后打印即可。

2、把USB打印机映射到LPT端口。

参照:http://blog.sina.com.cn/s/blog_6d4dcdba0100xowi.html

这里我在本机不需要安装"Microsoft Loopback Adapter",而是使用如下的方法:(gk888t是我共享的打印机名)
net use LPT2 \\127.0.0.1\gk888t

3、使用转意字符(需要ZPL语言,建议)。

参照:http://stackoverflow.com/questions/4442122/send-raw-zpl-to-zebra-printer-via-usb

一定要按上文方法设置转意字符。代码如下,不再阐述。


QPrinter printer(QPrinter::PrinterResolution);
QPrintDialog *dlg = new QPrintDialog(&printer, this);


if (dlg->exec() == QDialog::Accepted)
{
    QPainter p(&printer);
    p.drawText(0,0,"${^XA^FO10,100^BY3^BCN,100,Y,N,N^FDDC123456^FS^XZ}$");

............

}

4、使用CUPs API(未完成)。

参照:http://stackoverflow.com/questions/5558248/qt-print-raw-text

粗试文中的方法,当时链接库没搞好,所以放弃了。

5、使用libusb-win32(可以)。

参照:http://sourceforge.net/apps/trac/libusb-win32/wiki

http://www.4ucode.com/Study/Topic/617136

特别声明:如果你和我一样是菜鸟,请注意,最好在试验该方法时在虚拟机内进行,不然,系统USB设备可能会统统罢工的。
参照testlibusb.c例程,这里贴一下打印的代码:


别忘了在.pro文件添加
LIBS += ./libusb.a
这里我把libusb.a和源代码放在了一起,还有lusb0_usb.h头文件不要忘了,......


udev = usb_open(dev);
if (udev)
{
char *sb = "^XA^FO10,100^BY3^BCN,100,Y,N,N^FDDAe123456^FS^XZ";
int ok = usb_claim_interface(udev,0);
printf("%d\n",ok);
ok = usb_bulk_write(udev,0x01,sb,50,1000);
printf("%d\n",ok);
............


但这里有个问题,一直没有搞定使用libusb同时又使用系统的打印机驱动模式,也就是说,在该模式下,无法使用打印服务访问打印机,不再支持直接打印。
这个不知是我的设置问题还是什么。折腾的时候发现,使用一种方法可以一起使用,但一旦系统重启就不再可以,同时,打印服务以及rpc服务均不正常,需要使用斑马自带的打印机安装程序重新安装,系统才能回复正常,但一重启依旧。

6、使用Win32 API打印原始数据(强烈建议)。

这可是微软的方法啊,不用在系统添加任何文件,同时又能保证打印机的正常使用,所以强烈建议。

参照:http://support.microsoft.com/kb/138594

在.pro文件添加
LIBS += D:\Qt\qtcreator-2.4.1\mingw\lib\libwinspool.a
注:我的mingw安装路径 D:\Qt\qtcreator-2.4.1\mingw。


贴一段我用来试验该方法的源代码:
注意事项:qt creater是UNICODE环境,所以使用OpenPrinter等函数时会自动转为OpenPrinterW,这样就需要进行char到wchar的转换或者使用宏定义,请参看winspool.h的内容,觉得比较烦,所以就直接给它改成OpenPrinterA了(其它同)。

#include "widget.h"

#include "ui_widget.h"

#include

#include

#include

#include

#include <windows.h>

#include <winspool.h>

#include

BOOL RawDataToPrinter(LPSTR szPrinterName, LPBYTE lpData, DWORD dwCount);

bool RawDataToPrinter(QString printerName,QStringList *barcode);

Widget::Widget(QWidget *parent) :

QWidget(parent),

ui(new Ui::Widget)

{

ui->setupUi(this);

}

Widget::~Widget()

{

delete ui;

}

void Widget::on_pushButton_clicked()

{

QPrinter printer(QPrinter::PrinterResolution);

QPrintDialog *dlg = new QPrintDialog(&printer, this);

if (dlg->exec() == QDialog::Accepted)

{

QPainter p(&printer);

//p.drawText(0,0," X A F O 10 , 10 0 B Y 3 B C N , 100 , Y , N , N F D D C 12345 6 F S X Z {^XA^FO10,100^BY3^BCN,100,Y,N,N^FDDC123456^FS^XZ} XAFO10,100BY3BCN,100,Y,N,NFDDC123456FSXZ");

//p.drawText(0,0," X A F O 10 , 10 0 B Y 3 B C N , 100 , Y , N , N F D C D 12345 6 F S X Z {^XA^FO10,100^BY3^BCN,100,Y,N,N^FDCD123456^FS^XZ} XAFO10,100BY3BCN,100,Y,N,NFDCD123456FSXZ");

QString printerName = printer.printerName();

QString lpData = tr("^XA^FO10,100^BY3^BCN,100,Y,N,N^FDDD123456^FS^XZ");

long dwCount = lpData.length();

QStringList sl;

sl.append(tr("^XA^FO10,100^BY3^BCN,100,Y,N,N^FDAB123456^FS^XZ"));

sl.append(tr("^XA^FO10,100^BY3^BCN,100,Y,N,N^FDCD123456^FS^XZ"));

sl.append(tr("^XA^FO10,100^BY3^BCN,100,Y,N,N^FDEF123456^FS^XZ"));

if(RawDataToPrinter(printerName,&sl)==true)

{

qDebug() << "OK";

}else

{

qDebug() << "NO";

}

/if(RawDataToPrinter((char )printerName.toLocal8Bit().data(),(unsigned char*)lpData.toLocal8Bit().data(),dwCount) == true)

{

qDebug() << "OK";

}else

{

qDebug() << "NO";

}*/

}

delete dlg;

}

BOOL RawDataToPrinter(LPSTR szPrinterName, LPBYTE lpData, DWORD dwCount)

{

HANDLE hPrinter;

DOC_INFO_1A DocInfo;

DWORD dwJob;

DWORD dwBytesWritten;

// Need a handle to the printer.

if(!OpenPrinterA(szPrinterName,&hPrinter,NULL))

{

return FALSE;

}

// Fill in the structure with info about this "document."

DocInfo.pDocName = "BarCode";

DocInfo.pOutputFile = NULL;

DocInfo.pDatatype = "RAW";

// Inform the spooler the document is beginning.

if((dwJob = StartDocPrinterA(hPrinter,1,(PBYTE)&DocInfo)) == 0)

{

ClosePrinter(hPrinter);

return FALSE;

}

// Start a page.

if(!StartPagePrinter(hPrinter))

{

EndDocPrinter(hPrinter);

ClosePrinter(hPrinter);

return FALSE;

}

// Send the data to the printer.

if(!WritePrinter(hPrinter,lpData,dwCount,&dwBytesWritten))

{

EndPagePrinter(hPrinter);

EndDocPrinter(hPrinter);

ClosePrinter(hPrinter);

return FALSE;

}

if(!WritePrinter(hPrinter,lpData,dwCount,&dwBytesWritten))

{

EndPagePrinter(hPrinter);

EndDocPrinter(hPrinter);

ClosePrinter(hPrinter);

return FALSE;

}

// End the page.

if(!EndPagePrinter(hPrinter))

{

EndDocPrinter(hPrinter);

ClosePrinter(hPrinter);

return FALSE;

}

// Inform the spooler that the document is ending.

if(!EndDocPrinter(hPrinter))

{

ClosePrinter(hPrinter);

return FALSE;

}

// Tidy up the printer handle.

ClosePrinter(hPrinter);

// Check to see if correct number of bytes were written.

if(dwBytesWritten != dwCount)

{

QMessageBox::warning(0,QObject::tr("打印"),QObject::tr("打印输出数据与输入数据大小不相符"),QObject::tr("确定(&E)"));

return FALSE;

}else

{

return TRUE;

}

}

bool RawDataToPrinter(QString printerName, QStringList *barcode)

{

HANDLE hPrinter;

DOC_INFO_1A DocInfo;

DWORD dwJob;

DWORD dwBytesWritten;

LPSTR szPrinterName;

long dwCount;

if(!(barcode->length() >0))

{

return false;

}

szPrinterName = (char*)printerName.toLocal8Bit().data();

//获取打印机的handle

if(!OpenPrinterA(szPrinterName,&hPrinter,NULL))

{

return false;

}

//填充打印文档的DOC_INFO_1A

DocInfo.pDocName = "BarCode";

DocInfo.pOutputFile = NULL;

DocInfo.pDatatype = "RAW";

//通知打印服务,准备开始打印文档

if((dwJob = StartDocPrinterA(hPrinter,1,(PBYTE)&DocInfo)) == 0)

{

ClosePrinter(hPrinter);

return false;

}

//开始一页的打印

if(!StartPagePrinter(hPrinter))

{

EndDocPrinter(hPrinter);

ClosePrinter(hPrinter);

return false;

}

foreach(QString str,*barcode)

{

//发送数据到打印机

dwCount = str.toLocal8Bit().length();

if(!WritePrinter(hPrinter,(unsigned char *)str.toLocal8Bit().data(),dwCount,&dwBytesWritten))

{

EndPagePrinter(hPrinter);

EndDocPrinter(hPrinter);

ClosePrinter(hPrinter);

return false;

}

//检查实际写入数据是否与原始数据大小相符

if(dwBytesWritten != dwCount)

{

QMessageBox::warning(0,QObject::tr("打印"),QObject::tr("打印输出数据与输入数据大小不相符"),QObject::tr("确定(&E)"));

EndPagePrinter(hPrinter);

EndDocPrinter(hPrinter);

ClosePrinter(hPrinter);

return false;

}

}

//结束一页的打印

if(!EndPagePrinter(hPrinter))

{

EndDocPrinter(hPrinter);

ClosePrinter(hPrinter);

return FALSE;

}

//通知打印服务,文档打印结束

if(!EndDocPrinter(hPrinter))

{

ClosePrinter(hPrinter);

return FALSE;

}

//收回handle

ClosePrinter(hPrinter);

return true;

}

以上即我当前所能使用的方法,希望能给大家带来帮助,如有不到之处希望当家指正。
相关推荐
小堃学编程23 分钟前
计算机网络(十) —— IP协议详解,理解运营商和全球网络
网络·tcp/ip·计算机网络
吾爱星辰2 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer2 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
IT良2 小时前
c#增删改查 (数据操作的基础)
开发语言·c#
IPFoxy6663 小时前
探索路由器静态IP的获取方式
网络·智能路由器
Kalika0-03 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
_.Switch3 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
代码雕刻家3 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
menge23333 小时前
VLAN:虚拟局域网
网络·智能路由器
一个闪现必杀技3 小时前
Python入门--函数
开发语言·python·青少年编程·pycharm