说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

VB应用程序中打印条形码的两种方法

HTML文档下载 WORD文档下载 PDF文档下载
VB应用程序中打印条形码的两种方法
(作者:四川 李佑民 )


  条形码作为一种机器可识别的图形,它能快速、准确地标识某种产品或商品,在许多数据库应用中起作很重要的作用,如超市收银、车站售票等场合。当某件物品上带有的条形码被条码扫描器正确解读后,将会得到该物品的唯一标识字符串,通过检索数据库我们就可以很容易知道它的一些其它属性并作相应处理。虽然在Internet上能找到许多免费和不免费的条形码打印控件,但是这些控件除了使用不方便外,还有一个最大的缺点:它们的打印输出不能和我们的程序共存在一个打印页面上,比如说在一个过程中,我们先向系统 Printer 中输出一些内容,然后再调用控件的条形码打印方法,最后打印的结果为两页!,如果现在我们要处理一张车票,上面不仅要打印条形码,还要有终点站和票价等信息,那么控件就变得不可用。对程序员来说,可能还是希望能了解条形码打印的原理,本文提出两种打印方法与同行们探讨。



一、直接利用有条形码打印功能的打印机

  有许多打印机能够直接打印条形码,但在 VB 中,我们在DOS时代熟悉的LPRINT语句已经不能再使用了,打印操作被Windows的Spool系统完全接管,输出是以“页”为单位,所有的打印输出都被Windows转换为图形发送给打印驱动程序。而要使打印机打印条形码就必须将对应的ESC序列直接发送给它,因此我们就要想办法避开Windows的Spool系统,也就是说再程序中不能使用Printer对象和Printers集合处理打印输出,在VB中要将ESC指令直接发送给打印机至少有三种方法,前两种方法是调用Windows API 函数:Escape()和SpoolFile(),第三种是最容易的方法:打开打印机端口进行二进制存取,我们主要考虑这种方法。

  即使在Windows时代,”LPT1:”和”PRN”仍然是可用的,下面我们先作一个试验:打开一个DOS窗口,在提示符下输入COPY CON LPT1:回车,然后随便输入一些字符,最后按F6键,打印机就开始工作了,它将打印出你输入的那些字符!下面的代码演示了直接将指令和字符发送给打印机:

Private Sub Command1_Click()

  Dim strOut As String

  StrOut = “这是直接发送到打印机端口的字符串”

  ‘ 打开打印机端口,其中的”LPT1:”可能需要根据你的打印机设置而改变

  Open “LPT1:” For Binary Access Write As #1

  ‘ 发送给打印机,注意语句的最后一个参数必须是变量

    Put #1, ,strOut

    ‘ 关闭打印机端口

    Close #1

End Sub

  各种打印机打印条形码的指令可能不同,比如将上面的变量 strOut赋值为:

  strOut = Chr(28) & “P” & Chr(5) & Chr(2) & Chr(3) & Chr(3) & Chr(6) & “012345”

  将在 AR2400 打印机上打印出内容为”012345”的 CODE39 格式的条形码。具体的打印控制指令请参考打印机手册。

  用这种方法的缺点:一是过份依赖打印机本身,而有条形码打印功能的打印机通常要比普通打印机昂贵,这会使构造应用系统不够经济;二是所有的打印输出都必须你自己处理,比如打印定位就很浪费时间。



二、利用画图方式输出到普通打印机

  条形码的编码规则不外乎是通过线条和线条间间隙的宽窄不同来表示二进制的1和0,只要我们了解了条形码的编码规则,完全可以用画图的方式在普通打印机上得到可以接受的效果。下面我们就使用最普遍的CODE39码进行讨论。

  CODE39码的编码规则是:

1、 每五条线表示一个字符;

2、 粗线表示1,细线表示0;

3、 线条间的间隙宽的表示1,窄的表示0;

4、 五条线加上它们之间的四条间隙就是九位二进制编码,而且这九位中必定有三位是1,所以称为39码;

