由于项目需要实现标签在线打印,标签的信息根据产品信息变化,打印机型号为TSC TTP-244_Pro,TSC官方提供了免费的barTender可供下载使用,所以决定使用barTender设置标签模板,数据源采用嵌入式数据。在打印时,Qt通过QAxObject的方式,调用barTender,实现具名数据源替换和打印。
1、首先需要在项目的pro文件中添加axcontainer,如QT += axcontainer;本人使用Qt5.12+VS2019。
2、安装barTender;安装成功后,如果默认安装在C盘,可以在C:\Program Files\Seagull\BarTender 2022\Help\ 目录下找到开发帮助文档Automation.chm
文档中有关于ActivX相关接口的说明,以及c#和VB的例子,可供参考。使用C++调用barTarder接口就是参考的这个帮助文档。
3、使用barTender创建一个指定了打印机的模板,并给数据设置数据源名称。然后保存为btw格式。
4、bartender.h
#ifndef BARTENDER_H
#define BARTENDER_H
#include <QObject>
#include <QAxObject>
class BarTender : public QObject
{
Q_OBJECT
public:
explicit BarTender(QObject *parent = nullptr);
~BarTender();
//打开btw文件
bool OpenFliePath(const QString &path);
//当打开多个文件时,激活其中某个文件
void Activate(const QString path);
//关闭
void close(const QString path = "");
//获取打印机名(打印机名是从btw信息中获取的)
QString getPrinterName();
//设置打印机名
void setPrinterName(const QString &name);
//设置具名数据源的数据,name:数据源名称,value:值
void addNamedValue(const QString &name,const QString &value);
//获取所有具名数据源名称,返回的字符串数据用NameValueDelimiter和RecordDelimiter分割。
QString getAllNamedValue(const QString NameValueDelimiter, const QString RecordDelimiter);
//生成图片
bool generateBmp(QPixmap &);
//打印
void print();
signals:
public slots:
private:
QAxObject *m_btApp = nullptr;
QAxObject *m_btFormats = nullptr;
QAxObject *m_btFormat = nullptr;
QString m_PrinterName;
QMap<QString,QAxObject*> m_FormatMap;/*由于打开btw文件较慢,所以把打开的m_btFormat存到一个QMap中,以备后续再次使用文件*/
};
#endif // BARTENDER_H
5、bartender.cpp
#include "bartender.h"
#include <QDebug>
#include <ole2.h>
#include <QDir>
#include <QApplication>
#include <QClipboard>
#include <QPixmap>
BarTender::BarTender(QObject *parent) : QObject(parent)
{
OleInitialize(0);//多线程时,必须加
m_btApp = new QAxObject();
m_btApp->setControl("BarTender.Application");//连接BarTender控件
m_btFormats = m_btApp->querySubObject("Formats");
}
BarTender::~BarTender()
{
if(m_btApp)
{
m_btApp->dynamicCall("Quit(int)",1);
delete m_btApp;
}
qDebug()<<"BarTender destructing...";
}
//打开文件
bool BarTender::OpenFliePath(const QString &path)
{
if(path.isEmpty() || !QFile(path).exists())
{
return false;
}
if(m_FormatMap.contains(path))
{
m_btFormat = m_FormatMap[path];
return true;
}
else if(m_btFormats)
{
m_btFormat = m_btFormats->querySubObject("Open(char *,bool,char *)", path.toStdString().c_str(),false,"");
if(m_btFormat)
{
m_FormatMap.insert(path,m_btFormat);
return true;
}
}
return false;
}
void BarTender::Activate(const QString path)
{
if(m_FormatMap.contains(path))
{
m_btFormat = m_FormatMap[path];
m_btFormat->dynamicCall("Activate");
}
}
//关闭文件
void BarTender::close(const QString path)
{
if(path.isEmpty()) //关闭当前文件
{
if(m_btFormat)
{
m_btFormat->dynamicCall("Close(int)",1);
QMap<QString,QAxObject*>::iterator it;
for (it = m_FormatMap.begin(); it != m_FormatMap.end(); ++it)
{
if(it.value() == m_btFormat)
{
m_FormatMap.remove(it.key());
break;
}
}
m_btFormat = nullptr;
}
}
else if(m_FormatMap.contains(path)) //关闭指定文件
{
QAxObject *btFormat = m_FormatMap[path];
m_FormatMap.remove(path);
btFormat->dynamicCall("Close(int)",1);
if(m_btFormat == btFormat)
{
m_btFormat = nullptr;
}
}
}
//选择打印机(暂时没用到)
void BarTender::setPrinterName(const QString &name)
{
if(name.isEmpty())
{
return;
}
if(m_btFormat)
{
m_btFormat->dynamicCall("Printer(char *)",name.toStdString().c_str());
}
}
//获取打印机名(从btw文件信息中获取)
QString BarTender::getPrinterName()
{
QString name;
if(m_btFormat)
{
QAxObject *PrintSetup = m_btFormat->querySubObject("PrintSetup");
QVariant printName = PrintSetup->dynamicCall("Printer");
name = printName.toString();
}
return name;
}
//替换数据源
void BarTender::addNamedValue(const QString &name, const QString &value)
{
if(name.isEmpty() || value.isEmpty())
{
return;
}
if(m_btFormat)
{
m_btFormat->dynamicCall("SetNamedSubStringValue(char *,char *)", name.toStdString().c_str(),value.toStdString().c_str());
}
}
//获取所有具名数据源名称
QString BarTender::getAllNamedValue(const QString NameValueDelimiter, const QString RecordDelimiter)
{
QString namedSubStrings;
if(m_btFormat)
{
QAxObject *namedSubStringsPtr = m_btFormat->querySubObject("NamedSubStrings");
if(namedSubStringsPtr)
{
QVariant result = namedSubStringsPtr->dynamicCall("GetAll(char *,char *)", NameValueDelimiter.toStdString().c_str(),RecordDelimiter.toStdString().c_str());
namedSubStrings = result.toString();
}
}
return namedSubStrings;
}
//根据打开的文件,生成一张图片
bool BarTender::generateBmp(QPixmap &image)
{
if(m_btFormat)
{
//m_btFormat->dynamicCall("ExportToFile(char *,char *,int,int,int)",path.toStdString().c_str(), "BMP",2,400,2);/*保存图片到文件,第3个参数0表示位深(0:1,1:4,2:8),第4个参数表示分辨率(1表示和打印机分辨率一致),第5个参数表示是否保存修改(2表示保存修改)*/
m_btFormat->dynamicCall("ExportToClipboard(int,int)", 2,400);/*保存图片到粘贴板,2表示颜色,400表示dpi;*/
QClipboard *clipboard = QApplication::clipboard();
image = clipboard->pixmap();
if(!image.isNull())
{
return true;
}
}
return false;
}
//打印
void BarTender::print()
{
if(m_btFormat)
{
m_btFormat->dynamicCall("IdenticalCopiesOfLabel",1);//设置同序列打印的份数
m_btFormat->dynamicCall("NumberSerializedLabels",1);//设置需要打印的序列数
m_btFormat->dynamicCall("PrintOut(bool,bool)",true, false);
}
}
6、使用方法:首先就是调用OpenFliePath打开使用barTender编写好的xxx.btw文件,xxx.btw模板文件创建时会提示选择打印机,所以btw文件中已经有了打印机的信息。然后就是调用addNamedValue替换btw文件中的具名数据源,最后调用print打印。如果想在界面显示打印效果也可以调用generateBmp生成一个图片用于展示。
由于代码是从工程中摘录,并删除了一些和工程相关的代码,运行中可能会有错误,仅供参考。