转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> VB.NET程序 >> 正文
在VB中“遥控”鼠标         ★★★★

在VB中“遥控”鼠标

作者:闵涛 文章来源:闵涛的学习笔记 点击数:733 更新时间:2009/4/23 14:57:45
  尽管Windows的API函数在当今“Visual”成风的时代正渐渐被人们忘却,但是正如当年开发高技巧的DOS软件离不开汇编语言和DOS系统功能调用一样,无论开发平台高级到什么地步,只要Windows还在最底层运作,就要用到API函数。无论VB的开发手段多么高明,功能多么强大,但是在现实应用中,总有一些功能的实现是VB无能为力的。微软也早意识到这一点,在VB的诸多版本中始终为API留有一席之地。根据笔者多年的VB开发经验,每当我们为了实现一个功能在VB浩瀚的对象、属性、方法、函数中苦苦搜索最终无功而返时,如果换一个角度,到API函数库中去探寻,往往能得到一个惊喜。

Windows API

  API函数是应用程序接口函数的缩写。Windows在API函数库中,为用户开发基于Windows的应用程序提供了所需的各种基本功能。API函数库的几百个函数分布在Windows系统的三个动态链接库中。这三个库在Windows3.x中名为“KERNEL”、“USER”和“GDI”,在Windows 95中名为“KERNEL32”、“USER32”和“GDI32”。这些API函数的功能和接口在Windows的编程手册中有系统详尽的说明,也可以从Visual C++ for Windows或Borland C++ for Windows的联机帮助手册中查到。  

  在VB中引用API函数,就像混合语言编程一样,要声明所引用的函数调用接口以及函数所在的动态链接库。声明一个API函数的语法为:

Declare Function 函数名
Lib “库名  ([参数表])
As 返回类型

  如果一个API函数返回值为空(void),可以把它声明为过程:

Declare Sub 过程名
Lib “库名  ([参数表])

  此外,相当一部分API函数的调用参数中用到了Windows系统定义的结构数据类型,这些类型在VB中也要用Type语句定义。 

  好在VB在提供访问API函数功能的同时,也给用户提供了一个友好的工具,可以省去我们声明API函数、定义结构数据类型的绝大部分工作。这个工具在VB5.0中叫“API Text Viewer”。在该工具中,载入“Win32api.txt”后,就可以在“Declares”类中搜索API函数声明,在“Types”类中搜索结构数据类型的定义,或在“Costants”类中搜索API函数中用到的常量定义。把搜索到的声明、定义直接通过剪贴板复制 B程序中比较省力省心。 

  把需要用到的函数声明和相关的数据结构定义以及常数定义加到窗体(Form)的General部分,就可以在程序中像调用普通VB函数一样方便地调用API函数。

应用实例

  以下从实用的角度出发,援引笔者在实际工作开发中的API应用一例,谨供参考。

  漫游过Windows 3.2的五分钟教程的用户,大概还记得演示鼠标用法。鼠标指针自动随教程的指令移动,自动点开菜单、按动按钮,完全脱离了对物理鼠标器的依赖。这种高级控制技巧在VB的函数和方法中是找不到的,仍然要借助于API函数。  

  本例用API函数实现对鼠标的“遥控”:无论鼠标指针在何处,一个菜单命令Alt-C就能使鼠标指针自动平滑移动到窗口中一个按钮的中心,然后自动按动按钮,激活按钮的Click事件处理过程。掌握了本例的方法后,前面提到的五分钟教程软件就不难制作了。

  本例中,以下几个功能的实现至关重要:获取鼠标光标在屏幕上的位置、获取按钮在屏幕上(注意:不是在窗口中)的位置、移动鼠标光标、自动按下和放开按钮,下面分别介绍。  

  获取鼠标光标在屏幕上的位置和移动鼠标光标,分别需调用API函数GetCursorPos和SetCursorPos。这两个函数的接口声明如下:

Declare Function GetCursorPos Lib “user32  (lpPoint As POINTAPI) As Long Declare Function SetCursorPos Lib “user32  (ByVal X As Long, ByVal Y As Long) As Long

  在SetCursorPos函数中,参数X和Y指定了鼠标光标在屏幕上的坐标。GetCursorPos函数把鼠标光标的当前位置存到结构变量lpPoint中。结构变量的定义如下:

Private Type POINTAPI
X As Long
Y As Long
End Type

  按钮的Left和Top属性给出的是按钮的左上角在窗口客户区坐标系中的坐标位置。要把鼠标光标移到按钮正中,需要得到按钮中心在屏幕坐标系中的坐标位置。窗口客户区坐标系与屏幕坐标系不仅坐标原点不同,二者的坐标单位(scale)也不同。窗口客户区坐标系的单位是Twip,屏幕坐标系单位是Pixel,二者的关系可以从屏幕对象Screen的TwipsPerPixelX和TwipsPerPixelY属性获取。这两个属性分别代表了水平和垂直两个方向上的单位转换比例。  

  把按钮中心在窗口客户区中的坐标单位转换为屏幕坐标系的单位后,还要通过一个API函数进行坐标平移变换,最终取得按钮中心在屏幕坐标系中的坐标位置。这个API函数的接口声明如下:

