您的位置:首页 > 其它

通信控件MSComm使用详解

2008-05-17 15:19 831 查看
VB利用MSCOMM控件通过gsm modem发送短消息!

2006-12-07 11:44:57 Thu | 阅读(40)次

MSComm1.Settings = "9600,N,8,1" '9600波特,无奇偶校验,8位数据,一个停止位
MSComm1.InputLen = 0 '读入整个缓冲区
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True '打开端口
MSComm1.Handshaking = comRTSXOnXOff

Length = Len("你好") * 2

MSComm1.Output = "AT+CMGF=0" + vbCr

msg = "AT+CMGS=" & Str(15 + Length) + vbCr
'msg = msg + "08" 'SMSC地址信息的长度(91683110304105F0共八位字节)
'msg = msg + "91" '短消息中心地址类型(TON/NPI)
'msg = msg + "683110304105F0" '8613010314500
msg = msg + "00" '表示使用SIM卡上的短消息中心的地址,用来替换上述三行地址

'Str (15 + Length) 15指下面15位
msg = msg + "11" '11 基本参数(TP-MTI/VFP)( 发送,接收为84)
msg = msg + "00" 'MR Message Reference
msg = msg + "0D" '目标SIM卡号码长度(8613916160599按阿拉伯数字个数计)
msg = msg + "91" '手机地址类型(TON/NPI)
msg = msg + "683119160695F9" '8613916160599
msg = msg + "00" ' 00 协议标识(TP-PID) ,普通GSM类型,点到点方式
msg = msg + "08" 'UCS2编码
msg = msg + "00" '有效期
msg = msg + "04" '信息字节长度

msg = msg + "4F60597D" '你好
msg = msg + Chr$(26)

MSComm1.Output = msg

-------------------------------------------------------------------------------------
MSComm 控件的 Modem 通讯
www.easyde.net 来源:不详 发布时间:2006-11-6 11:23:18 发布人:hyztxeasy
减小字体 增大字体

下载源代码

  MSComm 控件通过串行端口(serial port)传送和接收数据,为应用程序提供了串行通讯功能。而且在可视化编程盛行的今天,可以很方便的在Visual Basic(VB)、Visual C++(VC)、Delphi等语言及开发平台中应用。
  MSComm 是 Microsoft 公司为简化Windows下串行端口编程而提供的ActiveX控件,它提供了一系列标准通讯命令的使用接口,为应用程序提供了通过串行口收发数据的简洁方法。处理数据的方式有事件驱动(Event-driver)、查询法(Inquire)两种。

1.事件驱动法

  在使用事件驱动法设计程序时,每当有新字符到达、端口状态变化或发生错误时,MSComm控件将解发OnComm事件,而应用程序在捕获该事件后,通过检查MSComm控件的CommEvent属性可以获知所发生的事件或错误,从而采取相应的操作。这种方法的优点是程序响应及时,可靠性高。

2.查询法

  这种方法适合于较小的应用程序。在这种情况下,每当应用程序执行完某一串行口操作后,将不断检查MSComm控件的CommEvent属性以检查执行结果或者检查某一事件是否发生。例如,当程序向串行设备发送了某个命令后,可能只是在等待收到一个特定的响应字符串,而不是对收到的每一个字符都立刻响应并处理。
  在VC中添加?MSComm控件非常简单。在打开的工程中,选择菜单Project->Add To Project->Component and Controls,在弹出的对话框“Component and Controls Gallery”中选中“Microsoft Communication Controls Version 6.0”?,单击“Insert”按钮即可完成添加MSComm控件操作。
本工程应用采用事件驱动法,具体实现如下:

一.串口信息配置
  按上述方法完成在基于对话框的应用程序中添加MSComm控件操作并增加相应成员变量m_comm。在对话框模板上右键单击MSComm控件,选择Property菜单项,即可设置MSComm控件各项属性。在此调制解调器通讯的程序中,设置“Control”属性页中Handshaking项为“2-comRTS”,否则国内部分厂家modem不能正常通讯。其它接受缺省设置。
  另外亦可通过修改对话框类的OnInitDialog()函数来设置控件的属性。具体参考MSDN中的关于Comm Control的详细说明。
