BarTender是一款优秀的条形码打印软件,可以支持很多种类型的条形码设计和打印,具体大家可参考他的官网(http://www.seagullscientific.com/aspx/products.aspx),这里不多介绍。
本来在做SilverLight的东西的,后来项目有需求,说要在系统里加入条形码的设计和打印功能,PM提出两个方案,一个就是自己去开发一个条形码设计器,这样的好处就是跟系统的集成使用比较方便,但是开发这个设计器又是一个比较大的Task;另外一个方案就是使用客户原有的BarTender软件,把软件集成到系统中,那么设计部分还是交由BarTender去完成,我们的系统只需开发集成的部分就好。经过商量,大家决定了采取集成BarTender的方案,于是就要找人去做技术攻关了,跟原来的Partner商量了一下,他说想继续深入学习SilverLight,我就想去涉猎更多的东西,于是刚好,分道了~~
在刚开始接触BarTender的时候,发现网上的资料很少,我是把他们官网上的资料都看了,什么白皮书啊,向导之类的都看了。我们的系统是ASP.NET做的,通过一段时间的学习,知道了BarTender的几种集成模式。ActiveX COM集成,Commander的触发式集成,还有9.0版本后支持的.NET SDK的支持。简单说说这几个方式:
1、              ActiveX COM:BarTender在你的机器上安装好后,会在机器上注册一个COM,你在程序中可以调用这个COM,使用他提供的方法和属性,进行BarTender的程序级控制。这个集成方式比较实用,对BarTender的版本要求低,不过因为是基本的COM使用,所以要求你对COM的接口比较熟悉,对整个BarTender的调用流程和细节比较清晰,对于COM接口的描述,大家可以参考Automation.chm这个帮助文档(在Seagull\BarTender Suite\BarTender目录下)。
2、              Commander的触发式集成:简单来说,这个是通过配置BarTender,让他监视某个文件,当程序生成这个文件的时候,就会触发唤醒BarTender进行打印工作,这种方式我觉得不大好用,所以了解也不多,欢迎讨论交流。
3、              .NET SDK:这个是9.0版本开始支持的一个适用于.NET框架的SDK,里面提供了很多类来进行BarTender的控制,由于这个SDK也是用.NET编写的,所以对于用在.NET下的集成非常方便,不过由于对版本有要求,所以要考虑客户的成本来使用。
一、.NET SDK
我们的项目开始的时候是使用.NET SDK 的,因为那时都还没有搞清楚客户是需要在服务器打印还是客户端打印,老大就要求先开始研究了,这个很气人!做了许久才说客户要在客户端打印,把之前做的一切东西都推翻了~~
.NET SDK里面分开了两个,一个是标准的,一个是Server版的,标准的只是简单的开启BarTender进程去处理打印任务,所以当有多个任务同时打印的时候,就需要自己去管理任务队列问题;而Server版的就是里面有了任务队列机制,很方便的管理任务队列和BarTender的进程资源。但是Server版需要安装BarTender的Enterprise版才支持,ORZ~~什么都是钱~~
1、              SDK其实底层上也是对COM的调用,只不过封装了,让开发者更好操作,标准的SDK应该看帮助文档没什么问题,里面对各个类以及他们的方法和属性都做了详细的解释。下面给出一段代码,里面代表了最简单的典型使用:<!--[endif]-->
首先添加引用,在.NET的TAB里面可以找到Seagull.BarTender.Print
然后,在程序里添加命名空间引用 “using Seagull.BarTender.Print;”
之后程序的简单使用如下:
//new an BarTender engine
Engine engine = new Engine(true);
//use the engine to open a format document to return a LabelFormatDocument object
LabelFormatDocument format = engine.Documents.Open("c:\\test.btw");
//use the LabelFormatDocument object to print
format.Print("Select printer", out messages);

           使用完成后记得回收相关资源。

2、              对于Server版的SDK,我在这里稍微的描述一下他的队列管理详细吧,不过单纯使用SDK是不需要知道这些东西的,使用上跟标准的SDK一样简单,只要参考帮助文档和Samples就可以很好明白了。写出他的队列管理详细仅供大家探讨~~大家看这一部分源码的时候,要先看一下线程的相关知识。<!--[endif]-->
1) 程序流程核心是:把任务放进任务队列里,任务队列检测到有任务在排队的话,就把任务扔到引擎管理中,选择一个空闲的引擎来执行任务。
2) 管理任务队列主要是使用BtPool类,这个类里面的Consume函数不断地检测队列是否为空,如果不为空,则开始任务的提交工作,先通过engine.Status != TaskEngineStatus.Busy来检测空闲的Engine,然后通过engine.SubmitTask(this.m_masterTaskQueue)来提交任务到Engine里。
在SubmitTask函数里面,我们可以看到把扔进来的任务付给当前引擎对应的任务的句子:
this.m_task = tasks.Dequeue();
然后我们查看管理引擎的主要类TaskEngine,可以看到里面同样有一个Consume函数,他会不断检测当前引擎对应的任务是否为空,不为空则开始执行任务。
因此,当SubmitTask函数里通过this.m_task = tasks.Dequeue()把任务赋给了当前引擎的任务后,就会开始任务执行的Task.Run()方法。
在Task.Run()方法里,根据多态的特性,调用this.OnRun()的时候,是调用了PrintLabelFormatTask类的OnRun()方法。在PrintLabelFormatTask类的OnRun()方法里就实现了把任务发送到打印机或者打印成文件的工作。

      BtPool管理任务队列和引擎池。TaskEngine对应的是一个引擎。TaskQueue为队列的相关操作的类。TaskEngines为TaskEngine的相关操作的类。

