我写了一个应用程序来检测所有活动的Windows并将它们放入列表中。
有没有办法在屏幕上相对于Windows位置模拟鼠标点击而不实际移动光标?
我无法访问应该点击的按钮句柄,只能访问窗口的句柄
答案 0 :(得分:4)
有没有办法在屏幕上相对于Windows位置模拟鼠标点击而不实际移动光标?
回答您的具体问题 - 没有。鼠标单击只能指向鼠标光标在单击时实际驻留的位置。模拟鼠标输入的正确方法是在旧系统上使用SendInput()
(或mouse_event()
)。但是这些函数将模拟事件注入到实际鼠标驱动程序发布到的相同输入队列中,因此它们将对鼠标光标产生物理效果 - 即在屏幕上移动等等。
How do I simulate input without SendInput?
SendInput在输入堆栈的底层运行。 这只是键盘和鼠标驱动程序使用相同输入机制的后门告诉窗口管理器用户已生成输入。 SendInput函数不知道输入会发生什么。这是由更高级别的窗口管理器处理的,就像点击测试鼠标输入以查看消息最初应该传递到哪个窗口的组件一样。
When something gets added to a queue, it takes time for it to come out the front of the queue
当您调用SendInput时,您将输入数据包放入系统硬件输入队列。 (注意:不是官方术语。这正是我今天所说的。)这是硬件设备驱动程序堆栈在物理设备报告事件时使用的相同输入队列。
消息进入硬件输入队列,Raw Input Thread接收它们。原始输入线程以高优先级运行,因此它可能会很快得到它,但在多核机器上,您的代码可以继续运行,而第二个核心运行原始输入线程。 Raw Input线程有一些东西,它一旦出事件就需要做。如果存在低级输入挂钩,则必须调用每个挂钩以查看是否有任何挂钩想要拒绝输入。 (并且那些钩子可以采用谁知道多长时间来决定。)只有在输入上的所有低级别挂钩签名后,Raw Input Thread才允许修改输入状态并导致GetAsyncKeyState报告密钥是下。
执行您要求的唯一真正方法是找到位于所需屏幕坐标的UI控件的HWND
。然后你可以:
直接向其发送WM_LBUTTONDOWN
和WM_LBUTTONUP
条消息。或者,对于标准的Win32按钮控件,请发送一条BM_CLICK
消息。
使用AccessibleObjectFromWindow()
API的UI Automation函数访问控件的IAccessible
界面,然后调用其accDoDefaultAction()
方法,单击按钮即可它
话虽如此,......
我无法访问应该点击的按钮句柄。
您可以访问具有HWND
的任何内容。例如,请查看WindowFromPoint()
。您可以使用它来查找占据所需屏幕坐标的按钮的HWND
(当然需要注意:WindowFromPoint, ChildWindowFromPoint, RealChildWindowFromPoint, when will it all end?)。