if(m_comm.GetPortOpen()) { m_comm.SetPortOpen(FALSE);//设置串口配置信息前先要关闭串口 } m_comm.SetCommPort(1);//Com1串行口 m_comm.SetSettings("9600,n,8,1");//设置波特率为9600bps,无奇偶校验位,数据位8位,停止位1位 m_comm.SetInputMode(1);//设置数据通讯格式为二进制数组格式 m_comm.SetRThreshold(1);//设置为每次接到一个字节数据就触发OnComm事件 if(!m_comm.GetPortOpen()) { m_comm.SetPortOpen(TRUE); } m_comm.GetInput();//清除串口输入缓冲区中残留数据 m_SendData="ATZ/r/n";//调制解调器初始化 m_comm.SetOutput(COleVariant(m_SendData));
二.接收数据
  添加接收数据函数,在对话框中双击Comm Control,接受默认函数,则对话框类的成员函数为OnCommMscomm(),添加代码如下:
Sleep(500); //视各厂家modem而定。不加则数据接受不全 VARIANT m_input; char *str,*str1; int k,nEvent,i,len,m; CString str2; m_ReceiveData=""; nEvent=m_comm.GetCommEvent(); switch(nEvent) { case 2: //收到大于RTHresshold个字符 k=m_comm.GetInBufferCount(); //接收缓冲区的字符数目 if(k>0) { m_input=m_comm.GetInput(); str=(char*)(unsigned char*)m_input.parray->pvData; } ?i=0; str1=str; while(i<k) { i++; str1++; } *str1=''/0''; str2=(const char*)str; //清除字符串中的不必要字符 m_ReceiveData=(const char *)str; break; case 3: //CTS线状态发生变化 break; case 4: //DSR线状态发生变化 break; case 5: //CD线状态发生变化 break; case 6: //Ring Indicator发生变化 break; }
  以上是在做工程之余写下的一点东西。VC我是初学者,有错误的地方,还请各位批评指正。例子在VC 6.0+Win2000下调试通过。Win98下测试数据接收不全。还望高手指点一二。
E-mail:qjxue@21cn.com

附:
  单片机或PC机对MODEM的控制是通过设置MODEM的S寄存器和发送标准AT命令来实现的。命令行由AT或at开始,不能是At或aT。它的一般格式为“AT+指令+回车”常用的AT命令简介如下,详细的AT命令见本说明书附录。
&F 恢复出厂设置
DT××× 音频拨号, ×××表示电话号码
+++ 切换到在线命令状态
Sn=X 写S寄存器
Hn 摘机/挂机控制
n=0 挂机
n=1 摘机
S0=X X=0,不自动应答
X=1~255,振铃指定次数后自动应答
/N0 异步方式设定为0
/q0 XON/XOFF流控方式
----------------------------------------------------------
通信控件MSComm使用详解
  MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能。MSComm控件在串口编程时非常方便,程序员不必去花时间去了解较为复杂的API函数,而且在VC、VB、Delphi等语言中均可使用。 Microsoft Communications Control(以下简称MSComm)是Microsoft公司提供的简化Windows下串行通信编程的ActiveX控件,它为应用程序提供了通过串行接口收发数据的简便方法。具体的来说,它提供了两种处理通信问题的方法:一是事件驱动(Event-driven)方法,一是查询法。

  1.MSComm控件两种处理通讯的方式

  MSComm控件提供下列两种处理通讯的方式:事件驱动方式和查询方式。

  1.1 事件驱动方式

  事件驱动通讯是处理串行端口交互作用的一种非常有效的方法。在许多情况下,在事件发生时需要得到通知,例如,在串口接收缓冲区中有字符,或者 Carrier Detect (CD) 或 Request To Send (RTS) 线上一个字符到达或一个变化发生时。在这些情况下,可以利用 MSComm 控件的 OnComm 事件捕获并处理这些通讯事件。OnComm 事件还可以检查和处理通讯错误。所有通讯事件和通讯错误的列表,参阅 CommEvent 属性。在编程过程中,就可以在OnComm事件处理函数中加入自己的处理代码。这种方法的优点是程序响应及时,可靠性高。每个MSComm 控件对应着一个串行端口。如果应用程序需要访问多个串行端口,必须使用多个 MSComm 控件。

  1.2 查询方式

  查询方式实质上还是事件驱动,但在有些情况下,这种方式显得更为便捷。在程序的每个关键功能之后,可以通过检查 CommEvent 属性的值来查询事件和错误。如果应用程序较小,并且是自保持的,这种方法可能是更可取的。例如,如果写一个简单的电话拨号程序,则没有必要对每接收一个字符都产生事件,因为唯一等待接收的字符是调制解调器的“确定”响应。

  2.MSComm 控件的常用属性

  MSComm 控件有很多重要的属性,但首先必须熟悉几个属性。

CommPort 设置并返回通讯端口号。
Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。
PortOpen 设置并返回通讯端口的状态。也可以打开和关闭端口。
Input 从接收缓冲区返回和删除字符。
Output 向传输缓冲区写一个字符串。

  下面分别描述:

  CommPort属性:设置并返回通讯端口号。

  语法 object.CommPort[value ] (value 一整型值,说明端口号。)

  说明 在设计时,value 可以设置成从 1 到 16 的任何数(缺省值为 1)。但是如果用 PortOpen 属性打开一个并不存在的端口时,MSComm 控件会产生错误 68(设备无效)。

  注意:必须在打开端口之前设置 CommPort 属性。

  RThreshold 属性:在 MSComm 控件设置 CommEvent 属性为 comEvReceive 并产生 OnComm 之前,设置并返回的要接收的字符数。

  语法:object.Rthreshold [ = value ](value 整型表达式,说明在产生 OnComm 事件之前要接收的字符数。 )

  说明:当接收字符后,若 Rthreshold 属性设置为 0(缺省值)则不产生 OnComm 事件。例如,设置 Rthreshold 为 1,接收缓冲区收到每一个字符都会使 MSComm 控件产生 OnComm 事件。

  CTSHolding 属性:确定是否可通过查询 Clear To Send (CTS) 线的状态发送数据。Clear To Send 是调制解调器发送到相联计算机的信号,指示传输可以进行。该属性在设计时无效,在运行时为只读。

  语法: object.CTSHolding(Boolean)

  Mscomm 控件的 CTSHolding 属性设置值:

  True Clear To Send 线为高电平。
  False Clear To Send 线为低电平。

  说明:如果 Clear To Send 线为低电平 (CTSHolding = False) 并且超时时,MSComm 控件设置 CommEvent 属性为 comEventCTSTO (Clear To Send Timeout) 并产生 OnComm 事件。

  Clear To Send 线用于 RTS/CTS (Request To Send/Clear To Send) 硬件握手。如果需要确定 Clear To Send 线的状态,CTSHolding 属性给出一种手工查询的方法。

  详细信息 有关握手协议,请参阅 Handshaking 属性。

  SThreshold 属性: MSComm 控件设置 CommEvent 属性为 comEvSend 并产生 OnComm 事件之前,设置并返回传输缓冲区中允许的最小字符数。

  语法 object.SThreshold [ = value ]

  value 整形表达式,代表在 OnComm 事件产生之前在传输缓冲区中的最小字符数。

  说明:若设置 Sthreshold 属性为 0(缺省值),数据传输事件不会产生 OnComm 事件。若设置 Sthreshold 属性为 1,当传输缓冲区完全空时,MSComm 控件产生 OnComm 事件。如果在传输缓冲区中的字符数小于 value,CommEvent 属性设置为 comEvSend,并产生 OnComm 事件。comEvSend 事件仅当字符数与 Sthreshold 交叉时被激活一次。例如,如果 Sthreshold 等于 5,仅当在输出队列中字符数从 5 降到 4 时,comEvSend 才发生。如果在输出队列中从没有比 Sthreshold 多的字符,comEvSend 事件将绝不会发生。

  Handshake 常数

常数 值 描述
comNone 0 无握手。
comXonXoff 1 XOn/Xoff 握手。
comRTS 2 Request-to-send/clear-to-send 握手。
comRTSXOnXOff 3 Request-to-send 和 clear-to-send 握手皆可。

  OnComm 常数

常数 值 描述
comEvSend 1 发送事件。
comEvReceive 2 接收事件。
comEvCTS 3 clear-to-send 线变化。
comEvDSR 4 data-set ready 线变化。
comEvCD 5 carrier detect 线变化。
comEvRing 6 振铃检测。
comEvEOF 7 文件结束。

  Error 常数

常数 值 描述
comEventBreak 1001 接收到中断信号
comEventCTSTO 1002 Clear-to-send 超时
comEventDSRTO 1003 Data-set ready 超时
comEventFrame 1004 帧错误
comEventOverrun 1006 端口超速
comEventCDTO 1007 Carrier detect 超时
comEventRxOver 1008 接收缓冲区溢出
comEventRxParity 1009 Parity 错误
comEventTxFull 1010 传输缓冲区满
comEventDCB 1011 检索端口 设备控制块 (DCB) 时的意外错误

  InputMode 常数

常数 值 描述
comInputModeText 0 (缺省) 通过 Input 属性以文本方式取回数据。
comInputModeBinary 1 通过 Input 属性以二进制方式检取回数据。

  CDHolding 属性:通过查询 Carrier Detect (CD) 线的状态确定当前是否有传输。Carrier Detect 是从调制解调器发送到相联计算机的一个信号,指示调制解调器正在联机。该属性在设计时无效,在运行时为只读。

  语法 object.CDHolding

  设置值:CDHolding 属性的设置值为:

设置 描述
True Carrier Detect 线为高电平
False Carrier Detect 线为低电平

  说明:注意当 Carrier Detect 线为高电平 (CDHolding = True) 且超时时,MSComm 控件设置CommEvent 属性为 comEventCDTO(Carrier Detect 超时错误),并产生 OnComm 事件。

  注意 在主机应用程序中捕获一个丢失的传输是特别重要的,例如一个公告板,因为呼叫者可以随时挂起(放弃传输)。

  Carrier Detect 也被称为 Receive Line Signal Detect (RLSD)。

  数据类型:Boolean

  DSRHolding 属性:确定 Data Set Ready (DSR) 线的状态。Data Set Ready 信号由调制解调器发送到相连计算机,指示作好操作准备。该属性在设计时无效,在运行时为只读。

  语法:object.DSRHolding

  object 所在处表示对象表达式,其值是“应用于”列表中的对象。

  DSRHolding 属性返回以下值:

值 描述 说明
True Data Set Ready 线高   当 Data Set Ready 线为高电平 (DSRHolding = True) 且超时时,MSComm 控件设置 CommEvent 属性为 comEventDSRTO(数据准备超时)并产生 OnComm 事件。
  当为 Data Terminal Equipment (DTE) 机器写 Data Set Ready/Data Terminal Ready 握手例程时该属性是十分有用的。
  数据类型:Boolean
False Data Set Ready 线低

  Settings 属性: 设置并返回波特率、奇偶校验、数据位、停止位参数。

  语法: object.Settings[ = value]

  说明:当端口打开时,如果 value 非法,则 MSComm 控件产生错误 380(非法属性值)。

  Value 由四个设置值组成,有如下的格式:

  "BBBB,P,D,S"

  BBBB 为波特率,P 为奇偶校验,D 为数据位数,S 为停止位数。value 的缺省值是:

  "9600,N,8,1"

  InputLen 属性:设置并返回 Input 属性从接收缓冲区读取的字符数。

  语法 object.InputLen [ = value]

  InputLen 属性语法包括下列部分:

  value 整型表达式,说明 Input 属性从接收缓冲区中读取的字符数。

  说明:InputLen 属性的缺省值是 0。设置 InputLen 为 0 时,使用 Input 将使 MSComm 控件读取接收缓冲区中全部的内容。

  若接收缓冲区中 InputLen 字符无效,Input 属性返回一个零长度字符串 ("")。在使用 Input 前,用户可以选择检查 InBufferCount 属性来确定缓冲区中是否已有需要数目的字符。该属性在从输出格式为定长数据的机器读取数据时非常有用。

  EOFEnable 属性:确定在输入过程中 MSComm 控件是否寻找文件结尾 (EOF) 字符。如果找到 EOF 字符,将停止输入并激活 OnComm 事件,此时 CommEvent 属性设置为 comEvEOF,

  语法:object.EOFEnable [ = value ]

  EOFEnable 属性语法包括下列部分:

  value 布尔表达式,确定当找到 EOF 字符时,OnComm 事件是否被激活,如“设置值”中所描述。

  value 的设置值:

  True 当 EOF 字符找到时 OnComm 事件被激活。

  False (缺省)当 EOF 字符找到时 OnComm 事件不被激活。

  说明:当 EOFEnable 属性设置为 False,OnComm 控件将不在输入流中寻找 EOF 字符。

  3.错误消息(MS Comm 控件)

  下表列出 MSComm 控件可以捕获的错误:

值 描述
380 无效属性值 comInvalidPropertyValue
383 属性为只读 comSetNotSupported
394 属性为只读 comGetNotSupported
8000 端口打开时操作不合法 comPortOpen
8001 超时值必须大于 0
8002 无效端口号 comPortInvalid
8003 属性只在运行时有效
8004 属性在运行时为只读
8005 端口已经打开 comPortAlreadyOpen
8006 设备标识符无效或不支持该标识符
8007 不支持设备的波特率
8008 指定的字节大小无效
8009 缺省参数错误
8010 硬件不可用(被其它设备锁定)
8011 函数不能分配队列
8012 设备没有打开 comNoOpen
8013 设备已经打开
8014 不能使用 comm 通知
8015 不能设置 comm 状态 comSetCommStateFailed
8016 不能设置 comm 事件屏蔽
8018 仅当端口打开时操作才有效 comPortNotOpen
8019 设备忙
8020 读 comm 设备错误 comReadError
8021 为该端口检索设备控制块时的内部错误 comDCBError
------------------------------------------------------------------------
将这段代码作为一个模块,

'Constants used in the DevMode structure

Private Const CCHDEVICENAME = 32

Private Const CCHFORMNAME = 32

'Constants for NT security

Private Const STANDARD_RIGHTS_REQUIRED = &HF0000

Private Const PRINTER_ACCESS_ADMINISTER = &H4

Private Const PRINTER_ACCESS_USE = &H8

Private Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)