3、              大家可能看到网络浏览器的打印例子,里面写到了客户端的打印,这个客户端的打印其实也是在服务器上做,但服务器上做的只是把打印的结果输出为一个打印文件,然后把文件传送到客户端,客户端再通过JaveScript调用本地的打印机读取打印文件进行打印。这个要求服务器和客户端都装有同一个打印机驱动,而且客户端真正打印时使用的打印机驱动,要跟服务器上用来生成打印文件的打印机驱动一致。这里也有对这种方式的一些资料,仅供参考:<!--[endif]-->
1)WebLabelPrint客户端打印
 //设定打印到文件
labelFormat.PrintSetup.PrintToFile = true;
//设定打印机
      labelFormat.PrintSetup.PrinterName = compatibleServerPrinter;
      //设定打印机的License
labelFormat.PrintSetup.PrintToFileLicense = Request.Form.Get(_listPrinters.PrintLicenseUniqueID);
      string tempFullPath = (string)Application["TempFolderFullPath"];
//设定打印文件的路径
           labelFormat.PrintSetup.PrintToFileName = System.IO.Path.Combine(tempFullPath,Guid.NewGuid().ToString() + ".prn");
2)设定好以上东西后,就像正常的服务器打印一样,把任务发送到任务队列,当打印完成的时候,调用函数TaskPrint_Succeeded,里面将printTask.PrintCode读取出来,然后把打印码发送到本地的打印机进行打印。
3)ClientPrinting.js: PrintList.aspx页面里用到GetClientPrinters函数,完成客户端打印的主要是BarTenderPrintClient.js和WebLabelPrintSample.js文件。
4)BarTenderPrintClient.js文件里主要包含了一些针对打印机的操作,如获得打印机列表,匹配服务器和客户端的打印机,获得打印机的License,还有就是把打印码发送到对应的打印机上。
        5)WebLabelPrintSample.js文件主要包含了将客户端打印机列表填充到DropDownList里(PrintListControl.ascx),将客户端打印机列表填充到Table里(Printers.aspx)。<!--[endif]-->
二、ActiveX COM
在我呕心沥血看了好久的SDK,把他的源码反编译出来慢慢研究了几个星期后,老大说要在客户端进行打印~~顿时内牛满面~~我跟老大说起上面的那种先生成打印文件,再发送到客户端的打印方式,老大说不行,最好少跟服务器进行通信,因为他们的网络环境不怎样~~郁闷了~~在Senior的提醒下,开始对ActiveX进行研究~~主要的思路是想通过做出一个ActiveX插件,然后进入页面的时候在客户端进行安装,然后对客户端机器上的BarTender进行控制~~既然是用ActiveX,那就使用BarTender提供的最简单的COM就行了~

COM里面主要的就那么几个类,下面一一详细说明:<!--[endif]-->

