1、Visual Basic串口通讯调试方法现有电子秤一台,使用串口与计算机进行通讯。编写VB程序来访问串口,达到读取电子秤上显示的数据。该电子秤为BE01型仪表,输出为RS-232C标准接口,波特率为300-9600、偶校验、7个数据位、2个停止位。所有字符均发送11位ASCII码,一个起始位。在VB中与串口通讯需要引入控件MSComm串口通讯控件(在Microsoft Comm Control 6.0中)。具体程序如下:控件简称:MSC Dim Out(12) As Byte 接收var中的值Dim var As Variant 接收MSC.input中的数值Dim nRece As Inte
2、ger 计算MSC.inputbuffer的个数Dim i As Integer, j As Integer 随即变量,计算循环*Private Sub Form_Load()ClearTextWith MSC.CommPort = 1 设置Com1为通信端口.Settings = 9600,E,7,2 设置通信端口参数 9600赫兹、偶校验、7个数据位、1个停止位.(这里需要进一步说明的是:.Setting=”BBBB,P,D,S”。含义是:B:Baud Rate(波特率);P:Parity(奇偶);D:Data Bit;S:Stop Bit).InBufferSize = 40 设置缓冲区
3、接收数据为40字节.InputLen = 1 设置Input一次从接收缓冲读取字节数为1.RThreshold = 1 设置接收一个字节就产生OnComm事件End WithEnd Sub*Private Sub ClearText()Text3.Text = Text2.Text = 5Text1.Text = End SubPrivate Sub Command1_Click()ClearText nRece = 0 计数器清零With MSC.InputMode = comInputModeBinary 设置数据接收模式为二进制形式.InBufferCount = 0 清除接收缓冲区If
4、 Not .PortOpen Then.PortOpen = True 打开通信端口End IfEnd WithEnd SubPrivate Sub MSC_OnComm()DelayTime 用来延续时间ClearTextWith MSCSelect Case .CommEvent 判断通信事件Case comEvReceive: 收到Rthreshold个字节产生的接收事件SwichVar 1If Out(1) = 2 Then 判断是否为数据的开始标志.RThreshold = 0 关闭OnComm事件接收End IfDoDoEventsLoop Until .InBufferCount
5、 = 3 循环等待接收缓冲区=3个字节 nRece = nRece + 1For i = 2 To 12SwichVar iText1.Text = Text1.Text & Chr(Out(i)NextText1.Text = LTrim(Text1.Text)Text2.Text = Text2.Text & CStr(nRece).RThreshold = 1 打开MSComm事件接收Case Else .PortOpen = FalseEnd SelectEnd WithEnd Sub*Private Sub DelayTime()Dim bDT As BooleanDim sPrev
6、ious As Single, sLast As SinglebDT = TruesPrevious = Timer (Timer可以计算从子夜到现在所经过的秒数,在Microsoft Windows中,Timer函数可以返回一秒的小数部分)Do While bDTIf Timer - sPrevious = 0.3 Then bDT = FalseLoopbDT = TrueEnd Sub(通信传输速率为9600bps,则最快速度1.04ms发送一个字节,仪表每秒发送50帧数据,每帧数据有4个字节,即每秒发送200个字节,平均5.0ms 发送一个字节,连续读取串口数据时要在程序中添加循环等待
7、程序)Private Sub SwichVar(ByVal nNum As Integer)DelayTimevar = Nullvar = MSC.InputOut(nNum) = var(0)End Sub(设置接收数据模式采用二进制形式,即 InputMode=comInputModeBinary,但用Input属性读取数据时,不能直接赋值给 Byte 类型变量,只能通过先赋值给一个 Variant 类型变量,返回一个二进制数据的数组,再转换保存到Byte类型数变量中。)Private Sub Text1_Change()Text3.Text = CText(Text1.Text) -
8、CText(Text2.Text)End Sub*Private Function CText(ByVal str As String) As CurrencyIf str ThenCText = CCur(Val(str)ElseCText = 0End IfEnd Function(仪表每秒发送50帧数据,微机收到一帧完整数据至少需要20 ms时间,然后再进行数据处理。如果微机在下一帧数据接收前即20ms内能将数据计算处理完毕,则接收缓冲区内只会保存有一帧数据,不会存有两帧以上数据,接收缓冲区的大小不会影响实时监测效果(接收缓冲区4字节),这时完全可以实现实时监测或实时控制;如果微机在20
9、ms内不能将数据计算处理完毕,接收缓冲区设置得又很大,在数据计算处理完毕前,接收缓冲区内就会保存有两帧以上数据,而且一次工作时间越长,缓冲区内滞留数据帧就越多,数据采集和数据处理之间产生逐渐增大的额外时间差,当接收缓冲区充满后,时间差不再增大,固定在某一值,部分数据因不能及时采集到接收缓冲区中,数据产生丢失现象,真实工作情况就会和微机处理结果产生较大的时间差,对实时监测和实时控制很不利,这种情况下接收缓冲区的大小就会影响实时监测效果,所以接收缓冲区设置不能过大,以保证数据处理的实时性。) 小结:本文所用的仪表为梅特勒公司出产的BE01型电子秤,其输出的每个编码均为标准的ASCII码。其他的仪表
10、存在发射的编码中含有BCD压缩码,而且分为高低位,需要接收后对其进行解码换算,之后还要将高位和低位数字进行相加,即可以将其BCD码换算成实数。另还存在误差的可能:判断最大值,仪表在刚开始工作时有干扰,会传导一些乱码,位移传感器有参数偏差,最大值一般都略大于50毫米,所以取51为极限最大值,取51为极限最小值。暂时先写这些,当然其他的情况可以依此类推! 附录资料:不需要的可以自行删除VB HOOK(钩子)超级无敌详细用法(介绍)hook是WINDOWS提供的一种消息处理机制,它使得程序员可以使用子过程来监视系统消息,并在消息到达目标过程前得到处理。 下面将介绍WINNDOWS HOOKS并且说明
11、如何在WINDOWS 程序中使用它。关于HOOKS 使用HOOK 将会降低系统效率,因为它增加了系统处量消息的工作量。建议在必要时才使用HOOK,并在消息处理完成后立即移去该HOOK。HOOK链 WINDOWS提供了几种不同类型的HOOKS;不同的HOOK可以处理不同的消息。例如,WH_MOUSE HOOK用来监视鼠标消息。 WINDOWS为这几种HOOKS维护着各自的HOOK链。HOOK链是一个由应用程序定义的回调函数队列,当某种类型的消息发生时,WINDOWS向此种类型的HOOK链的第一个函数发送该消息,在第一函数处理完该消息后由该函数向链表中的下一个函数传递消息,依次向下。如果链中某个函
12、数没有向下传送该消息,那么链表中后面的函数将得不到此消息。(对于某些类型的HOOK,不管HOOK链中的函数是否向下传递消息,与此类型HOOK联系的所有HOOK函数都会收到系统发送的消息)HOOK过程 为了拦截特定的消息,你可以使用SetWindowsHookEx函数在该类型的HOOK链中安装你自己的HOOK函数。该函数语法如下: public function MyHook(nCode,wParam,iParam) as long 加入代码 end function 其中MyHook可以随便命名,其它不能变。该函数必须放在模块段。nCode指定HOOK类型。wParam,iParam的取值随n
13、Code不同而不同,它代表了某种类型的HOOK的某个特定的动作。 SetWindowsHookEx总是将你的HOOK函数放置在HOOK链的顶端。你可以使用CallNextHookEx函数将系统消息传递给HOOK链中的下一个函数。 注释对于某些类型的HOOK,系统将向该类的所有HOOK函数发送消息,这时,HOOK函数中的CallNextHookEx语句将被忽略。 全局HOOK函数可以拦截系统中所有线程的某个特定的消息(此时该HOOK函数必须放置在DLL中),局部HOOK函数可以拦截指定线程的某特定消息(此时该HOOK函数可以放置在DLL中,也可以放置在应用程序的模块段)。 注释 建议只在调试时使
14、用全局HOOK函数。全局HOOK函数将降低系统效率,并且会同其它使用该类HOOK的应用程序产生冲突。HOOK类型 WH_CALLWNDPROC 和 WH_CALLWNDPROCRET HOOK WH_C ALLWNDPROC 和WH_CALLWNDPROCRET HOOK可以监视SendMessage发送的消息。系统在向窗体过程发送消息前,将调用WH_CALLWNDPROC;在窗体过程处理完该消息后系统将调用WH_CALLWNDPROCRET。 WH_CALLWNDPROCRET HOOK会向HOOK过程传送一个CWPRETSTRUCT结构的地址。该结构包含了窗体过程处理系统消息后的一些信息。
15、 WH_CBT Hook 系统在激活,创建,消毁,最小化,最大化,移动,改变窗体前;在完成一条系统命令前;在从系统消息队列中移去鼠标或键盘事件前;在设置输入焦点前,或同步系统消息队列前,将调用WH_CBT HOOK。你可以在你的HOOK 过程拦截该类HOOK,并返回一个值,告诉系统,是否继续执行上面的操作。 WH_DEBUG HOOK 系统在调用与某种HOOK类型联系的HOOK过程前,将调用WH_DEBUG ,应用程序可以使用该HOOK决定是否让系统执行某种类型的HOOK。 WH_FOREGROUNDIDLE Hook 系统在空闲时调用该HOOK,在后台执行优先权较低的应用程序。 WH_GET
16、MESSAGE Hook WH_GETMESSAGE Hook使应用程序可以拦截GetMessage 或 PeekMessage的消息。应用程序使用WH_GETMESSAGE HOOK监视鼠标、键盘输入和发送到队列中的其它消息。 WH_JOURNALRECORD Hook WH_JOURNALRECORD Hook使应用程序可以监视输入事件。典型地,应用程序使用该HOOK记录鼠标、键盘输入事件以供以后回放。该HOOK是全局HOOK,并且不能在指定线程中使用。 WH_JOURNALPLAYBACK Hook WH_JOURNALPLAYBACK Hook使应用程序可以向系统消息队列中插入消息。该
17、HOOK可以回放以前由WH_JOURNALRECORD HOOK录制的鼠标、键盘输入事件。在WH_JOURNALPLAYBACK Hook安装到系统时,鼠标、键盘输入事件将被屏蔽。该HOOK同样是一个全局HOOK,不能在指定线程中使用。 WH_JOURNALPLAYBACK Hook返回一个时间暂停值,它告诉系统,在处理当前回放的消息时,系统等待百分之几秒。这使得此HOOK可以控制在回放时的时间事件。 WH_KEYBOARD Hook WH_KEYBOARD Hook使应用程序可以监视由GetMessage和PeekMessage返回的WM_KEYDOWN 及WM_KEYUP消息。应用程序使用
18、该HOOK监视发送到消息队列中的键盘输入。 WH_MOUSE Hook WH_MOUSE Hook 使应用程序可以监视由GetMessage和PeekMessage返回的消息。应用程序使用该HOOK监视发送到消息队列中的鼠标输入。 WH_MSGFILTER and WH_SYSMSGFILTER Hooks WH_MSGFILTER 和WH_SYSMSGFILTER Hooks使应用程序可以监视菜单、滚动条、消息框、对话框,当用户使用ALT+TAB或ALT+ESC来切换窗体时,该HOOK也可以拦截到消息。WH_MSGFILTER仅在应用程序内部监视菜单、滚动条、消息框、对话框,而WH_SYSM
19、SGFILTER则可以在系统内监视所有应用程序的这些事件。 WH_SHELL Hook 一个SHELL程序可以使用WH_SHELL Hook来接收重要的信息。当一个SHELL程序被激活前或当前窗体被创建、消毁时,系统会调用WH_SHELL Hook过程。 使用HOOK 安装、销毁HOOK过程 监视系统事件安装、销毁HOOK过程 使用SetWindowsHookEx函数,指定一个HOOK类型,自己的HOOK过程是全局还是局部HOOK,同时给出HOOK过程的进入点,就可以轻松的安装你自己的HOOK过程。Declare Function SetWindowsHookEx Lib user32 Ali
20、as SetWindowsHookExA _ (ByVal idHook As Long, _ ByVal lpfn As Long, _ ByVal hmod As Long, _ ByVal dwThreadId As Long) As LongidHook代表是何种Hook,有以下几种 Public Const WH_CALLWNDPROC = 4 Public Const WH_CALLWNDPROCRET = 12 Public Const WH_CBT = 5 Public Const WH_DEBUG = 9 Public Const WH_FOREGROUNDIDLE = 11
21、 Public Const WH_GETMESSAGE = 3 Public Const WH_HARDWARE = 8 Public Const WH_JOURNALPLAYBACK = 1 Public Const WH_JOURNALRECORD = 0 Public Const WH_KEYBOARD = 2 Public Const WH_MOUSE = 7 Public Const WH_MSGFILTER = (-1) Public Const WH_SHELL = 10 Public Const WH_SYSMSGFILTER = 6lpfn代表Hook Function所在的
22、Address,这是一个CallBack Fucnction,当挂上某个Hook时,我们便得定义一个Function来当作某个讯息产生时,来处理它的Function,这个Hook Function有一定的叁数格式 Private Function HookFunc(ByVal nCode As Long, _ ByVal wParam As Long, _ ByVal lParam As Long ) As Long nCode 代表是什麽请况之下所产生的Hook,随Hook的不同而有不同组的可能值。 wParam lParam 传回值则随Hook的种类和nCode的值之不同而不同。 因这个叁
23、数是一个 Function的Address所以我们固定将Hook Function放在.Bas中,并以AddressOf HookFunc传入。至於Hook Function的名称我们可以任意给定,不一定叫 HookFunchmod 代表.DLL的hInstance,如果是Local Hook,该值可以是Null(VB中可传0进去),而如果是Remote Hook,则可以使用GetModuleHandle(.dll名称)来传入。dwThreadId 代表执行这个Hook的ThreadId,如果不设定是那个Thread来做,则传0(所以一般来说,Remote Hook传0进去),而VB的Loca
24、l Hook一般可传App.ThreadId进去。值回值 如果SetWindowsHookEx()成功,它会传回一个值,代表目前的Hook的Handle,这个值要记录下来。因为A程式可以有一个System Hook(Remote Hook),如KeyBoard Hook,而B程式也来设一个Remote的KeyBoard Hook,那麽到底KeyBoard的讯息谁所拦截?答案是,最後的那一个所拦截,也就是说A先做keyboard Hook,而後B才做,那讯息被B拦截,那A呢?就看B的Hook Function如何做。如果B想让A的Hook Function也得这个讯息,那B就得呼叫CallNex
25、tHookEx()将这讯息Pass给A,於是产生Hook的一个连线。如果B中不想Pass这讯息给A,那就不要呼叫CallNextHookEx()。Declare Function CallNextHookEx Lib user32 Alias CallNextHookEx _ (ByVal hHook As Long, _ ByVal ncode As Long, _ ByVal wParam As Long, _ lParam As Any) As LonghHook值是SetWindowsHookEx()的传回值,nCode, wParam, lParam则是Hook Procedure中
26、的三个叁数。最後是将这Hook去除掉,请呼叫UnHookWindowHookEx()Declare Function UnhookWindowsHookEx Lib user32 Alias UnhookWindowsHookEx _ (ByVal hHook As Long) As LonghHook便是SetWindowsHookEx()的传回值。此时,以上例来说,B程式结束Hook,则换A可以直接拦截讯息。KeyBoard Hook的范例Hook Function的三个叁数nCode wParam lParam 传回值HC_ACTION表按键Virtual Key与WM_KEYDOWN同
27、若讯息要被处理传0或 反之传1HC_NOREMOVEPublic hHook as LongPublic Sub UnHookKBD ()If hnexthookproc 0 Then UnhookWindowsHookEx hHook hHook = 0End IfEnd SubPublic Function EnableKBDHook()If hHook 0 Then Exit FunctionEnd Ifhhook = SetWindowsHookEx(WH_KEYBOARD, AddressOf _ MyKBHFunc, App.hInstance, App.ThreadId)End
28、FunctionPublic Function MyKBHFunc(ByVal iCode As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long MyKBHfunc = 0 表示要处理这个讯息 If wParam = vbKeySnapshot Then 侦测 有没有按到PrintScreen键 MyKBHFunc = 1 在这个Hook便吃掉这个讯息 End If Call CallNextHookEx(hHook, iCode, wParam, lParam) 传给下一个HookEnd Function鼠标钩子的示例列
29、下。(1)模块中输入:Public Const WM_MOUSEMOVE = &H200Public Const WM_LBUTTONDOWN = &H201Public Const WM_LBUTTONUP = &H202Public Const WM_LBUTTONDBLCLK = &H203Public Const WM_RBUTTONDOWN = &H204Public Const WM_RBUTTONUP = &H205Public Const WM_RBUTTONDBLCLK = &H206Public Const WM_MBUTTONDOWN = &H207Public Cons
30、t WM_MBUTTONUP = &H208Public Const WM_MBUTTONDBLCLK = &H209Public Const WM_MOUSEACTIVATE = &H21Public Const WM_MOUSEFIRST = &H200Public Const WM_MOUSELAST = &H209Public Const WM_MOUSEWHEEL = &H20A 以上是鼠标的各个值Private Declare Function CallNextHookEx Lib user32 (ByVal hHook As Long, ByVal nCode As Long,
31、ByVal wParam As Long, lparam As Any) As LongPublic Function HookProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lparam As Long) As Long If nCode 0 Then HookProc = CallNextHookEx(hHook, nCode, wParam, lparam) Exit Function End If If wParam = WM_RBUTTONDOWN Then MsgBox aa End IfEnd Function(2)窗体
32、中输入:Private Declare Function SetWindowsHookEx Lib user32 Alias SetWindowsHookExA (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As LongPrivate Declare Function UnhookWindowsHookEx Lib user32 (ByVal hHook As Long) As LongPrivate Const WH_MOUSE_LL As Long = 14
33、Private Sub Form_Load() hHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf HookProc, App.hInstance, 0)End SubPrivate Sub Form_Unload(Cancel As Integer)Call UnhookWindowsHookEx(hHook)End Sub=保存图片:创建一个picturebox,其 autosize设为true 创建一个按钮 运行以下代码 Option Explicit Private Sub Command1_Click() Picture1.Picture
34、= Clipboard.GetData SavePicture Picture1.Picture, d:1.jpg 保存路径和文件名自己定 End Sub =将一个或多个按键(注意可以是多个)消息发送到活动窗口,就如同在键盘上进行输入一样。 语法 SendKeys string, wait SendKeys 语句的语法具有以下几个命名参数: 部分 描述 string 必需的。字符串表达式,指定要发送的按键消息。 Wait 可选的。指定等待方式的 BooleandefBooleanDataTypeveendf98.chm 值。如果为 False(缺省值),则控件在按键发送出去之后立刻返回到过程。
35、如果为 True,则按键消息必须在控件返回到过程之前加以处理。 说明 每个按键由一个或多个字符表示。为了指定单一键盘字符,必须按字符本身的键。例如,为了表示字母 A,可以用 A 作为 string。为了表示多个字符,就必须在字符后面直接加上另一个字符。例如,要表示 A、B 及 C,可用 ABCD 作为 string。 对 SendKeys 来说,加号 (+)、插入符 ()、百分比符号 (%)、上划线 () 及圆括号 ( ) 都具有特殊意义。为了指定上述任何一个字符,要将它放在大括号 () 当中。例如,要指定正号,可用 + 表示。方括号 ( ) 对 SendKeys 来说并不具有特殊意义,但必须
36、将它们放在大括号中。在其它应用程序中,方括号有特殊意义,在出现动态数据交换 (DDE) 的时候,它可能具有重要意义。为了指定大括号字符,请使用 及 。 为了在按下按键时指定那些不显示的字符,例如 ENTER 或 TAB 以及那些表示动作而非字符的按键,请使用下列代码: 按键 代码 BACKSPACE BACKSPACE, BS, 或 BKSP BREAK BREAK CAPS LOCK CAPSLOCK DEL or DELETE DELETE 或 DEL DOWN ARROW DOWN END END ENTER ENTER或 ESC ESC HELP HELP HOME HOME INS
37、or INSERT INSERT 或 INS LEFT ARROW LEFT NUM LOCK NUMLOCK PAGE DOWN PGDN PAGE UP PGUP PRINT SCREEN PRTSC RIGHT ARROW RIGHT SCROLL LOCK SCROLLLOCK TAB TAB UP ARROW UP F1 F1 F2 F2 F3 F3 F4 F4 F5 F5 F6 F6 F7 F7 F8 F8 F9 F9 F10 F10 F11 F11 F12 F12 F13 F13 F14 F14 F15 F15 F16 F16 为了指定那些与 SHIFT、CTRL 及 ALT 等
38、按键结合的组合键,可在这些按键码的前面放置一个或多个代码,这些代码列举如下: 按键 代码 SHIFT + CTRL ALT % 为了说明在按下其它按键时应同时按下 SHIFT、CTRL、及 ALT 的任意组合键,请把那些按键的码放在括号当中。例如,为了说明按下 E 与 C 的时候同时按下 SHIFT 键,请使用 +(EC)。为了说明在按下 E 的时候同时按下 SHIFT 键,但接着按 C 而不按 SHIFT,则使用 +EC。 为了指定重复键,使用 key number 的形式。必须在 key 与 number 之间放置一个空格。例如,LEFT 42 意指 42 次按下 LEFT ARROW 键;h 10 则是指 10 次按下 H 键。 注意 不能用 SendKeys 将按键消息发送到这样一个应用程序,这个应用程序并没有被设计成在 Microsoft Windows 中运行。Sendkeys 也无法将 PRINT SCREEN 按键 PRTSC 发送到任何应用程序。