用SendMessage 模拟鼠标点击指定位置坐标出错

lmhcs 2017-12-31 05:06:19
用SendMessage发送WM_LBUTTONDOWN,并在lparam指定坐标位置。但接受放接受到位置严重出错。不知道错误哪里。知道c#高手多,特来c#这边发帖,请教!贴代码


Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
'测试发送鼠标点击
Dim res As Integer
Win.SetForegroundWindow(hwnd) '窗体激活
'测试鼠标窗体点击
Dim x As Int16 = 58
Dim y As Int16 = 155
Dim pt As New Point(x, y)
Dim lp As Int32 = Helper.ToLParam(x, y)
lp = 10158138 '低16位58,高16位155
MSG.SetCursorPos(x, y) '在网上看到SetCursorPos可以模拟点击制定位置,但本测试不行)
res = MSG.SendMessage(hwnd, WM.WM_LBUTTONDOWN, MouseMK.MK_LBUTTON, lp)
Threading.Thread.Sleep(200)
res = MSG.SendMessage(hwnd, WM.WM_LBUTTONUP, MouseMK.MK_LBUTTON, lp)
End Sub


上例发打算发送x=58,y=155坐标位置,但被模拟点击的程序收到的是:在 WndProc 方法lparam接受到是165864560,即x=58480,y=2530,这个坐标跟发送的坐标严重不一致。
api声明

Public Class MSG
<DllImport("user32", SetLastError:=True)>
Public Shared Function PostMessage(hWnd As IntPtr, Msg As UInteger, wParam As Integer, lParam As Integer) As Boolean
End Function
<DllImport("user32.dll", EntryPoint:="SendMessage", CharSet:=CharSet.Auto)>
Public Shared Function SendMessage(hwnd As IntPtr, wMsg As Integer, wParam As Int32, ByRef lParam As Int32) As Int32
End Function
''' <summary>
''' 成功返回非0
''' </summary>
''' <param name="x"></param>
''' <param name="y"></param>
''' <returns></returns>
''' <remarks></remarks>
<DllImport("user32.dll", EntryPoint:="SetCursorPos")>
Public Shared Function SetCursorPos(x As Int32, y As Int32) As Int32
End Function
End Class

'按键消息
Public Enum WM
WM_LBUTTONDOWN = &H201
WM_LBUTTONUP = &H202
BM_CLICK = &HF5
End Enum

Public Enum MouseMK

''' <summary>
''' 鼠标左键
''' </summary>
''' <remarks></remarks>
MK_LBUTTON = &H1
''' <summary>
''' 鼠标右键
''' </summary>
''' <remarks></remarks>
MK_RBUTTON = &H2
''' <summary>
''' 鼠标中键
''' </summary>
''' <remarks></remarks>
MK_MBUTTON = &H10 '

MK_SHIFT = &H4
''' <summary>
''' 键盘Ctrl键
''' </summary>
''' <remarks></remarks>
MK_CONTROL = &H8
End Enum



Public Class Helper
''' <summary>
''' y右移16位
''' </summary>
''' <param name="x"></param>
''' <param name="y"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function ToLParam(x As Int32, y As Int32) As Int32
' Return (y << 16) Or (x And &HFFFF)
Return x + (y << 16)
End Function

''' <summary>
''' 返回低16位
''' </summary>
''' <param name="lp"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function LoWord(lp As Int32) As Int16
Dim mask As Int32 = &HFFFF
Return (lp And mask)
End Function
''' <summary>
''' 返回高16位
''' </summary>
''' <param name="lp"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function HiWord(lp As Int32) As Int16
Dim mask As Int32 = &HFFFF
Return (lp >> 16) And mask
End Function

End Class

...全文
1572 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
srgcc 2018-11-27
  • 打赏
  • 举报
回复
遇到同样的问题,楼主知道为什么CharSet:=CharSet.Unicode这样就可以吗? 是不是64位的系统就需要这样声明?
lmhcs 2018-01-07
  • 打赏
  • 举报
回复
结帖。上面的错误是sendmessage声明错误。郁闷死。一直没有发现。。。。 在vb中正确声明, <DllImport("user32.dll", EntryPoint:="SendMessage", CharSet:=CharSet.Unicode)> Public Shared Function SendMessage(hwnd As IntPtr, wMsg As Integer, wParam As IntPtr, ByVal lParam As IntPtr) As Int32 End Function
zzyhost 2018-01-01
  • 打赏
  • 举报
回复
推荐你用SendInput,很好很强大
真相重于对错 2018-01-01
  • 打赏
  • 举报
回复
The WM_LBUTTONDOWN message is posted when the user presses the left mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
xuzuning 2018-01-01
  • 打赏
  • 举报
回复
鼠标位置是相对控件左上角的,你考虑到这点了吗?
lmhcs 2018-01-01
  • 打赏
  • 举报
回复
to From_TaiWan 朋友: WM_LBUTTONDOWN消息,wparam参数是指示鼠标按键参数,lparam是坐标信息。其中x坐标为lp的低16位,高16位为y坐标 Public Shared Function ToLParam(x As Int32, y As Int32) As Int32 ' Return (y << 16) Or (x And &HFFFF) Return x + (y << 16) End Function 这个函数应该没有错吧?!我把x坐标放在低16位,y坐标左移16位后。即高十六位啊。 我在网上百度很久,网上差不多都用这种方法。但我测试就不能发送成功,不知道是不是 64位系统的缘故。我是win7 64位。 至于10158138,是我拦截消息是的鼠标坐标值, Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) MyBase.WndProc(m) If m.Msg = WM_LBUTTONUP Then Console.WriteLine(m.LParam) Label1.Text = m.LParam Label2.Text = LoWord(m.LParam) & " " & HiWord(m.LParam) End If End Sub 当lp=10158138,x坐标就是58,y坐标就是155。
秋的红果实 2017-12-31
  • 打赏
  • 举报
回复
在 WndProc 方法lparam接受到是165864560,即x=58480,y=2530 ==> 这个转换是怎么进行的? 发送的x,y编码成一个数lp,接收到后,再还原为坐标,规则必须是一样的 平时用win32 API的毕竟少,只能帮到这里了
秋的红果实 2017-12-31
  • 打赏
  • 举报
回复
 ''' y右移16位 Public Shared Function ToLParam(x As Int32, y As Int32) As Int32         ' Return (y << 16) Or (x And &HFFFF)         Return x + (y << 16)     End Function ==> 不知道你要将传递的数据变成什么形式?貌似将x坐标放到一个32位整数的高位部分,y放到低位部分 但是,看注解,y向右移,应该写:y>>16 调用函数时,lp = 10158138,这个值你是怎么来的? 另外,输出sendMessage函数返回值是多少,验证是不是执行成功 另外可以尝试PostMessage函数,这个立刻返回。不过最后一个参数,也要定义为Byref的
Jason_Mao1 2017-12-31
  • 打赏
  • 举报
回复
屏幕的坐标的分辨率 还有 DPI 有一定的关系,你多看看这方面的东西 。希望能帮助到你。
lmhcs 2017-12-31
  • 打赏
  • 举报
回复
添加接受程序代码

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        MyBase.WndProc(m)
        If m.Msg = WM_LBUTTONUP Then
            Console.WriteLine(m.LParam)
            Label1.Text = m.LParam
            Label2.Text = LoWord(m.LParam) & " " & HiWord(m.LParam)

        End If
    End Sub


111,120

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