1)           Application类:实际上代表一个BarTender的进程,当你新建一个此类的对象的时候,就会出现一个新的BarTender进程。
2)           Format类:实际上代表一个格式标签(BTW文件),使用Application. Formats.Open()方法可以打开并返回一个Format对象。这个类里面包含了打印设置,标签的参数设置等一系列的设置,很重要的一个类。
3)           NamedSubString类:管理标签文件里所有SubString的类。
4)           DataBase类:管理标签文件里设置的所有数据库链接的类。
5)      QueryPromts类:管理标签文件里面数据库查询参数的类。
<!--[endif]-->鉴于Format类是比较重要的类,这里再对他的相关属性和方法也做一下说明:<!--[endif]-->
1) Print方法:这个就是最常用的打印方法,里面可设置打印的任务名,是否等待打印完成,等待超时时间,打印过程输出的信息。
2) PrintOut方法:如果你需要在打印时出现打印设置对话框和状态框,你可以选择这个方法来实现。
3) Save方法:保存对Format的更改。
4) SetNamedSubStringValue方法:设置某个特定的SubString的值,这里就可以作为一个动态改变打印内容的方法。
5) SetPromt方法:跟SetNamedSubStringValue方法类似,不过他设置的是打印提示的值,某些标签通过设置可以在打印的时候弹出对话框,输入某些变量的值来改变打印内容,这个方法就是动态设置这些变量的。不过在集成中比较少用。
6) IdenticalCopiesOfLabel属性:这个是设置打印时要打印多少份相同的标签的,默认为标签设置。
7) NumberSerializedLabels属性:这个是序列化打印时使用的,当你的标签启动了序列化后,这个属性代表的就是打印的份数,譬如你的序列化初始数据是1,增量为1,NumberSerializedLabels设置为5,那么就会打印出1、2、3、4、5,五个标签出来。
8) Printer属性:指定要使用的打印机,默认为系统指定的默认打印机。
9)     PrintToFile属性:标示是马上用打印机打印出实物,还是生成一个打印文件。<!--[endif]-->
通过上面方法的解释,大家已经看到里面已经有几种动态控制打印内容的方式了,我在项目中使用了上面两种,一种是直接通过SetNamedSubStringValue方法去设置某些变量的值,然后进行打印,这个适合小量的打印,因为每次都要调用Application和Format对象来处理,所以打印100份就要调用一百次,效率低,但是可以灵活设置每次的打印内容;另外一种是使用序列化打印,这个的效率就高了,因为他是只调用一次把数据扔给BarTender,之后的都是BarTender根据序列化规则去生成打印内容,不过这个方式就欠缺灵活性,只适用于标签的内容是有一定的规律进行变化的大批量打印。
上面还提到了DataBase和QueryPromts类,这两个类是用在连接数据库的打印中的,这个是我用到的第三种动态控制打印内容的方法。主要思路是,在标签里设置好各项内容,这些内容都是对应数据库的某些字段,然后设置好查询条件,暴露一个或多个查询参数,然后在程序里通过QueryPromts类来设置这些查询参数来查询出不同的数据库内容,达到动态改变打印内容的目的。Format.Databases.QueryPrompts.GetQueryPrompt()可以特定的查询条件,然后通过设置Value属性来设置他的值,最后设置完所有查询条件后进行打印。
关于这几种动态控制打印内容的方法,都是要设计标签文件和程序相互配合的,比较不灵活,其实可以做成更好的动态配置方式的,不过老大说没必要,就放弃了。至于要是有朋友不了解标签文件的设计,我有时间会写一个文章来专门说标签文件的设计的。

<!--[endif]-->

三、集成
有了上面的介绍后,大家对BarTender提供的集成信息有了一定的了解了。我是采用了ActiveX COM的方式,而且我的是客户端打印,于是我也做了个伪ActiveX插件,为什么叫“伪”呢?因为他不是传统意义上的ActiveX,而是用C#编写的(悔恨当年没学C++),所以叫“伪”。关于制作伪ActiveX,网上有很好的教程,我这里就给个链接算了(http://www.cnblogs.com/homer/archive/2005/01/04/86473.html)。
         在做好ActiveX并确定部署好后,在网页上调用ActiveX插件就需要用到JavaScript了,大家在部署ActiveX的网页上,会有下面这样一句代码:
        <object id="BTDPrintClient" classid="clsid:{0750A7B0-CF1E-4EAD-8C73-E0C8F6D9E890}" codebase="CAB/BarTender_AX.cab"></object>
       这里也提醒一下,第二个属性的名字是classid,然后里面设置的字符串的开头那几个是clsid,是不同的,我当时就在这里没注意,部署了好久都不行。
       回到JavaScript的调用上来,在调用时,主要就是下面的代码:
printClient = new ActiveXObject("BTDPrintClient.PrintClient");
这里应该很好理解,就是创建BTDPrintClient这个object对象里面的PrintClient对象。完成这一句后,printClient就等于是一个PrintClient的对象了,你可以在JavaScript里面调用PrintClient的各种方法属性了,于是就可以控制本地的BarTender了。 
四、小结
做一个东西的集成,我觉得首先你是必须要去很了解这个要集成的软件,可以通过上网搜索资料,官方文档,最重要的还是软件自身的一些帮助文档和API文档,基本软件的信息都在里面了。而且这次做集成我还联系上了BarTender的亚太区这边的技术支持,也给我带来了不少帮助,虽然他们是要购买产品才能提供支持,但是初步的支持还是可以提供的,你只要跟他们说在用他们的试用版进行集成测试,看效果如何再决定要不要购买产品,哈哈~~引诱引诱~~
还有在做一个新的东西的时候,还是建议多动手吧,做些小Demo来验证一下想法,认真调试一下追踪问题。不动手是没办法可以很好的理解一样东西的,所以,做IT,累死了~~什么时候上天砸些钱给我啊?烧香去~~~

