PB程序使用串口打印

享有的鱼 2008-01-26 09:27:55
我现在帮朋友做了个小程序,他电脑上有个并口的打印机了,想在这个小程序中使用串口打印,这样就不用来回换纸了,希望高手指点!最好能给出使用的详细说明
...全文
492 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
dawugui 2008-01-26
  • 打赏
  • 举报
回复
如何在PB中定制打印页长 

  在使用连续纸打印数据窗口的情况下,需要定制打印的页长,以保证打印机走纸正确,不用人工干预,实现连续打印。在PB中须调用外部函数来自定义纸张长度,比较繁琐。本文介绍一种直接对打印机的控制方法,简单实现对页长的设定。
  一、预备知识
  计算机与打印机的通讯使用ASCII码进行,其中标准ASCII码包括可打印字符及非打印字符(控制码),打印机使用控制码来定制打印机。大多数打印机指令使用控制码escape作为其指令序列的第一个序列码。下面介绍本文用到的几个指令码序列:
  设置换行量(行距)1/8 英寸
  ASCII码 ESC 0
  十进制码 27 48
  设置以行为单位的页长
  ASCII码 ESC C n
  十进制码 27 67 n
  其中n 为每页行数范围(1-127)
  二、PB中控制码的传送及定制页长的实现
  在PB中通过函数Printsend(printjobnumber,string,{zerochar})来实现向打印机发送控制码。各参数定义如下:
  printjobnumber: 由printjob()函数返回的打印作业号;
  string: 控制字符串,使用ASCII码;
  zerochar: 用来替代string中的数字0;
  由于字符串中,0终止字符串,如果string 中包含0,则需利用其他字符来表示0,参数zerochar即为此用途而设,当PB发送控制字符串给打印机时,把替代的字符zerochar转化为0。
  下面是具体的完成定制页长打印数据窗口的程序(定制页长为2.75英寸):
  long ll_job
  dw_print.reset()
  ll_job = printopen()
  if ll_job = -1 then
    messagebox(gs_title,"打印机未准备好")
    return
  end if
  //定制行距1/8英寸
  PrintSend(ll_job, CHAR(27)+CHAR(48))
  //设定页长22行
  PrintSend(ll_job, CHAR(27)+CHAR(67)+CHAR(22))
  printdatawindow(ll_job,dw_print)
  printclose(ll_job)

dawugui 2008-01-26
  • 打赏
  • 举报
回复
PB中数据窗口的精确页面打印技术 

  原著:国永杰、张颖,中国计算机世界。

  摘要本文详细介绍了PowerBuilder中数据窗口打印输出技术,并给出了一个通用的数据窗口打印控制程序。
  关键词:PowerBuilder DataWindow Print

  1、引言
  自PowerBuild问世以来,以其简洁高效的集成开发环境、强大的数据窗口技术、(几乎)无所不能的数据库访问能力,越来越受到编程人员的青睐。据Sybase自己的统计,目前全球有60万程序员和系统分析人员在使用他们的Powerbuilder和S-designer,进行各种类型的应用程序开发。最新发布的PowerBuilder6.0族系列开发工具,直接支持ActiveX技术、ServerPush技术,对分布式计算模型的定义更加明确,实现更为简便,并可以利用数据窗口直接生成HTML格式文件,等等。所以,PowerBuilder已成为C/S模式应用和基于InterNet模式应用的主要开发工具之一。
  数据窗口(DataWindow)是PowerBuilder的专利,也是PowerBuilder应用程序的核心和精华所在.PowerBuilder通过丰富的属性和函数来控制数据窗口的显示和数据操纵,但对数据窗口的打印支持似乎过于简单,只有一个Print()窗口函 数和一个PrintDataWindowPowerScript函数,并且这两个函数的功能几乎都是一样,都只简单地将选定数据窗口原样送入打印队列,本身不具备页面控制功能。为此很多程序员抱怨这是PowerBuilder的一个缺陷,其实,PowerBuilder对打印功能的支持一样十分周到全面,只不过应用场合不同,需要用户自行加以选择。
  以下是对PowerBuilder打印控制功能的详尽分析,并介绍一个实用的数据窗口页面控制程序。

  2、Powerbuilder实现动态页面控制的途径
  PowerBuilder数据窗口有一对函数Describe 和Modify,用于动态描述和修改数据窗口结构,与其它相关函数结合可以完成动态生成数据窗口、任意改变数据窗口显示方式、修改打印属性等。这两个函数是控制与修改数据窗口的核心函数,其使用方法如下:
  1)、Describe获取数据窗口特定属性值
  语法:dwcontrol.Describe(propertylist)
  参数:dwcontrol数据窗口(或datastore)控 件名。
  propertylist用字符串表示的数据窗口属性。
  返回值:返回一个表示属性的字符串。
  数据窗口属性值也可以用dwcontrol.object.Datawindow.property来完成直接取得。
  2)、Modify修改数据窗口特定属性
  语法:dwcontrol.Modify(modstring)
  参数:dwcontroldwcontrol数据窗口(或datastore)控 件名。
  modstring用字符串表示的数据窗口属性。
  返回值:如果函数执行成功返回“1”。
  与Describe类似, 修改数 据窗口 属性可 以用:
  dwcontrol.object.Datawindow.property=value直 接赋值。
  3)、与打 印有关 的数据 窗口属 性
  数据窗口属性中与打印有关的有24个,其中实现打印页面控制的几个属性是:
  Copies:打印份数。
  Filename:如果不为空,表示输出到文件的文件名。
  Orientation:打印方向1=横向,2=纵 向
  Page.Range:输出页范围,要打印1,2,和5到10 页,输入: "1,2,5-10"。Page.RangeInclude:本
