1、取出来的是十进制数;2、X=400,Y=300,那么
'一个long型的变量有8个字节,把前4个字节的值改成Y,后4个字节的值改为X
lParam=300*&H10000+400 '&H10000=4^8 '以十六进制的方式显示出lParam的值,前4个字符就是前Y,后4个字符就是X
DEBUG.PRINT "lParam=&H" & HEX(lParam) 3. 你的可用分越来越少,就要多回答问题,可以增加专家分和可用分
'一个long型的变量有8个字节,把前4个字节的值改成Y,后4个字节的值改为X
lParam=300*&H10000+400 '&H10000=4^8 '以十六进制的方式显示出lParam的值,前4个字符就是前Y,后4个字符就是X
DEBUG.PRINT "lParam=&H" & HEX(lParam) 3. 你的可用分越来越少,就要多回答问题,可以增加专家分和可用分
发送了4个不同的坐标(像素坐标)
a(0).x = 100
a(0).y = 100
a(1).x = 300
a(1).y = 100
a(2).x = 300
a(2).y = 300
a(3).x = 100
a(3).y = 300
x = a(i).x
y = a(i).y
xy = y * &H10000 + x
temp = SendMessage(hwnds, WM_LBUTTONDOWN, MK_LBUTTON, xy)
Call Sleep(1000)
temp = SendMessage(hwnds, WM_LBUTTONUP, MK_LBUTTON, xy)然后在目标程序里使用了
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
X = X / Screen.TwipsPerPixelX
Y = Y / Screen.TwipsPerPixelY
xy = Y * &H10000 + X
d = d + 1 '计数
Me.Label2.Caption = "button=" & Button & "," & "x y=" & X & " " & Y & " " & d
Me.Label9.Caption = xy & " " & Hex(xy)
End SubPrivate Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
X = X / Screen.TwipsPerPixelX
Y = Y / Screen.TwipsPerPixelY
u = u + 1 '计数
xy = Y * &H10000 + X
Me.Label8.Caption = "button=" & Button & "," & "x y=" & X & " " & Y & " " & u
Me.Label10.Caption = xy & " " & Hex(xy)
End Sub然后奇怪的现象产生了 (上面程序的结果)
X = X / Screen.TwipsPerPixelX--------〉=-1780
Y = Y / Screen.TwipsPerPixelY--------> =127
xy = Y * &H10000 + X --------> =8321292
Hex(xy) --------> =7EF90C
而且 只有这一个结果(不是4个),但是 计数 却正常的+1,+1...
如果我手动 在任何地方 单击 则正常得到x y xy Hex(xy) 4个数据,然后又回到那样了,计数还在跳
2、PostMessage和SendMessage的工作方式是不同的,前者把一个消息挂接在Windows消息列队里,发送消息后就马上返回;而后者导致立即调用消息处理函数;
3、用SPY++这个工具(Visual Studio中带的)来查看一下,你将会看到LBUTTONDOWN/LBUTTONUP/KEYDOWN/KEYUP这些由用户通过输入设备(键盘和鼠标)产生的消息,都是P类型的,即由PostMessage函数发送的。
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As LongPrivate Const WM_MOUSEMOVE = &H200
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202
Private Const WM_LBUTTONDBLCLK = &H203
Private Const WM_RBUTTONDOWN = &H204
Private Const WM_RBUTTONUP = &H205
Private Const WM_RBUTTONDBLCLK = &H206
Private Const WM_MBUTTONDOWN = &H207
Private Const WM_MBUTTONUP = &H208
Private Const WM_MBUTTONDBLCLK = &H209Private Const MK_LBUTTON = &H1
Private Const MK_RBUTTON = &H2
Private Const MK_SHIFT = &H4
Private Const MK_CONTROL = &H8
Private Const MK_MBUTTON = &H10Public Function SendMouseMsg(ByVal hWnd As Long, ByVal uMsg As Long, ByVal Button As Long, ByVal X As Integer, ByVal Y As Integer) As Long
Dim TempLng As Long
TempLng = (TempLng Or X) And &HFFFF
TempLng = TempLng Or (Y And &H7FFF) * &H10000
If Y And &H8000 Then TempLng = TempLng Or &H80000000
SendMouseMsg = SendMessage(hWnd, uMsg, Button, ByVal TempLng)
End Function
Private Sub Command1_Click()
'
End SubPrivate Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Debug.Print "MouseDown", Button; Hex(Shift); X \ Screen.TwipsPerPixelX; Y \ Screen.TwipsPerPixelY
End SubPrivate Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Debug.Print "MouseMove", Button; Hex(Shift); X \ Screen.TwipsPerPixelX; Y \ Screen.TwipsPerPixelY
End SubPrivate Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Debug.Print "MouseUp", Button; Hex(Shift); X \ Screen.TwipsPerPixelX; Y \ Screen.TwipsPerPixelY
End SubPrivate Sub Command2_Click()
Debug.Print
Debug.Print SendMouseMsg(Command1.hWnd, WM_LBUTTONDOWN, MK_LBUTTON, 10, 10)
Debug.Print SendMouseMsg(Command1.hWnd, WM_LBUTTONUP, MK_LBUTTON, 10, 10)
End SubPrivate Sub Form_Load()
'
End Sub
TempLng = (TempLng Or X) And &HFFFF&
to junwhj()
我查过以前的帖子 发现 PostMessage 会产生 顺序问题(123,213,321等,)因为我的程序需要顺序,消息之间空隙 最多1~2秒 所以只能用SendMessage
,用SendMessage为什么会产生问题? 可以改正么?
to zyl910(910:分儿,我来了!)
你的程序 我今天看看 不过你这些是写在一个程序里边的吧 我的是写在两个里边的,我回去改改
自从我来到这里一直是2位帮我 很感谢~
使用SendMessage 不再出错,比较2位的方法 关键在于lParam
总结如下:
junwhj() 的做法
xy = y * 4 ^ 8 + x
zyl910(910:分儿,我来了!)的做法
TempLng = (TempLng Or X) And &HFFFF
TempLng = TempLng Or (Y And &H7FFF) * &H10000
If Y And &H8000 Then TempLng = TempLng Or &H80000000使用了zyl910(910:分儿,我来了!)的做法,成功!
其中的 or=或 and=与 templng定义后没有赋值应该是0
应该按照二进制计算方法解释,%……%¥……%¥(以下为内心旁白)
tmd,谁发明的二进制,老子脑袋爆炸了,也没想明白
(旁白结束)
还是请zyl910(910:分儿,我来了!) 说明吧(解释清楚一些吧,我脑袋现在不转了,1+1=2 都要计算器)
另to zyl910(910:分儿,我来了!)
TempLng = (TempLng Or X) And &HFFFF& 最后的&加不加 好像没什么区别
其实真正的原因是lParam参数没有加BYVAL,下面的程序执行结果是正确的。xy = Y * &H10000 + X
temp = SendMessage(hwnds, WM_LBUTTONDOWN, MK_LBUTTON, byval xy)
Call Sleep(1000)
temp = SendMessage(hwnds, WM_LBUTTONUP, MK_LBUTTON, byval xy)
&HFFFF&=65535
&HFFFF=-1
-1&=&HFFFFFFFF其实“xy = y * 4 ^ 8 + x”这样可以
当碰到坐标为负的时候就会出问题
所以我那样写假设为(1,1)
TempLng Or 1=1
1 and &Hffff&=11 and &H7fff=1
1*&H10000=&H10000
1 Or &H10000=&H10001
因为(1 and &H8000)=0,所以“TempLng = TempLng Or &H80000000”不执行1 and &H7fff=1
假设为(-1,-1)
TempLng Or 1=-1&=&HFFFFFFFF
&HFFFFFFFF And &Hffff&=&HFFFF&-1 and &H7fff=&H7fff
&H7fff*&H10000=&H7FFF0000
&H7FFF0000 Or &HFFFF&=&H7FFFFFFF
因为(-1 And &H8000)<>0,则:
&H7FFFFFFF=&H7FFFFFFF Or &H80000000=&Hffffffff
byval 按值 传递 访问变量的复本 不可改变变量的真正值
我在这里 并没有 改变值(或者希望要改变值 ) 所以,已开始我并没有使用byval,没想到 有这么大麻烦, 但是这是为什么呢?请教~(学明白点比较好)to zyl910(910:分儿,我来了!)
多谢,写了这么多
开始 我使用了4个点作为例子
(0).x = 100
a(0).y = 100
a(1).x = 300
a(1).y = 100
a(2).x = 300
a(2).y = 300
a(3).x = 100
a(3).y = 300
所以不应该会有-的情况,但是就是错!
&是什么东西?msdn竟然查不了最后一个问题,如果我先结贴 你们还能不能答,告诉我,省得我总的等你们答完了才敢结
&:长整形
@:货币型
!:单精度浮点型
#:双精度浮点型
$:字符串
只要加上ByVal 一切ok不过有新问题了 :( 还的麻烦二位
现在 在我的测试目标程序里边 可以看到 mouse 在我指定的地方单击了但是,我真正的目标是个游戏 用到他里边 发现 也能单击 但是不在我指定的地方 怎么办?是在 我鼠标当前位置 单击 为什么?
temp = SendMessage(hwnds, WM_MOUSEMOVE, WM_MOUSEMOVE, ByVal xy)
同样 在程序里 可以在mousemove里边捕捉到 我发的xy但是 鼠标并没有 真正的移动 怎么办?
2、移动鼠标可以用SetCurPos()这个函数。
使程序响应事件不会改变鼠标坐标要改变鼠标位置
用SetCursorPos
SetCursorPos VB声明
Declare Function SetCursorPos Lib "user32" Alias "SetCursorPos" (ByVal x As Long, ByVal y As Long) As Long
说明
设置指针的位置
返回值
Long,非零表示成功,零表示失败。会设置GetLastError
参数表
参数 类型及说明
x,y 鼠标指针在屏幕像素坐标系统中的X,Y位置
耿有效率的 方法
它的参数
MOUSEEVENTF_MOVE 移动鼠标
MOUSEEVENTF_LEFTDOWN 模拟鼠标左键按下
MOUSEEVENTF_LEFTUP 模拟鼠标左键抬起
MOUSEEVENTF_RIGHTDOWN 模拟鼠标右键按下
MOUSEEVENTF_RIGHTUP 模拟鼠标右键按下
MOUSEEVENTF_MIDDLEDOWN 模拟鼠标中键按下
MOUSEEVENTF_MIDDLEUP 模拟鼠标中键按下
是不是和SendMessage的参数 谁对应的 数字是一样的
而mouse_event是用来模拟鼠标事件,必须用它的鼠标事件常数,即MOUSEEVENTF_……
:::::::::::form1 :::::::::::::Option ExplicitPrivate Sub Command1_Click()
EventLog = 0
hHook = SetWindowsHookEx(WH_JOURNALRECORD, AddressOf HookProc, _
App.hInstance, 0)
Command2.Enabled = True
Command1.Enabled = False
End SubPrivate Sub Command2_Click()
UnhookWindowsHookEx hHook
hHook = 0 Command1.Enabled = True
Command2.Enabled = False
Command3.Enabled = True
End SubPrivate Sub Command3_Click()
PlayLog = 0
hPlay = SetWindowsHookEx(WH_JOURNALPLAYBACK, AddressOf PlaybackProc, _
App.hInstance, 0)
Command3.Enabled = False
End SubPrivate Sub Form_Load()
Command1.Caption = "纪录"
Command2.Caption = "停止"
Command3.Caption = "回放"
Command2.Enabled = False
Command3.Enabled = False
End Sub::::::::::::::::::::Module1:::::::::::
Option ExplicitPublic Type EVENTMSG
message As Long
paramL As Long
paramH As Long
time As Long
hwnd As Long
End TypePublic Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Long, _
ByVal ncode As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Public Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" _
(ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
Public Declare Sub CopyMemoryT2H Lib "kernel32" _
Alias "RtlMoveMemory" _
(ByVal Dest As Long, _
Source As EVENTMSG, _
ByVal Length As Long)
Public Declare Sub CopyMemoryH2T Lib "kernel32" _
Alias "RtlMoveMemory" _
(Dest As EVENTMSG, _
ByVal Source As Long, _
ByVal Length As Long)
Public Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As LongPublic Const WH_JOURNALPLAYBACK = 1
Public Const WH_JOURNALRECORD = 0
Public Const HC_SYSMODALOFF = 5
Public Const HC_SYSMODALON = 4
Public Const HC_SKIP = 2
Public Const HC_GETNEXT = 1
Public Const HC_ACTION = 0Public EventArr(1000) As EVENTMSG
Public EventLog As Long
Public PlayLog As Long
Public hHook As Long
Public hPlay As Long
Public recOK As Long
Public canPlay As Long
Public bDelay As BooleanPublic Function HookProc(ByVal iCode As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
Dim Result As Long
recOK = 1
Result = 0 If iCode < 0 Then 'iCode小于0必须直接调用下一个消息钩子函数
Result = CallNextHookEx(hHook, iCode, wParam, lParam)
ElseIf iCode = HC_SYSMODALON Then '不允许纪录
recOK = 0
ElseIf iCode = HC_SYSMODALOFF Then '允许纪录
recOK = 1
ElseIf ((recOK > 0) And (iCode = HC_ACTION)) Then
'将消息纪录在纪录队列中
CopyMemoryH2T EventArr(EventLog), lParam, Len(EventArr(EventLog))
EventLog = EventLog + 1
If EventLog >= 1000 Then
'当纪录大于1000后释放消息钩子
UnhookWindowsHookEx hHook
End If
End If
HookProc = Result
End FunctionPublic Function PlaybackProc(ByVal iCode As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
Dim Result As Long
canPlay = 1
Result = 0 If iCode < 0 Then 'iCode小于0必须直接调用下一个消息钩子函数
Result = CallNextHookEx(hPlay, iCode, wParam, lParam)
ElseIf iCode = HC_SYSMODALON Then '不允许回放
canPlay = 0
ElseIf iCode = HC_SYSMODALOFF Then '允许回放
canPlay = 1
ElseIf ((canPlay = 1) And (iCode = HC_GETNEXT)) Then
If bDelay Then
bDelay = False
Result = 50
End If
'从纪录队列中取出消息并赋予lParam指针指向的EVENTMSG区域
CopyMemoryT2H lParam, EventArr(PlayLog), Len(EventArr(EventLog))
ElseIf ((canPlay = 1) And (iCode = HC_SKIP)) Then
bDelay = True
PlayLog = PlayLog + 1
End If
If PlayLog >= EventLog Then
UnhookWindowsHookEx hPlay
End If
PlaybackProc = Result
End Function