我最近在网上搜索了多光标解决方案,并发现了在给定窗口中模拟游标的一堆可能性,如MultiPoint SDK,但没有解决方案,在整个桌面上可以使用多个游标(因此不限于一个应用程序)。我几乎放弃了,认为Windows体系结构使它不可能,但后来我发现MultiMouse,在YouTube上声明this视频,它至少可以在整个桌面上为不同的用户使用不同的游标。如果这是真的,那么可以模拟多个用户,从而使多个游标解决方案成为可能。它如何在一个Windows客户端上使用多个游标?
所以我的问题是:
- 是否有人在这里使用Multimouse和描述是不是真的工作?
- 它是如何工作的,有人可以使用Windows API,或需要重新配置Windows来做到这一点?
- 对于如何在Windows 7上绘制和命令多个游标有任何想法吗?问题是,只有一个鼠标指针。有人可以改变这一点,或者远程应用程序正在做什么?我的意思是,只显示光标(全局)并自动控制它们就足够了。
- 我可以自由地使用任何互操作技术,不管它们有多脏,因为如果我的应用程序仅在Windows 7上运行就足够了。有人知道可以提供此类功能的Windows库吗?可惜的是,windows api文档记录很差。
编辑: 在下面我将介绍如何窗口消息部分工作,但为什么他们不一般的事。首先,我们以一个Flash客户端为例,这是一个带有子对象的句柄,它的子对象是一个Flash对象。每当在闪蒸区域的任意位置进行点击,下面的窗口消息显示:
< 000001> 00100354小号WM_PARENTNOTIFY fwEvent:WM_LBUTTON XPOS:[X] yPos:[Y]
< 000002> 00100354řWM_PARENTNOTIFY
< 000003> 001B09D6小号WM_MOUSEACTIVATE hwndTopLevel:00100354 nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN
< 000004> 00100354小号WM_MOUSEACTIVATE hwndTopLevel:0 0100354 nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN
< 000005> 00100354řWM_MOUSEACTIVATE fuActivate:MA_ACTIVATE
< 000006> 001B09D6řWM_MOUSEACTIVATE fuActivate:MA_ACTIVATE
< 000007> 001B09D6 P WM_LBUTTONDOWN fwKeys:MK_LBUTTON XPOS:[X ] yPos:[Y]
< 000008> 001B09D6 P WM_LBUTTONUP fwKeys:0000 XPOS:[X] yPos:[Y]
在此示例中,00100354是父级,001B09D6是子级(Flash对象)。所以它发生,父母告诉孩子点击某个位置([x],[y])。但是,使用Windows消息的假冒点击解决方案无法知道它必须点击哪个处理。如果点击或通知只发送到00100354,则不会发生任何事情。我们试图完成的是消息< 000007>和< 000008>,但除了通过向前台句柄的所有后代(包括前台句柄本身)发送垃圾消息,我们不能。但这也可能导致我们不想要的点击。我们无法执行命中测试,因为目标应用可能有目标手柄前面的透明手柄。请注意,如果子句柄未位于其父级的(0,0)处,则还需要计算新的相对坐标。
为了实现通信,如上所示,可以使用Win32调用,例如:
[DllImport("User32.dll", SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
public static extern bool PostMessage(IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam);
[...]
public static IntPtr ToWMCoords(Point pt)
{
return (IntPtr)(((uint)pt.Y << 16) | (ushort)pt.X);
}
[...]
foreach (Point pt in coordinates)
{
Console.Write("Message-Clicking at " + pt + "\n");
IntPtr mousePos = ToWMCoords(pt);
//# Get flash handle
//## Variation, assuming the client has always only 1 child with class name "MacromediaFlashPlayerActiveX"
IntPtr flashHwnd = Interop.GetChildWindows(hwnd).Where(x => Interop.GetClassNameOfHandle(x) == "MacromediaFlashPlayerActiveX").Single();
//# Simulating a click
//*1: Messages getting to handle of class "#32770 (Dialog)"
//*2: Messages getting to handle of class "MacromediaFlashPlayerActiveX"
Interop.User32.SendMessage(hwnd, Interop.WM.PARENTNOTIFY, (IntPtr)0x201, mousePos);//*1
Interop.User32.SendMessage(flashHwnd, Interop.WM.MOUSEACTIVATE, hWnd, (IntPtr)0x2010001);//*2
Interop.User32.SendMessage(hwnd, Interop.WM.MOUSEACTIVATE, hWnd, (IntPtr)0x2010001);//*1
bool lBtnDown = Interop.User32.PostMessage(flashHwnd, Interop.WM.LBUTTONDOWN, (IntPtr)Interop.MK.LBUTTON, mousePos);//*2
bool lBtnUp = Interop.User32.PostMessage(flashHwnd, Interop.WM.LBUTTONUP, IntPtr.Zero, mousePos);//*2
Console.Write("WM_LBUTTONDOWN " + (lBtnDown ? "success" : "fail") + ", WM_LBUTTONUP " + (lBtnDown ? "success" : "fail") + "\n");
}
总之,根据目标应用程序,使用Windows消息伪造鼠标输入似乎是不正确或不可能的。
在阅读Multimouse手册 - **请注意,我没有使用实际产品** - 我强烈怀疑它只使用我在[我的答案中描述的技术之一来伪造额外的游标](http://stackoverflow.com/a/25550951/2144232)。但再一次,这只是一个怀疑。 – mg30rg 2014-08-29 12:59:29
我也开始认为:(但它会使他们的工具非常糟糕,我认为一个好方法是检查一下,使用一个绘图工具作为mspaint,并且一次绘制多于一个的光标。 。如果它工作的话,该工具并不是伪装的(即使mspaint由于输入信息太多而表现怪异)。如果它只与一个用户绘图一起工作,那么当一个用户执行一个动作时,可能会使用真正的光标。如果它从来没有工作,它是一个很大的假,使用简单的Windows消息。 – xamid 2014-08-29 17:33:29
我认为这个想法一般不错,但我会使用其他工具,因为我不确定MsPaint是否使用[多点SDK控件](http://msdn.microsoft.com/zh-cn/library/ windows/desktop/ee906605.aspx),它可以处理多个鼠标输入,但对你来说没有用处,因为它们的范围是它们内置的应用程序(即使在那里它们也很蹩脚:即像文本框滚动条那样的嵌入式控件没有工作)。 – mg30rg 2014-09-01 08:32:00