模拟鼠标单击而不移动光标 [英] Simulate mouse click without moving the cursor

查看:279
本文介绍了模拟鼠标单击而不移动光标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个应用程序,检测所有活动的Windows并将其放入列表。



有没有办法在屏幕上相对于Windows位置模拟mouseclick,而不实际移动光标?



我无法访问应该单击的按钮句柄,只能到窗口的句柄

解决方案

有没有办法在屏幕上相对于Windows位置模拟mouseclick,而不实际移动光标?


要回答你的具体问题 - NO。鼠标点击只能指向鼠标光标实际驻留在点击时的位置。 正确模拟鼠标输入的方法是使用 SendInput() (或 mouse_event() )。但是这些函数将模拟事件注入到与实际鼠标驱动程序相同的输入队列中,因此它们将对鼠标光标产生物理效应,即在屏幕上移动它。



如何模拟输入SendInput?


SendInput在输入堆栈的底层进行操作。 它只是一个后门到相同的输入机制,键盘和鼠标驱动程序使用告诉窗口管理器用户已生成输入。 SendInput函数不知道输入将会发生什么。这是由更高级别的窗口管理器处理的,比如命中测试鼠标输入以查看消息应该最初传递到哪个窗口的组件。


当一个东西被添加到一个队列,它需要时间从队列的前面出来



< blockquote>

当调用SendInput时,将输入数据包放入系统硬件输入队列。 (注意:不是官方术语,这就是我今天所说的。)这是硬件设备驱动程序堆栈在物理设备报告事件时使用的相同的输入队列。



消息进入硬件输入队列,原始输入线程将其拾取。原始输入线程以高优先级运行,因此它可能会很快得到它,但在多核机器上,您的代码可以保持运行,而第二个核心运行原始输入线程。原始输入线程有一些东西,它需要做的事情出队。如果有低级输入钩子,它必须调用每个钩子,以查看是否有任何他们想拒绝输入。 (这些钩子可以采取谁知道多长时间来决定。)只有在所有低级钩子签署输入后,原始输入线程允许修改输入状态,并导致GetAsyncKeyState报告该键是下。


唯一真正的方法来做你要的是找到 HWND 位于所需的屏幕坐标处。然后您可以:


  1. 发送 WM_LBUTTONDOWN WM_LBUTTONUP 消息。或者,如果是标准的Win32按钮控件,请发送单个 msdn.microsoft.com/en-us/library/windows/desktop/dd317978.aspxrel =nofollow> AccessibleObjectFromWindow() < a href =https://msdn.microsoft.com/en-us/library/windows/desktop/ee684009.aspx =nofollow> UI Automation API访问控件的 IAccessible 界面,然后调用其 accDoDefaultAction()


这就是说, ...


我无法访问应点击的按钮。


您可以访问任何具有 HWND 的文件。请查看 WindowFromPoint() 。您可以使用它来找到占用所需屏幕坐标的按钮的 HWND (注意,当然: WindowFromPoint,ChildWindowFromPoint,RealChildWindowFromPoint,什么时候全部结束?)。


I wrote an application that detects all active Windows and puts them into a list.

Is there a way to simulate a mouseclick on a spot on the screen relative to the Windows location without actually moving the cursor?

I don't have access to the buttons handle that is supposed to be clicked, only to the handle of the window

解决方案

Is there a way to simulate a mouseclick on a spot on the screen relative to the Windows location without actually moving the cursor?

To answer your specific question - NO. Mouse clicks can only be directed where the mouse cursor actually resides at the time of the click. The correct way to simulate mouse input is to use SendInput() (or mouse_event() on older systems). But those functions inject simulated events into the same input queue that the actual mouse driver posts to, so they will have a physical effect on the mouse cursor - ie move it around the screen, etc.

How do I simulate input without SendInput?

SendInput operates at the bottom level of the input stack. It is just a backdoor into the same input mechanism that the keyboard and mouse drivers use to tell the window manager that the user has generated input. The SendInput function doesn't know what will happen to the input. That is handled by much higher levels of the window manager, like the components which hit-test mouse input to see which window the message should initially be delivered to.

When something gets added to a queue, it takes time for it to come out the front of the queue

When you call Send­Input, you're putting input packets into the system hardware input queue. (Note: Not the official term. That's just what I'm calling it today.) This is the same input queue that the hardware device driver stack uses when physical devices report events.

The message goes into the hardware input queue, where the Raw Input Thread picks them up. The Raw Input Thread runs at high priority, so it's probably going to pick it up really quickly, but on a multi-core machine, your code can keep running while the second core runs the Raw Input Thread. And the Raw Input thread has some stuff it needs to do once it dequeues the event. If there are low-level input hooks, it has to call each of those hooks to see if any of them want to reject the input. (And those hooks can take who-knows-how-long to decide.) Only after all the low-level hooks sign off on the input is the Raw Input Thread allowed to modify the input state and cause Get­Async­Key­State to report that the key is down.

The only real way to do what you are asking for is to find the HWND of the UI control that is located at the desired screen coordinates. Then you can either:

  1. send WM_LBUTTONDOWN and WM_LBUTTONUP messages directly to it. Or, in the case of a standard Win32 button control, send a single BM_CLICK message instead.

  2. use the AccessibleObjectFromWindow() function of the UI Automation API to access the control's IAccessible interface, and then call its accDoDefaultAction() method, which for a button will click it.

That being said, ...

I don't have access to the buttons handle that is supposed to be clicked.

You can access anything that has an HWND. Have a look at WindowFromPoint(), for instance. You can use it to find the HWND of the button that occupies the desired screen coordinates (with caveats, of course: WindowFromPoint, ChildWindowFromPoint, RealChildWindowFromPoint, when will it all end?).

这篇关于模拟鼠标单击而不移动光标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