Declare Function ClientToScreen Lib “user32  (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

  最后一步是自动按下和放开按钮,这是通过模拟鼠标左键的按下和放开来实现的。该功能需调用API函数SendMessage向按钮发一对鼠标左键按下和放开的消息,函数接口声明如下:

Declare Function SendMessage Lib “user32  Alias “SendMessageA  (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

  SendMessage函数的hwnd参数为接收消息的窗口或控件的hwnd句柄。wMsg参数指定具体的消息值。在本例中,要发送鼠标左键按下和释放的消息,wMsg的取值分别为WM_LBUTTONDOWN和WM_LBUTTONUP,这两个常量定义如下:

Const WM_LBUTTONDOWN = &H201
Const WM_LBUTTONUP = &H202  

  把这两个消息发送给一个按钮,按钮就会像真的被鼠标左键单击了一样。SendMessage函数中的后两个参数在本例中可以不理,简单置0即可。

  还有一点细节需注意。如果连续给按钮发送一对WM_LBUTTONDOWN和WM_LBUTTONUP消息,Windows会来不及进行一些必要的系统操作,这样在视觉上就看不出按钮被按下后又放开的效果,好像按钮没有按动。但按钮的Click事件处理过程被激活执行表明按钮确实被按过。为了达到视觉上的完美效果,我们不妨在WM_LBUTTONDOWN和WM_LBUTTONUP两个消息之间插入一段短短的延时,比如说200毫秒,在这段延时期间,把处理权交给Windows,这样Windows就有时间显示按钮被按下的效果了。插入延时的办法有很多,可以加入一段空循环或利用计时器控件,这里再介绍一个API函数GetTickCount,该函数获取自Windows启动至被调用时所经过的毫秒数。利用这个函数控制延时,不仅精确,而且节省资源。GetTickCount函数的接口声明如下:

Declare Function GetTickCount Lib “kernel32  () As Long  

  下面进行窗体设计。我们在窗体Form1中安插一个按钮Command1。Command1的Click事件处理过程调用VB的Beep产生一声蜂鸣。另外在Form1的主菜单上加上一个ClickButton的菜单命令,热键设为Alt-C,该菜单命令的事件处理过程完成对鼠标光标的遥控。 

  最后给出Form1的完整程序清单:

Begin VB.Form Form1
BorderStyle = 1 Fixed Single
Caption = “Auto-click demonstration 
ClientHeight = 3195
ClientLeft = 150
ClientTop = 720
ClientWidth = 4680
LinkTopic = “Form1 
MaxButton = 0 False
ScaleHeight = 3195
ScaleWidth = 4680
StartUpPosition = 3 Windows Default
Begin VB.CommandButton Command1
Caption = “Click me! 
Height = 495
Left = 1740
TabIndex = 0
Top = 1380
Width = 1215
End
Begin VB.Menu mnuClickButton
Caption = “&ClickButton 
End
End
Attribute VB_Name = “Form1 
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Type POINTAPI
X As Long
Y As Long
End Type
Const WM_LBUTTONDOWN = &H201
Const WM_LBUTTONUP = &H202
Dim ButtonPos As POINTAPI
Private Declare Function GetCursorPos Lib “ user32  (lpPoint As POINTAPI) As
ongPrivate Declare Function SetCursorPos Lib “user32  (ByVal X As Long,
yVal Y As Long) As Long
Private Declare Function SendMessage Lib “ user32  Alias “SendMessageA 
ByValhwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any)
s LongPrivate Declare Function ClientToScreen Lib “user32  (ByVal hwnd As
ong, lpPoint As POINTAPI) As Long
Private Declare Function GetTickCount Lib “ kernel32  () As Long
Private Sub Command1_Click()
Beep
End Sub
Private Sub Form_Load()
Dim tmp As Long
With Command1
ButtonPos.X = (.Left + .Width / 2) / Screen.TwipsPerPixelX
ButtonPos.Y = (.Top + .Height / 2) / Screen.TwipsPerPixelY
End With
tmp = ClientToScreen(Me.hwnd, ButtonPos)
End Sub
Private Sub mnuClickButton_Click()
Const MoveStep As Integer = 50
Dim CursorPos As POINTAPI
Dim DistX As Double, DistY As Double
Dim tmp As Long
Dim i As Integer
Dim PosX As Integer, PosY As Integer
Dim TickCount As Long
tmp = GetCursorPos(CursorPos)
DistX = ButtonPos.X - CursorPos.X
DistY = ButtonPos.Y - CursorPos.Y
For i = 1 To MoveStep
PosX = CursorPos.X+DistX*i / MoveStep
PosY = CursorPos.Y+DistY*i / MoveStep
tmp = SetCursorPos(PosX, PosY)
Next i
tmp = SendMessage(Command1.hwnd,
M_LBUTTONDOWN, 0, 0)
TickCount = GetTickCount()
While GetTickCount() - TickCount < 200
mp = DoEvents()
Wend
tmp = SendMessage(Command1.hwnd,
WM_LBUTTONUP, 0, 0)
End Sub  

  笔者所用的操作系统为Windows 95,开发环境为VB企业版5.0。以上两例已调试运行成功,所介绍的方法同样适用于Windows 3.x下的VB 3.0和VB 4.0。

结语

  API函数在Windows程序开发中的地位就相当于DOS的INT 21H系统功能调用,无论高级语言、可视平台,最终都要归结于对这些底层功能的调用。我们开发高级的应用软件不能纯粹依赖这些底层调用(当然不是技术上实现不了,而是工作量吃不消),但也不能彻底撇开,就像盖楼时既要充分利用大量的预制件,也要用最基本的泥砂砖石一样。

155


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台