次打印范围,0=全部,1= 偶数页,2= 奇数页。Paper.Size:纸张大小。
  Scale:打印比例。
  程序中利用Modify函数设置好这些属性后,即可实现动态修改数据窗口的目的,再调用datawindow.print()函数,完成最后的打印输出。

  一个通用Datawindow打印控制程序
  将数据窗口中的报表在打印机上输出是PowerBuilder应用程序开发过程中必不可少的功能,作为例子,这里提供一个使用上述方法研制的通用打印控制窗口,用以替代Prompt属性所提供的Print窗口,实现汉化界面,并且可被自行修改扩充。为了书写简单,程序中采用直接赋值的方式修改属性。
  实例变量:
  datawindowdw_print
  stringprintername,name,port
  窗口open事件脚本:
  dw_print=Message.PowerObjectParm
  printername=dw_print.Object.Datawindow.Printer
  name=left(printername,pos(printername,"on")-1)
  port=right(printername,len(printername)-pos(printername,"on")-1)
  plb_printername.additem(name,1)
  st_portname.text=port
  "设置" 按钮clicked事件脚本
  Integercode
  Code=printSetup()
  If code = 1 then
    printername=dw_print.Object.Datawindow.Printer
    name=left(printername,pos(printername,"on")-1)
    port=right(printername,len(printername)-pos(printername,"on")-1)
    plb_printername.additem(name,1)
    st_portname.text=port
  endif

  打印范围组中"全部"选择钮clicked事件脚本
  dw_print.object.DataWindow.Print.Range=''
  sle_1.enabled=false
  sle_2.enabled=false
  sle_3.enabled=false
  "页数"栏后sle_2单行文本编辑框Modified事件脚本
  dw_print.object.DataWindow.Print.Page.Range=sle_1.text+"-"+sle_2.text
  "自定义"栏后sle_3单行文本编辑框Modified事件脚本
  dw_print.object.DataWindow.Print.Page.Range=sle_3.text
  打印份数组中份数单行文本编辑框Modified事件脚本
  dw_print.Object.DataWindow.Print.Copies=integer(this.text)
  "全部"选择钮Cliecked事件脚本
  dw_print.Object.DataWindow.Print.Page.Rangeinclude = 0
  "奇数"选择钮Cliecked事件脚本
  dw_print.Object.DataWindow.Print.Page.Rangeinclude = 1
  "偶数"选择钮Cliecked事件脚本
  dw_print.Object.DataWindow.Print.Page.Rangeinclude = 2
  "确认"命令按钮Clicked事件脚本
  longjob
  if IsValid(dw_print) then
    job = PrintOpen()
    PrintDataWindow(job,dw_print)
    PrintClose(job)
    close(parent)
  endif
  "取消"命令按钮Clicked事件脚本
  close(parent)

  窗口调用方法:在其它带有数据窗口的窗口中,使用OpenWithParm(w_print_set,dwname)即可,其中w_print_set为本窗口名,dwname为要打印的数据窗口。该程序是一个通用打印控制程序,可在任何版本的PowerBuilder应用中使用。

dawugui 2008-01-26
  • 打赏
  • 举报
回复
设计串口通讯程序 

  PB是一种面向对象的、具有可视图形界面的、快速的交互式开发工具,它通过不同数据库采用各自的专用接口或通过ODBC接口,同时支持多种关系数据库系统、支持多文档界面(MDI)、对象嵌入与链接(OLE)、动态数据交换(DDE)。利用其独特的数据窗口对象,无须编写SQL语句,便可直接对数据库进行查询、修改、插入、删除、浏览、打印,以多种文件格式打开和存储数据,因此深受广大用户的欢迎。在实际应用过程中经常遇到PowerBuilder与其它设备通过串口进行通讯的程序设计如IC卡应用系统中需通过串口与IC卡读写器进行通讯;在控制系统中,需通过串口与下位机进行通讯。下面介绍PowerBuilder5.0中常用的两种串口通讯设计方法。