'Constants used to make changes to the values contained in the DevMode

Private Const DM_MODIFY = 8

Private Const DM_IN_BUFFER = DM_MODIFY

Private Const DM_COPY = 2

Private Const DM_OUT_BUFFER = DM_COPY

Private Const DM_DUPLEX = &H1000&

Private Const DMDUP_SIMPLEX = 1

Private Const DMDUP_VERTICAL = 2

Private Const DMDUP_HORIZONTAL = 3

Private Const DM_ORIENTATION = &H1&

Private PageDirection As Integer

'------USER DEFINED TYPES

'The DevMode structure contains printing parameters.

'Note that this only represents the PUBLIC portion of the DevMode.

' The full DevMode also contains a variable length PRIVATE section

' which varies in length and content between printer drivers.

'NEVER use this User Defined Type directly with any API call.

' Always combine it into a FULL DevMode structure and then send the

' full DevMode to the API call.

Private Type DEVMODE

dmDeviceName As String * CCHDEVICENAME

dmSpecVersion As Integer

dmDriverVersion As Integer

dmSize As Integer

dmDriverExtra As Integer

dmFields As Long

dmOrientation As Integer

dmPaperSize As Integer

dmPaperLength As Integer

dmPaperWidth As Integer

dmScale As Integer

dmCopies As Integer

