2014-08-28 23 views
0

我最近在网上搜索了多光标解决方案,并发现了在给定窗口中模拟游标的一堆可能性,如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消息伪造鼠标输入似乎是不正确或不可能的。

+1

在阅读Multimouse手册 - **请注意,我没有使用实际产品** - 我强烈怀疑它只使用我在[我的答案中描述的技术之一来伪造额外的游标](http://stackoverflow.com/a/25550951/2144232)。但再一次,这只是一个怀疑。 – mg30rg 2014-08-29 12:59:29

+0

我也开始认为:(但它会使他们的工具非常糟糕,我认为一个好方法是检查一下,使用一个绘图工具作为mspaint,并且一次绘制多于一个的光标。 。如果它工作的话,该工具并不是伪装的(即使mspaint由于输入信息太多而表现怪异)。如果它只与一个用户绘图一起工作,那么当一个用户执行一个动作时,可能会使用真正的光标。如果它从来没有工作,它是一个很大的假,使用简单的Windows消息。 – xamid 2014-08-29 17:33:29

+0

我认为这个想法一般不错,但我会使用其他工具,因为我不确定MsPaint是否使用[多点SDK控件](http://msdn.microsoft.com/zh-cn/library/ windows/desktop/ee906605.aspx),它可以处理多个鼠标输入,但对你来说没有用处,因为它们的范围是它们内置的应用程序(即使在那里它们也很蹩脚:即像文本框滚动条那样的嵌入式控件没有工作)。 – mg30rg 2014-09-01 08:32:00

回答

0

如果你正在寻找一个解决方案,有被移动周围的桌面上的指针般的物体,我可能有一个“”解决方案的想法,但我想提醒你,这应该是你的最后选择。这是真正的肮脏和不明智的。 (我做了这样的事情时,我是一个真正的初学者,我永远不会再这样做。)


因此,这里的交易:

您可以创建一个最上面的小表单,这是鼠标指针-成形。然后它可以通过程序在屏幕上移动。点击/双击/悬停可以通​​过可访问性或通过Windows消息来模拟(两种解决方案都有自己的洞穴,所以要明智地选择)。

辅助功能提供了一种有点标准化的方式来访问窗体和控件,并且会是推荐的解决方案,但有一个问题:并不是所有的Windows程序都支持辅助功能(特别是较旧的软件和游戏),所以有些不会响应假指针。

如果你想要类似的东西,Windows消息是非托管Win32方式。在这种情况下,您可以发送鼠标消息(WM_CAPTURECHANGED WM_LBUTTONDBLCLK WM_LBUTTONDOWN WM_LBUTTONUP WM_MBUTTONDOWN WM_MBUTTONUP WM_MOUSEMOVE WM_MOUSEWHEEL WM_RBUTTONDOWN WM_RBUTTONUP)到虚假游标下的表单。这个解决方案有一个窍门,那就是你必须调用非托管的postmessage API。


什么解决方案形成上述所列您使用做好准备,有些程序直接管理的游标,因此一些软件将采取行动怪异。

+0

但是真的......只有在没有其他解决方案的情况下才能做到这一点。我不知道Windows是否支持多个游标,而我的解决方案只能帮助伪造一个游标。 – mg30rg 2014-08-28 14:25:30

+0

感谢您的回答,但这不是我所期待的。这是相当微不足道的假解决方案,我试图通过提出这个问题来避免。该解决方案还存在更多问题,例如Windows消息无法模拟Windows输入,如[在此解释](http://blogs.msdn.com/b/oldnewthing/archive/2011/07/28/10190521.aspx) 。 – xamid 2014-08-29 11:57:45

+0

@xamid - 这就是为什么我建议使用任何其他解决方案,如果有的话。 **(据我所知没有。)**另外你链接的旧新文章只提到字符输入,这是有原因的。大多数应用程序通过Windows消息处理鼠标事件,因此可以使用我的解决方案。直接处理键盘输入是非常普遍的做法,但直接处理鼠标并不常见。 – mg30rg 2014-08-29 12:13:52