5、 条形码的首尾各一个*标识开始和结束

  在我们的程序中,给常用的字符都进行编码,解读时先取线条粗细,再取间隙宽窄,如:



  上图中的字符*就可以解读为 001101000,字符3解读为 110000100

  下面就是我们给出的子过程:

注释: 将字符串 strBarCode 对应的条形码输出到缺省打印机

Private Sub PrintBarCode( _

  ByVal strBarCode As String, _

  Optional ByVal intXPos As Integer = 0, _

  Optional ByVal intYPos As Integer = 0, _

  Optional ByVal intPrintHeight As Integer = 10, _

  Optional ByVal bolPrintText As Boolean = True _

)

注释: 参数说明:

注释: strBarCode    - 要打印的条形码字符串

注释: intXPos, intYPos - 打印条形码的左上角坐标(缺省为(0,0),坐标刻度为:毫米)

注释: intHeight     - 打印高度(缺省为一厘米,坐标刻度为:毫米)

注释: bolPrintText   - 是否打印人工识别字符(缺省为true)



注释: "0"-"9","A-Z","-","%","$"和"*" 的条码编码格式,总共 40 个字符

Static strBarTable(39) As String

注释: 初始化条码编码格式表

  strBarTable(0) = "001100100"   注释: 0

  strBarTable(1) = "100010100"   注释: 1

  strBarTable(2) = "010010100"   注释: 2

  strBarTable(3) = "110000100"   注释: 3

  strBarTable(4) = "001010100"   注释: 4

  strBarTable(5) = "101000100"   注释: 5

  strBarTable(6) = "011000100"   注释: 6

  strBarTable(7) = "000110100"   注释: 7

  strBarTable(8) = "100100100"   注释: 8

  strBarTable(9) = "010100100"   注释: 9

  strBarTable(10) = "100010010"  注释: A

  strBarTable(11) = "010010010"  注释: B

  strBarTable(12) = "110000010"  注释: C

  strBarTable(13) = "001010010"  注释: D

  strBarTable(14) = "101000010"  注释: E

  strBarTable(15) = "011000010"  注释: F

  strBarTable(16) = "000110010"  注释: G

  strBarTable(17) = "100100010"  注释: H

  strBarTable(18) = "010100010"  注释: I

  strBarTable(19) = "001100010"  注释: J

  strBarTable(20) = "100010001"  注释: K

  strBarTable(21) = "010010001"  注释: L

  strBarTable(22) = "110000001"  注释: M

  strBarTable(23) = "001010001"  注释: N

  strBarTable(24) = "101000001"  注释: O

  strBarTable(25) = "011000001"  注释: P

  strBarTable(26) = "000110001"  注释: Q

  strBarTable(27) = "100100001"  注释: R

  strBarTable(28) = "010100001"  注释: S

  strBarTable(29) = "001100001"  注释: T

  strBarTable(30) = "100011000"  注释: U

  strBarTable(31) = "010011000"  注释: V

  strBarTable(32) = "110001000"  注释: W

  strBarTable(33) = "001011000"  注释: X

  strBarTable(34) = "101001000"  注释: Y

  strBarTable(35) = "011001000"  注释: Z

  strBarTable(36) = "000111000"  注释: -

  strBarTable(37) = "100101000"  注释: %

  strBarTable(38) = "010101000"  注释: $

  strBarTable(39) = "001101000"  注释: *



  If strBarCode = "" Then Exit Sub 注释: 不打印空串



  注释: 保存打印机 ScaleMode

  Dim intOldScaleMode As ScaleModeConstants

  intOldScaleMode = Printer.ScaleMode

  注释: 保存打印机 DrawWidth

  Dim intOldDrawWidth As Integer

  intOldDrawWidth = Printer.DrawWidth

  注释: 保存打印机 Font

  Dim fntOldFont As StdFont

  Set fntOldFont = Printer.Font

  

  Printer.ScaleMode = vbTwips 注释: 设置打印用的坐标刻度为缇(twip=1)

  Printer.DrawWidth = 1   注释: 线宽为 1

  Printer.FontName = "宋体" 注释: 打印在条码下方字符的字体和大小

  Printer.FontSize = 10

  

  Dim strBC As String     注释: 要打印的条码字符串

  strBC = Ucase(strBarCode)

  注释: 将以毫米表示的 X 坐标转换为以缇表示

  Dim x As Integer

  x = Printer.ScaleX(intXPos, vbMillimeters, vbTwips)

  注释: 将以毫米表示的 Y 坐标转换为以缇表示

  Dim y As Integer

  y = Printer.ScaleY(intYPos, vbMillimeters, vbTwips)

  注释: 将以毫米表示的高度转换为以缇表示

  Dim intHeight As Integer

  intHeight = Printer.ScaleY(intPrintHeight, vbMillimeters, vbTwips)

  

  注释: 是否在条形码下方打印人工识别字符

  If bolPrintText = True Then

    注释: 条码打印高度要减去下面的字符显示高度

    intHeight = intHeight - Printer.TextHeight(strBC)

  End If

  

  Const intWidthCU As Integer = 30 注释: 粗线和宽间隙宽度

  Const intWidthXI As Integer = 10 注释: 细线和窄间隙宽度

  Dim intIndex As Integer      注释: 当前处理的字符串索引

  Dim i As Integer, j As Integer, k As Integer  注释: 循环控制变量



  注释: 添加起始字符

  If Left(strBC, 1) <> "*" Then

    strBC = "*" & strBC

  End If

  注释: 添加结束字符

  If Right(strBC, 1) <> "*" Then

    strBC = strBC & "*"

  End If

  

  注释: 循环处理每个要显示的条码字符

  For i = 1 To Len(strBC)

    注释: 确定当前字符在 strBarTable 中的索引

    Select Case Mid(strBC, i, 1)

    Case "*"

      intIndex = 39

    Case "$"

      intIndex = 38

    Case "%"

      intIndex = 37

    Case "-"

      intIndex = 36

    Case "0" To "9"

      intIndex = CInt(Mid(strBC, i, 1))

    Case "A" To "Z"

      intIndex = Asc(Mid(strBC, i, 1)) - Asc("A") + 10

    Case Else

      MsgBox "要打印的条形码字符串中包含无效字符!当前版本只支持字符 注释:0注释:-注释:9注释:,注释:A注释:-注释:Z注释:,注释:-注释:,注释:%注释:,注释:$注释:和注释:*注释:"

    End Select

    

    注释: 是否在条形码下方打印人工识别字符

    If bolPrintText = True Then

      Printer.CurrentX = x

      Printer.CurrentY = y + intHeight

      Printer.Print Mid(strBC, i, 1)

    End If



    For j = 1 To 5

      注释: 画细线

      If Mid(strBarTable(intIndex), j, 1) = "0" Then

        For k = 0 To intWidthXI - 1

          Printer.Line (x + k, y)-Step(0, intHeight)

        Next k

        x = x + intWidthXI

      注释: 画宽线

      Else

        For k = 0 To intWidthCU - 1

          Printer.Line (x + k, y)-Step(0, intHeight)

        Next k

        x = x + intWidthCU

      End If



      注释: 每个字符条码之间为窄间隙

      If j = 5 Then

        x = x + intWidthXI * 3

        Exit For

      End If

      

      注释: 窄间隙

      If Mid(strBarTable(intIndex), j + 5, 1) = "0" Then

        x = x + intWidthXI * 3

      注释: 宽间隙

      Else

        x = x + intWidthCU * 2

      End If

    Next j

  Next i



  注释: 恢复打印机 ScaleMode

  Printer.ScaleMode = intOldScaleMode

  注释: 恢复打印机 DrawWidth

  Printer.DrawWidth = intOldDrawWidth

  注释: 恢复打印机 Font

  Set Printer.Font = fntOldFont