dmDefaultSource As Integer

dmPrintQuality As Integer

dmColor As Integer

dmDuplex As Integer

dmYResolution As Integer

dmTTOption As Integer

dmCollate As Integer

dmFormName As String * CCHFORMNAME

dmLogPixels As Integer

dmBitsPerPel As Long

dmPelsWidth As Long

dmPelsHeight As Long

dmDisplayFlags As Long

dmDisplayFrequency As Long

dmICMMethod As Long ' // Windows 95 only

dmICMIntent As Long ' // Windows 95 only

dmMediaType As Long ' // Windows 95 only

dmDitherType As Long ' // Windows 95 only

dmReserved1 As Long ' // Windows 95 only

dmReserved2 As Long ' // Windows 95 only

End Type

Private Type PRINTER_DEFAULTS

'Note:

' The definition of Printer_Defaults in the VB5 API viewer is incorrect.

' Below, pDevMode has been corrected to LONG.

pDataType As String

pDevMode As Long

DesiredAccess As Long

End Type

'------DECLARATIONS

Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As PRINTER_DEFAULTS) As Long

Private Declare Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal Command As Long) As Long

Private Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal cbBuf As Long, pcbNeeded As Long) As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long

'The following is an unusual declaration of DocumentProperties:

' pDevModeOutput and pDevModeInput are usually declared ByRef. They are declared

