zoukankan      html  css  js  c++  java
  • QT(Send raw data to printer)发送原始数据到USB打印机

    QT(Send raw data to printer)发送原始数据到USB打印机

    http://hi.baidu.com/ppacctv/blog/item/c9517538a35ef3d2b211c72f.html

    欢迎转载,敬请注明出处,如有疑问可以发邮件给我ppacctv@163.com,欢迎探讨,如果可以,也请把您的高招分享一下。谢谢!

    项目需要,在网上找了很久,能用的很少,试了很多方法,总结一下分享在这里,希望能给大家提供帮助。

    这里的打印机是条码打印机,因为第一次接触这种设备,所以买了斑马的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.1gk888t

    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 ",ok);
    ok = usb_bulk_write(udev,0x01,sb,50,1000);
    printf("%d ",ok);
    …………

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


    6、使用Win32 API打印原始数据(强烈建议)。
    这可是微软的方法啊,不用在系统添加任何文件,同时又能保证打印机的正常使用,所以强烈建议。
    参照:http://support.microsoft.com/kb/138594

    在.pro文件添加
    LIBS += D:Qtqtcreator-2.4.1mingwliblibwinspool.a
    注:我的mingw安装路径 D:Qtqtcreator-2.4.1mingw。

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


    #include "widget.h"
    #include "ui_widget.h"

    #include <QPrinter>
    #include <QPrintDialog>
    #include <QPainter>
    #include <QDebug>
    #include <windows.h>
    #include <winspool.h>
    #include <QMessageBox>

    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,"${^XA^FO10,100^BY3^BCN,100,Y,N,N^FDDC123456^FS^XZ}$");
    //p.drawText(0,0,"${^XA^FO10,100^BY3^BCN,100,Y,N,N^FDCD123456^FS^XZ}$");

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


    以上即我当前所能使用的方法,希望能给大家带来帮助,如有不到之处希望当家指正。

    在次感谢网上其他同仁的无私奉献!

    欢迎讨论、欢迎转载,敬请注明出处,谢谢!

  • 相关阅读:
    hdu6514 // 二维差分 二维前缀和 基本容斥 压维
    【模板】欧拉函数 & 欧拉筛
    并查集模板 hdu1703
    大数 gcd
    hdu1087 dp
    洛谷p1306 斐波那契公约数
    hdu6814 Tetrahedron 线性求逆元 + 快速幂求逆元
    hdu6867 Tree // DFS
    hdu6869 Slime and Stones // 威佐夫博弈&#183;改
    Python实现EXCEL表格的排序功能
  • 原文地址:https://www.cnblogs.com/kevinzhwl/p/3619786.html
Copyright © 2011-2022 走看看