End Sub



  最理想的情况是将它做成一个控件,在控件中提供一个打印方法,该方法实现与上

  那个过程大致相同,只是不能在控件中直接使用VB的Printer对象,否则VB会将你在控件中的打印输出处理为一个单独的页面,而是应该将Printer.hDc传给它,通过调用那些需要指定 HDC 的Windows API函数实现与容器的打印输出在一个页面上,比如我们可以这样定义这个控件的打印方法:

注释: PrintIt 方法将对应的条形码输出到缺省打印机

Public Sub PrintIt(ByVal PrintDC As Long, _

   Optional ByVal intXPos As Integer = 0, _

  Optional ByVal intYPos As Integer = 0, _

   Optional ByVal intPrintHeight As Integer = 10)

  既然不能使用Printer对象,那么画线和输出文字也不能使用Printer对象的Line和Print方法,在我们的程序中至少要申明以下三个Windows API函数:

‘ 移动画笔的位置

Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, lpPoint As POINTAPI) As Long

‘ 从画笔的当前位置到(x,y)画一条线

Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long

‘ 在(x,y)处输出一个字符串

Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As String, ByVal nCount As Long) As Long

‘ MoveToEx() 函数需要的参数

Private Type POINTAPI

  xp As Long

  yp As Long

End Type

Dim papi As POINTAPI

  画线操作为(原来的Printer.Line函数):