转载于:https://blog.51cto.com/yerik/611804

BarTender的集成小结相关推荐

  1. Bartender软件标签打印

    前段时间接到一个客户二次开发需求,在原有扫码出货系统中增加打印标签功能.之前标签客户是使用Bartender编辑后打印,由于是人工操作难免会出现错误,所以想与现有的出货系统集成.具体的想法是:通过Ba ...

  2. 分布式系统搭建:服务发现揭秘

    CAP理论 加州大学终身教授与著名计算机科学家Eric Allen Brewer在90年代末提出了CAP理论,理论断言任一个基于网络的分布式系统,最多只能满足"数据一致性".&qu ...

  3. python连接mysql用哪个模块_pymysql模块使用---Python连接MySQL数据库

    VS2010与水晶报表V13的打包集成小结 感谢孟子E章提供的技术咨询. 系统配置: Windows 7 + VS2010 , WinForm + DotNet4 + 水晶报表 这里说的打包集成,指的 ...

  4. The requirements of using provenance in e-Science experiments(论文阅读)

    目录 论文背景 论文贡献 关键字 起源体系结构 面向服务的架构 SOA Provence的起源 起源的思想 起源方面的初步研究 开发系统 小结 用例 生物学 用例一:内含子复杂性实验 用例二:候选基因 ...

  5. swift python混合开发_引用swift项目

    iOS - OC 与 Swift 互相操作 前言 在 Swift 语言中,我们可以使用 Objective-C.C 语言编写代码,我们可以导入任意用 Objective-C 写的 Cocoa 平台框架 ...

  6. 这回又来个 ionic2 的微信支付!(遇到一些莫名的BUG)

    目录 目录 ionic2实现微信支付前的准备工作 ionic2中的微信支付 ionic2中实现微信支付的参考代码 客户端APP 实现插件的封装 WechatPlugints 引入WechatPlugi ...

  7. 这回又来个 ionic2 的微信支付 (遇到一些莫名的BUG)

    目录 目录 ionic2实现微信支付前的准备工作 ionic2中的微信支付 ionic2中实现微信支付的参考代码 客户端APP 实现插件的封装 WechatPlugints 引入WechatPlugi ...

  8. 101种在家就能做的网上生意

    转载自 [http://baike.baidu.com/link?url=67Ertf8LNQ3LlAPeXgsp7e4jZUDSafwET5i0O3DPrBr6im5KLpEwLXvFpUivy-J ...

  9. Android微信支付遇到的坑

    文章是转载的,,因为看了这文章后感觉跟自己搞微信支付的过程很像,所以转下来收藏下相当于自己的经历 原文:http://www.bubuko.com/infodetail-1020413.html 今天 ...

最新文章

  1. ad20如何导入库_零基础小白自学Python,如何快速学会及掌握?
  2. c语言ctype中替换查找字符,c – std :: ctype是否总是按“C”语言环境对字符进行分类?...
  3. 一文详述Attention最新进展
  4. (转载)机器学习知识点(十七)Bagging与随机森林算法原理小结
  5. 看bilibili的财经博主,分析博主的频道
  6. c语言json映射,GitHub - xujun621/cson: 基于C语言的json数据映射解析库
  7. python 并列条形图_python – 如何绘制具有相同X坐标并排的条形图
  8. linux的进程栈和线程栈
  9. struct/class等内存字节对齐问题详解
  10. latex 常用学习/模板/公式输入网站合集
  11. 关于Lua的下载以及wlua、luac等文件的解释
  12. 第二十次CCF CSP认证考试经验
  13. win10无法防问其他计算机没有权限,win10系统访问磁盘共享没有权限的解决方案...
  14. win10输入法转win7模式
  15. python模块cpca修改源码支持国外地址解析
  16. 金三银四马上到了,找工作需要准备什么?
  17. 网新恒天php,网新恒天,为德邦快递插上数字化翅膀
  18. echarts可视化市级地图详细版(vue+element)
  19. 【转】entity、bo、vo、po、dto、pojo如何理解和区分?
  20. JAI LT-400CL相机设置

热门文章

  1. oracle中job无法正常运行,如何排查
  2. 百度App网络深度优化系列(一):DNS优化
  3. 基于Raspbian(树莓派)搭建web安全练习环境(一)
  4. gulp自己主动化任务脚本在HybridApp开发中的使用
  5. 程序员为什么值得写博客
  6. (转) mp4编码全介绍 (一)
  7. [交互设计工具/原型创作工具]Axure RP Pro 5.0新特性 破解版 注册码
  8. sql 异常除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。...
  9. linux_basics
  10. 堆——神奇的优先队列(上)