' ByVal in this program because we're using a Printer_Info_2 structure.

' The pi2 structure contains a variable of type LONG which contains the address

' of the DevMode structure (this is called a pointer). This LONG variable must

' be passed ByVal.

' Normally this function is called with a BYTE ARRAY which contains the DevMode

' structure and the Byte Array is passed ByRef.

Private Declare Function DocumentProperties Lib "winspool.drv" Alias "DocumentPropertiesA" (ByVal hWnd As Long, ByVal hPrinter As Long, ByVal pDeviceName As String, ByVal pDevModeOutput As Any, ByVal pDevModeInput As Any, ByVal fMode As Long) As Long

Private Sub SetOrientation(NewSetting As Long, chng As Integer, ByVal frm As Form)

Dim PrinterHandle As Long

Dim PrinterName As String

Dim pd As PRINTER_DEFAULTS

Dim MyDevMode As DEVMODE

Dim Result As Long

Dim Needed As Long

Dim pFullDevMode As Long

Dim pi2_buffer() As Long 'This is a block of memory for the Printer_Info_2 structure

'If you need to use the Printer_Info_2 User Defined Type, the

' definition of Printer_Info_2 in the API viewer is incorrect.

' pDevMode and pSecurityDescriptor should be defined As Long.

PrinterName = Printer.DeviceName