一、调用Windows SDK函数进行串口通讯
1、Windows SDK函数介绍
OpenComm
int OpenComm(LpszDevControl,
CbInQueue,cbOutQueue)
LPCSTR lpszdevcontro
l 设备控制信息的地址
UINT CbInQueue
接受队列的大小(以字节为单位)
UINT cbOutQueue
发送队列的大小
返回:如调用成功,返回值标示此打开的设备否则其返回值小于0
·CloseComm
Int CloseComm(idComDev)
Int idComDey 要关闭的设备
返回值:调用成功返回0,否则返回负值
·WriteComm
int WriteComm(idComDev,lpvBuf,cbWrite)
int idComDev 通讯设备标示符
const void FAR * lpvBuf 数据缓存区地址
int ,cbWrite 要写的长度
返回值:如果成功返回所写的字节数,否则返回值小于0
·ReadComm
Int ReadComm(idComDev,lpvBuf,cbRead)
int idComDev 通讯设备标示符
const void FAR * lpvBuf 数据缓存区地址
int cbRead 要读的字节数
返回值:如果成功返回所读的字节数,否则返回值小于0
·FlushComm
Int FluseComm(idComDev,fnQueue)
Int idComDev 通讯设备标示符
Int fnQueue 要刷新的队列
返回值:成功时返回0,否则返回为负

2、示例:
  图一(略)为一人事管理系统中的查询窗口。如果想与被查询人拨打电话,可输入该人姓名,在输入过程中,数据窗口会显示满足要求的所有人姓名,双击该行即将该人电话号码显示于单行编辑窗内,然后按“拨号”按钮即可。

程序设计如下:
在窗口设计菜单中选取:Declare菜单?Declare External Function 输入:
Function int OpenComm(String Comm,
Uint Inqueue,Uint Outqueue)Library
“USER.EXE”
Function int CloseComm(int lpt)Library
“USER.EXE”
Function int WriteComm(int lpt,String
buf,int Size) Library “USER.EXE”
Function int FlushComm(int lpt,
int no_que)Library “USER.EXE”

“拨号”按钮的”Clicked” 事件编程如下:
int ret
String port_2,ph_code
port_2=”Com2”
//取单行编辑框内容,并用atdt拨号
ph_code=”atdt”+sle_code+”~r~n”
//打开串口
ret=OpenComm(port_2,128,128)
//拨号开始
FlushComm(ret,0)
FlushComm(ret,1)
WriteComm(ret,ph_code,len(ph_code))
WriteComm(ret,”~r~n”,2)
CloseComm(ret)

二、 利用Microsoft公司提供的通讯控件
  利用Microsoft公司提供的通讯控件(Mscomm.vbx,用于16位通讯程序、Mscomm32.ocx用于开发32位通讯程序)可方便实现串口通讯。
1、常用属性
CommPort:设置或返回串行端口号,缺省为1。
Setting:设置或返回串行端的波特率、奇偶校验位、数据位数、停止位。缺省值为"9600,N,8,1"。
PortOpen:设置它为True则打开端口,设置它为False则关闭端口。
InBufferSize:设置或返回接收缓冲区的大小,缺省为1024 字 节。
InBufferCount:返回接收缓冲区内的等代读取的字节个数,设属性为0清除接收缓冲区。
OutBufferSize:设置或返回发送缓冲区,缺省为512字节。
OutBufferCounter:返回发送缓冲区内等待发送的字符数,可用0来清空缓冲区。
Output:向发送缓冲区传送数据
RThreshold: 该属性确定当接收缓冲区内字节个数达或超过该值后就产生代码为ComEventReceive的OnComm事件,设置位0,则不产生OnComm事件。
CommEvent:有通讯错误或事件发生时产生OnComm事件,CommEvent事件的值可以用来确定引发OnComm事件的具体的错误或事件常用的有以下几种(更详
细的资料可参考MSComm控件帮助文件)
ComEventbreak:接受到中断信号
ComEventFrame:硬件检测到帧错误。
ComEventRxOver:接收缓冲区溢出。
ComEventTxFull:发送缓冲区溢出。
ComEventReceive:接受到规定的字符数。
InputLen:设置或返回接收缓冲区内用Input读入的个数。若取0,则读取整个缓冲区的内容。
Input:返回并删除接受缓冲区的数据。

2、 示例:
  下面举一接收程序示例:制作一通讯接收窗口,选择菜单Controls→OLE→Insert Control→Microsoft Communications Control,在窗口中出现通信控件图标单击鼠标右键,选择OCX Properties设置常用属性,也可在程序中进行设置窗口的Open事件程序如下
