鼠标单击/拖动特定位置(特定窗口内)而不移动光标(.NET / C ++)

时间:2014-06-16 22:44:25

标签: c# winapi input mouse sendmessage

我正在开发一个能够平滑鼠标光标移动的应用程序,这样就可以在绘图应用程序(如MS Pain,SAI等)中使用普通鼠标绘制漂亮的曲线。但是,我不喜欢我的应用程序实际移动鼠标光标,因为它的位置用于平滑过程。这意味着我必须使绘图应用程序忽略鼠标光标的实际位置,并为其提供假的,平滑移动的鼠标光标的位置。

你对完成这个有什么想法吗?

<小时/> 我的想法是获取目标窗口的处理程序,禁用它(因为它禁用了输入,所以当我移动我的鼠标时,Windows不会向窗口宣布它),发送一个WM_LBUTTONDOWN,一系列WM_MOUSEMOVE,和WM_LBUTTONUP消息,然后再次启用窗口,以获得所需的结果。

我很快将一些代码放在一起,但它没有正常运行。然后我发现奇怪的事情。我拿走了禁用窗口的代码以及WM_MOUSEMOVE消息。剩下的代码应该在目标窗口内进行简单的单击。但是,在大多数情况下,它没有。当我尝试用它点击MSPaint的画布时,没有任何反应,但SendMessage返回0.但是当我尝试在VS2013或Google Chrome窗口内点击时,它运行得很好。 (那么现在呢?)

简化代码如下:

[DllImport("user32.dll", EntryPoint = "FindWindowA", SetLastError = true)]
static extern IntPtr FindWindow(IntPtr lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern int SendMessage(IntPtr hWnd, int msg, int WParam, int LParam);

void ClickInsideAnotherWindow(string windowTitle, Point clickPos)
{
    IntPtr hWnd = FindWindow(IntPtr.Zero, windowTitle);

    //MSDN said:
    //The low-order word specifies the x-coordinate of the cursor.
    //The high-order word specifies the y-coordinate of the cursor.  
    //
    //The following line of code does the trick by shifting 
    //the Y coordinate by 16 and ORing it with the X coordinate.

    int lParam = ((clickPos.Y << 16) | clickPos.X);

    SendMessage(hWnd, 0x0201, 0, lParam);
    System.Threading.Thread.Sleep(10); //Wait 10ms, just to be sure...
    SendMessage(hWnd, 0x0202, 0, lParam);

    //0x201 is equivalent to WM_LBUTTONDOWN, while
    //0x202 is equivalent to WM_LBUTTONUP
}


所以我想手动将鼠标事件发送到窗口,而忽略真实的光标位置。

我主要使用C#进行编码,但如果在C ++中使用它更容易,我会使用它(并且可能会创建一个dll,如果是这样的话) )。对不起,如果我很难跟进,我尽力解释这个问题。

请帮我解决这个问题!

1 个答案:

答案 0 :(得分:0)

使用Send / PostMessage时,某些窗口必须位于前景,某些窗口必须具有焦点。

在某些使用DirectX或具有特殊屏幕绘制方法的应用程序中,窗口必须位于鼠标指针下方。就在下面,而不是前景。

我不知道这究竟是为什么。

你可以试试AttachThreadInput和SetForegroundWindow / SwitchToThisWindow和SetFocus,用三种组合中的一些,它应该可以工作。