If PrinterName = "" Then

Exit Sub

End If

pd.pDataType = vbNullString

pd.pDevMode = 0&

'Printer_Access_All is required for NT security

pd.DesiredAccess = PRINTER_ALL_ACCESS

Result = OpenPrinter(PrinterName, PrinterHandle, pd)

'The first call to GetPrinter gets the size, in bytes, of the buffer needed.

'This value is divided by 4 since each element of pi2_buffer is a long.

Result = GetPrinter(PrinterHandle, 2, ByVal 0&, 0, Needed)

ReDim pi2_buffer((Needed / 4))

Result = GetPrinter(PrinterHandle, 2, pi2_buffer(0), Needed, Needed)

'The seventh element of pi2_buffer is a Pointer to a block of memory

' which contains the full DevMode (including the PRIVATE portion).

pFullDevMode = pi2_buffer(7)

'Copy the Public portion of FullDevMode into our DevMode structure

Call CopyMemory(MyDevMode, ByVal pFullDevMode, Len(MyDevMode))

'Make desired changes

MyDevMode.dmDuplex = NewSetting

MyDevMode.dmFields = DM_DUPLEX Or DM_ORIENTATION

MyDevMode.dmOrientation = chng

'Copy our DevMode structure back into FullDevMode

Call CopyMemory(ByVal pFullDevMode, MyDevMode, Len(MyDevMode))

'Copy our changes to "the PUBLIC portion of the DevMode" into "the PRIVATE portion of the DevMode"