MoveToEx PrintDC, x + k, y, papi

LineTo PrintDC, x + k, y + intHeight + 1

  打印字符为(原来的Printer.Print函数):

TextOut PrintDC, x, y + intHeight, Mid(strBC, i + 1, 1), 1
专访:InMobi全球CEO Naveen Tewari MDCC 2013精彩专题论坛之产品与设计 中关村大型IT人才招聘会举办 现场火爆 [简讯]新代码编辑器Lime发布 号称Sublime Text的开源实现 从真实案例出发:如何在协作开发中避免误解! Google工程师谈程序员的自我修养 依然很强大:微软第一财季净利润同比增17% MDCC 2013垂直行业应用与O2O专题论坛透露劲爆话题 专访豌豆荚产品设计团队:Design Hackathon是绞尽脑汁之后的海阔天空 首日报名爆满超300 向C++大师Lippman提问征集 做华为合伙人:华为开发者联盟沙龙(北京站)即将开幕 Windows XP发行12周年 我仍年轻而你已垂暮 2013浏览器市场份额:Chrome领衔,Firefox、IE相去甚远 人人网陈弢:从RecSys2013看大数据和移动给推荐系统带来的挑战 继续紧逼Oracle:在占领谷歌等公司之后,MariaDB迈向企业端 移动周报:十款最实用的Android UI设计工具 阿里巴巴CTO王坚:开发者精神是云计算与移动互联网的“信仰” 黑客老鹰:安全软件同样需要用户体验 六届中国大数据技术大会PPT精粹(二) 专访百度蒋凡:从RecSys2013大会看推荐系统发展新趋势 Hike副总裁杜中强:携手阿里云OS,拥抱云时代 玩蟹科技CEO叶凯:手游和云计算的合作相得益彰 倒计时20天!金玩奖各大奖项花落谁家由你主宰 宅男程序员福利:来自纽约的28位智慧与美貌并存的IT女神 创季度记录:苹果发布第四季财报 iPhone仍是苹果商业心脏 在破晓中行走:一位盲人开发的盲人应用 腾讯云俱乐部成都站——云时代手游开发:用数据说话 首届微App峰会将在MDCC2013上举行 微信易信百度新浪等平台开发商云集 TUP Masters第七期:C++大师Lippman论编程新范式Hugo OpenCL用于13个微型计算机领域的经典案例 从测试数据来看Node.js和Java EE的性能区别 在dos下,如何用汇编语句获知XXX盘符是否为网络盘或本地盘或substed盘??? 如何实现字符串种的准确查询! 灰头土脸的问 F7 & F8 区别到底是什么? 我看着都是单步.... 如何在 windows下 破解 写保护卡? VC+ADO,怎么实现把*.DBF表导入SQLServer2k里。 一个关于库文件的问题 我在用VB编数据库SQL SERVER,想实现数据库中关键表在本地磁盘中备份,通过代码应该怎样实现 谁想与我交换主页链接 一个程序编译通过后,我把paradox数据表的某一字段由N型改为了A型,结果运行时出错,应该怎么做呢? 如何用存储过程将一个查询的结果存为本地的一个XML文件? 有人知道.DUL文件是什么东西,有什么用,怎么创建? 如何把richtext.text的内容发到直接激活的word文档中?(在线等待) 高人指点,高人救命,我急。这是我唯一的办法了。 C++中为什么析构函数可以是虚函数,而构造函数不可以是虚函数? 100分求救:谁有webeasymail的解密版本或是能用的注册机??? 寻求C++参考书 高分问一个简单问题,什么叫“RAM驱动器”? 关于运算符重载的问题,请高手进来看看 如何把unsigned long型的对方IP地址,设在ClientSocket的IP中 为什么打开防火墙后,别人不能浏览自己的主页了? 钩子函数 请问如何唤醒机器? 关于ADOQUERY的问题?? 为什么打开防火墙后,别人不能浏览自己的主页了? ■■■征集顶级域名■■■ 谁知道在WIN2000有没有象WIN98中的WINPOPU发送信息的文件,若有,文件名为什么? 云南的程序员考试者看过来!!!一起来交流一下吧!!! 为什么打开防火墙后,别人不能浏览自己的主页了? 请你帮助! 谁知道在WIN2000有没有象WIN98中的WINPOPU发送信息的文件,若有,文件名为什么? 请教pnm和rtsp协议?请问哪儿有相关技术资料下载?谢谢! VC.NET那个变态的属性太难用了!!!我怎么死活都找不到我定义的消息??? 你们遇没遇到在builder中显示 link error提示的?? 请教pnm和rtsp协议?请问哪儿有相关技术资料下载?谢谢! 为什么在form1的paint事件中加入"form1.refresh语句后,在不做任何动作的情况下,事件会连续发生???你们有这种现象吗? 数据表格数据的块粘贴,如何实现? 网络病毒!急救! SOS 救命!!!!!! 为什么打开防火墙后,别人不能浏览自己的主页了? 急,判断某个记录是否为空的语句怎么写???除了record="" ,还有一个 jrun下如何配servlet,急急急 一个简单的问题,有劳各位了! 有一个EXE文件的图标很好看,如何把它保存下来? 超大整数相乘 急,判断某个记录是否为空的语句怎么写???除了record="" ,还有一个 请大家提供一部最精典的武侠小说,我最近特无聊,想看! 关于表空间的菜问题 一个简单的问题 一个最简单的CSocket问题。(请指出借在哪里) 我建好了一个RICH EDIT控件,怎么把一个文本文件的内容输入到它里面去啊??? 在造纸时,抄纸用的网,网孔是多少目的? this man looks like old句子中错误的改正 特仑苏有机奶咋样上周2010年10月31日在超市买了一箱特仑苏有机奶,68元,12小盒.给老婆喝 她怀孕三个多月了,但她同事说 特仑苏有致癌物质,我在网上查了 都是2009年的事了.有机奶有化学成份吗 关于抄纸请问 抄纸 具体是怎样道工序?都要用到哪些助剂? It's black.It look like a man.是什么动物?快. 特仑苏一共有几种牛奶? 造纸术 怎样抄纸快 like black有劳 柱箍筋表示为C10-100/200(C12-100)括号里表示啥意思?柱箍筋表示为C10-100/200(C12-100)括号里表示啥意思 雪下得真大呀!改为排比句 Look!The black cat_____a black hat over thereA looks like B looks after C looks over D looks into选出来的说一下理由···明天老师的正确答案出来我会再加分 Dave has a basketball【改为一般疑问句】 she is playing volleyball.的一般疑问句 英语下面的句子变一般疑问句是否让has还原 she has a dog He has a volleyball 改为一般疑问句 做回答 孕妇喝特仑苏有机奶好吗? she has a dog她有一只狗 Sandra has a volleyball改成特殊疑问句 题:甲,乙两辆汽车分别从A,B两地相向而行,速度比是7:11.相遇后继续行驶,分别到达AB两地,立即返回,当第二次相遇时,甲车距B地80千米.A,B两地相距多少千米?1,他们走的时间一样吗?3, she has (get)a dogshe has (get)a dog添get的适当形式 谁改进了造纸术? 有什么排比句 She has found her lost dog 改为一般疑问句 造纸术发展顺序 是从什么到什么再到什么就是那种从印刷术—印章和研牌—==那种的呀 蜗牛和鼻涕虫有什么区别? 乌龟有什么天敌 造纸术在各大洲的传播顺序是什么? 蜗牛与鼻涕虫的区别 乌龟的天敌是什么? 蔡伦是怎样改进造纸术的?制做步骤是什么? 化肥厂计划生产化肥350吨,实际比计划多生产70吨.(1)实际完成了计划的百分之几?(2)计划产量比实际少 乌龟的天敌是谁 古代造纸术的最关键的步骤是哪部? 六一班,上学期男生与女生的人数比是13:12,这学期又转来两名女生,这时女生人数正好占全班人数的50%,这个班原有女生多少人? 乌龟有怎样避免天敌 猜动物a black and white animal.it sleeps during the day. she likes piaying the guitar?yes ,she 改为一般疑问句,并作肯定回答 乌龟在水里有天敌吗? 是a black animal 还是an?中间有一个不是原因音节开头的要怎么用定冠词? 水蛭,鼻涕虫和蜗牛有什么区别告诉我他们的区别和相同点 蛞蝓是什么?蛞蝓就是鼻涕虫! 英语测试This animal looks like a bear but not a bear with a white and black coat. 鼻涕虫与蜗牛1.谁跑得快2.谁更会保护自己3.谁更容易怕热.说说原因 鼻涕虫是什么? 大熊猫是一种漂亮的、黑白相间的动物.Giant pandas are a beautiful ,black-and-white animal.Giant pandas are beautiful ,black-and-white animals.两种都对吗? 鼻涕虫是不是蜗牛?我在树上看到的就是鼻涕虫 现代用什么原料造纸,基本工序有哪些? 什么叫做鼻涕虫? 蜗牛和鼻涕虫的最大区别是什么?A.蜗牛有钱一些 B.鼻涕虫比蜗牛怕热些 C.蜗牛爬的慢一些 D.鼻涕虫身字长一些 E.以上都对 蛞蝓是什么东西? 动物歇后语尾巴长不了 鼻涕虫是蜗牛变的吗?我今天看到一个鼻涕虫,好像蜗牛!···所以我觉得鼻涕虫像蜗牛.可是,鼻涕虫就是蜗牛吗? 1 造纸原料.2 造纸对环境的影响.3 纸与森林的关系.4 节约纸与保护环境的关系.(任意一个都可以) 世界上最小的蛞蝓叫什么我是问这种生物的名字。还有``必须是BAIDU百科里面有的= =...= 把过程抄在纸 造纸要经过那几种步骤?主要的材料和器材有哪些? =IF(C10100%,C10,0)中,这个函数中""表示什么意思?但是太专业了,看不懂,能帮我解释一下这个具体的IF函数的意思吗?我由于看不懂这个符号,就看不懂这个函数的意思? 造纸术中抄纸用的工具是什么 The little m____ looks like a man 组合c2,1*c10,5+c2,2*c10,4=714种 这个能不能解释的详细一些,要小学4年级听得懂的方法
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