找回密码
 立即注册
搜索
热搜: rtk 全站仪 航测
查看: 510|回复: 3

在VB中“遥控”鼠标

[复制链接]

主题

0

回帖

113

积分

新手上路

积分
113
发表于 2004-4-14 06:19:16 | 显示全部楼层 |阅读模式
获取鼠标光标在屏幕上的位置和移动鼠标光标,分别需调用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 LongPrivate Declare Function SetCursorPos Lib “user32" (ByVal X As Long, ByVal 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) As LongPrivate Declare Function ClientToScreen Lib “user32" (ByVal hwnd As Long, 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,

WM_LBUTTONDOWN, 0, 0)

TickCount = GetTickCount()

While GetTickCount() - TickCount < 200

tmp = DoEvents()

Wend

tmp = SendMessage(Command1.hwnd,

WM_LBUTTONUP, 0, 0)

End Sub
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|测量空间论坛 ( 闽ICP备19019609号-1 )

GMT+8, 2026-7-5 00:09 , Processed in 0.068548 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表