Result = DocumentProperties(frm.hWnd, PrinterHandle, PrinterName, ByVal pFullDevMode, ByVal pFullDevMode, DM_IN_BUFFER Or DM_OUT_BUFFER)

'Update the printer's default properties (to verify, go to the Printer folder

' and check the properties for the printer)

Result = SetPrinter(PrinterHandle, 2, pi2_buffer(0), 0&)

Call ClosePrinter(PrinterHandle)

'Note: Once "Set Printer = " is executed, anywhere in the code, after that point

' changes made with SetPrinter will ONLY affect the system-wide printer --

' -- the changes will NOT affect the VB printer object.

' Therefore, it may be necessary to reset the printer object's parameters to

' those chosen in the devmode.

Dim p As Printer

For Each p In Printers

If p.DeviceName = PrinterName Then

Set Printer = p

Exit For

End If

Next p

Printer.Duplex = MyDevMode.dmDuplex

End Sub

Public Sub ChngPrinterOrientationLandscape(ByVal frm As Form)

PageDirection = 2

Call SetOrientation(DMDUP_SIMPLEX, PageDirection, frm)

End Sub

Public Sub ResetPrinterOrientation(ByVal frm As Form)

If PageDirection = 1 Then

PageDirection = 2

Else

PageDirection = 1

End If

Call SetOrientation(DMDUP_SIMPLEX, PageDirection, frm)

End Sub

Public Sub ChngPrinterOrientationPortrait(ByVal frm As Form)

PageDirection = 1

Call SetOrientation(DMDUP_SIMPLEX, PageDirection, frm)

End Sub

'**********在屏幕中调用如下**********

' ResetPrinterOrientation Me '设为默认值

' ChngPrinterOrientationPortrait Me '设置为纵向

' ChngPrinterOrientationLandscape Me '设置为横向

' SetDefaultPrinterOrientation 2, 9 '以前的那个函数
-------------------------------------------------------------------------------------------------------------------
给你一段程序,作为一个模块,调用就可以了

Option Explicit

Public Enum PrinterOrientationConstants

OrientPortrait = 1

OrientLandscape = 2

End Enum

Private Type DEVMODE

dmDeviceName As String * 32

dmSpecVersion As Integer

dmDriverVersion As Integer

dmSize As Integer

dmDriverExtra As Integer

dmFields As Long

dmOrientation As Integer

dmPaperSize As Integer

dmPaperLength As Integer

dmPaperWidth As Integer

dmScale As Integer

dmCopies As Integer

dmDefaultSource As Integer

dmPrintQuality As Integer

dmColor As Integer

dmDuplex As Integer

dmYResolution As Integer

dmTTOption As Integer

dmCollate As Integer

dmFormName As String * 32

dmUnusedPadding As Integer

dmBitsPerPel As Integer

dmPelsWidth As Long

dmPelsHeight As Long

dmDisplayFlags As Long

dmDisplayFrequency As Long

End Type

Private Type PRINTER_DEFAULTS

pDataType As String

pDevMode As Long

DesiredAccess As Long

End Type

Private Type PRINTER_INFO_2

pServerName As Long

pPrinterName As Long

pShareName As Long

pPortName As Long

pDriverName As Long

pComment As Long

pLocation As Long

pDevMode As Long

pSepFile As Long

pPrintProcessor As Long

pDataType As Long

pParameters As Long

pSecurityDescriptor As Long

Attributes As Long

Priority As Long

DefaultPriority As Long

StartTime As Long

UntilTime As Long

Status As Long

cJobs As Long

AveragePPM As Long

End Type

'*******************'

' iDmpaper值 纸张 '

' 11 A5 '

' 13 B5 '

'*******************'

Private Const DM_IN_BUFFER As Long = 8

Private Const DM_OUT_BUFFER As Long = 2

Private Const DM_ORIENTATION As Long = &H1

Private Const DM_PAPERSIZE = &H2&

Private Const PRINTER_ACCESS_ADMINISTER As Long = &H4

Private Const PRINTER_ACCESS_USE As Long = &H8

Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000

Private Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED _

Or _

PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)

Private Declare Sub CopyMemory Lib "kernel32" Alias _