ole_1.object.CommPort=2
ole_1.object.Settings="9600,N,8,1"
ole_1.object.PortOpen=ture
ole_1.object.Rthreshold=10
ole_1.object..Inputlen=0
.
.
通信控件的oncomm事件的程序如下
choose case ole_1.object.CommEvent
case comEventBreak //接收到中断信号
case comEventCDTO //处理CD超时
.
.
.
case comEvReceive
sle_1.text=ole_1.object.Input
.
.
end choose

以上是一个基本的例子,在实际应用过程中应根据不同的情况进行不同的设计,如波特率、帧格式等。
总之,利用以上方法可以方便的在PowerBuilder中进行串口通讯,并对接收的数据利用PowerBuilder进行数据处理。

dawugui 2008-01-26
  • 打赏
  • 举报
回复
PB下从串口通信获取程控交换机计费数据的API调用 

我是通过调用API实现的: 如你用的是二进制的,请把缓冲区改成BLOB型的。
首先定义外部函数:
Function Boolean CloseHandle(ulong hObject ) Library "kernel32.dll"
FUNCTION boolean ReadFile(ulong fhand,
& ref string lpbuffer,
& ulong numbyte,
& ref ulong bytesread,
& ulong lpover) LIBRARY "kernel32.dll"
FUNCTION ulong CreateFileA(ref string fname,
& ulong f_access,
& ulong f_share,
& ulong f_sec,
& ulong f_create,
& ulong f_flag,
& ulong f_attrib) LIBRARY "kernel32.dll"
Function Boolean WriteFile(uLong handle,
& ref string lpbuffer,
& ulong numbytes,
& ref ulong bytesread,
& ulong lpOverLaped) Library "Kernel32.dll"
Function Boolean GetCommProperties(ulong hFile,
& ref COMMPROP lpCommProp ) Library "Kernel32.dll"
Function Boolean BuildCommDCBA(ref string lpDef,
& ref DCB lpDCB ) Library "Kernel32.dll"
Function Boolean SetCommState(ulong hCommDev,
& ref DCB lpdcb ) Library "Kernel32.dll"
Function Boolean GetCommState(ulong hCommDev,
& ref DCB lpdcb ) Library "Kernel32.dll"
Function ulong GetLastError() Library "Kernel32.dll"
Function Boolean SetCommTimeouts(ulong hCommDev,
& ref COMMTIMEOUTS lpctmo ) Library "Kernel32.dll"
Function Boolean PurgeComm(ulong hCommDev,
& ulong fdwAction ) Library "Kernel32.dll"
实例变量定义:
ulong iu_file
string is_buffer//数据缓冲
string is_valid_num = "123" //有效数据
第二是初始设置
string ls_com,ls_commset
dcb lst_dcb
ls_com = "COM1" //
ib_reading = true //打开串口
iu_file = CreateFileA(ls_com,3221225472,0,0,3,128,0)
if (iu_file < 0) then
messagebox("错误","无法打开" + ls_com + " #" + string(getlasterror ( )),StopSign!)
end if //初始化DCB
ls_commset = "4800,N,8,1"
if (Not BuildCommDcbA ( ls_commset, lst_dcb )) then
messagebox("错误","无法创建DCB" + " #" + string(getlasterror ( )),StopSign!)
end if
//设置串口
if (Not setcommstate ( iu_file, lst_dcb )) then
messagebox("错误","无法设置串口"+ ls_com + " #" + string(getlasterror ( )),StopSign!)

end if
//设置超时
commtimeouts lst_to lst_to.readintervaltimeout = 4294967295 //MAXDWORD //
lst_to.readtotaltimeoutconstant = 60000 //
lst_to.readtotaltimeoutmultiplier = 10
SetCommTimeouts(iu_file, lst_to)
第三步:读或写(例子中的是读,写可用writefile)
ulong lu_bytesread, lu_numbytes
string ls_buff
ulong lstr_locstruct //注意!这是ULONG 而不是STRUCT
ls_buff = space(100)
setnull(lstr_locstruct)
lu_numbytes = 100
if (not readfile ( iu_file, ls_buff, lu_numbytes, & lu_bytesread, lstr_locstruct))
then
messagebox("错误","无法读取 #" + string(getlasterror ( )),StopSign!)
timer(0)
else
if( lu_bytesread > 0) then
is_buffer += trim(ls_buff) mle_1.text += trim(ls_buff) //处理数据
this.wf_is_valid_receieve ( ) //检验函数
end if
end if
第四步:完成后释放端口
closehandle ( iu_file )
具体函数使用方法可参见MSDN中的TAPI。 有时可能用控件做起来更简单一些(如SCOMM、SAX COMM等)。

dawugui 2008-01-26
  • 打赏
  • 举报
回复
打的时候选择打印或定制纸张.

609

社区成员

发帖
与我相关
我的任务
社区描述
PowerBuilder DataWindow
社区管理员
  • DataWindow社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