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("XAFO10,100BY3BCN,100,Y,N,NFDDD123456FS^XZ");

long dwCount = lpData.length();

QStringList sl;

sl.append(tr("XAFO10,100BY3BCN,100,Y,N,NFDAB123456FS^XZ"));

sl.append(tr("XAFO10,100BY3BCN,100,Y,N,NFDCD123456FS^XZ"));

sl.append(tr("XAFO10,100BY3BCN,100,Y,N,NFDEF123456FS^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;

}

复制代码
以上即我当前所能使用的方法,希望能给大家带来帮助,如有不到之处希望当家指正。
相关推荐
不是万能的豆学长4 小时前
filetidy 文件整理助手:一键归类 + 规范重命名(Python 零依赖单文件工具)
大数据·开发语言·python·技术美术
懂点Tech8 小时前
ctfshow MISC入门图片篇(信息附加):misc41解题思路
开发语言·python
catchadmin9 小时前
PHP 8.7 协程新提案 让跨协程代码共享请求身份
开发语言·php
念何架构之路10 小时前
go-grpc设计思想
开发语言·后端·golang
酷炫码神10 小时前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
Elastic 中国社区官方博客11 小时前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn18811 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn12 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
g3voip13 小时前
工业防水电话到底怎么选?隧道、管廊与码头的需求差异
服务器·网络·信息与通信·ip
传奇开心果编程13 小时前
【Rust入门练中学】第5课:引用与借用
开发语言·rust·引用·编程语言理论·通用编程语言·借用