"RtlMoveMemory" _

(hpvDest As Any, hpvSource As Any, ByVal _

cbCopy As Long)

Private Declare Function OpenPrinter Lib "winspool.drv" Alias _

"OpenPrinterA" (ByVal pPrinterName As String, phPrinter As _

Long, pDefault As Any) As Long

Private Declare Function ClosePrinter Lib "winspool.drv" _

(ByVal hPrinter As Long) As Long

Private Declare Function DocumentProperties Lib "winspool.drv" _

Alias "DocumentPropertiesA" (ByVal hWnd As Long, ByVal hPrinter _

As Long, _

ByVal pDeviceName As String, pDevModeOutput As _

Any, _

pDevModeInput As Any, _

ByVal fMode As Long) As Long

Private Declare Function GetPrinter Lib "winspool.drv" _

Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal level As Long, _

pPrinter As Any, ByVal cbBuf As Long, pcbNeeded As Long) As _

Long

Private Declare Function SetPrinter Lib "winspool.drv" _

Alias "SetPrinterA" (ByVal hPrinter As Long, ByVal level As Long, _

pPrinter As Any, ByVal Command As Long) As Long

'在打印或预览之前直接调用SetDefaultPrinterOrientation 打印走向常数。注意:红色注释部分用于改变纸张的大小。

Function SetDefaultPrinterOrientation(ByVal eOrientation As _

PrinterOrientationConstants, iDmpaper As Integer) As Boolean

Dim bDevMode() As Byte

Dim bPrinterInfo2() As Byte

Dim hPrinter As Long

Dim lResult As Long

Dim nSize As Long

Dim sPrnName As String

Dim dm As DEVMODE

Dim olddm As DEVMODE

Dim pd As PRINTER_DEFAULTS

Dim pi2 As PRINTER_INFO_2

' 获取默认打印机的设备名称

sPrnName = Printer.DeviceName

' 由于要调用SetPrinter,所以

' 如果是在NT下就要求PRINTER_ALL_ACCESS

pd.DesiredAccess = PRINTER_ALL_ACCESS

' 获取打印机句柄

If OpenPrinter(sPrnName, hPrinter, pd) Then

' 获取PRINTER_INFO_2结构要求的字节数

Call GetPrinter(hPrinter, 2&, 0&, 0&, nSize)

ReDim bPrinterInfo2(1 To nSize) As Byte

lResult = GetPrinter(hPrinter, 2, bPrinterInfo2(1), nSize, nSize)

Call CopyMemory(pi2, bPrinterInfo2(1), Len(pi2))

nSize = DocumentProperties(0&, hPrinter, sPrnName, 0&, 0&, 0)

ReDim bDevMode(1 To nSize)

If pi2.pDevMode Then

Call CopyMemory(bDevMode(1), ByVal pi2.pDevMode, Len(dm))

Else

Call DocumentProperties(0&, hPrinter, sPrnName, bDevMode(1), 0&, DM_OUT_BUFFER)

End If

Call CopyMemory(dm, bDevMode(1), Len(dm))

Call CopyMemory(olddm, bDevMode(1), Len(olddm))

With dm

' 设置新的走向

.dmOrientation = eOrientation

.dmFields = DM_ORIENTATION

.dmPaperSize = iDmpaper '将纸张大小设为iDmpaper,请自行更改所需大小

' .dmPaperLength = iDmpaperLength

' .dmPaperWidth = iDmpaperWidth

.dmFields = DM_PAPERSIZE '必须,否则无法设置纸张大小

End With

Call CopyMemory(bDevMode(1), dm, Len(dm))

Call DocumentProperties(0&, hPrinter, sPrnName, _

bDevMode(1), bDevMode(1), DM_IN_BUFFER Or _

DM_OUT_BUFFER)

pi2.pDevMode = VarPtr(bDevMode(1))

lResult = SetPrinter(hPrinter, 2, pi2, 0&)

Call ClosePrinter(hPrinter)

SetDefaultPrinterOrientation = True

Else

SetDefaultPrinterOrientation = False

End If

End Function
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: