本文介绍了如何在一个Windows客户端上使用多个游标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在网络上搜索多光标解决方案,并发现了一堆在给定窗口中模拟游标的可能性,例如,但没有解决方案,可以在整个桌面上使用多个游标(因此不限于一个应用程序)。

I recently searched the web for multi-cursor solutions and found a bunch of possibilities to emulate cursors in a given window, like MultiPoint SDK, but no solutions where one can use multiple cursors on the whole desktop (and thus not restricted to one application).

我几乎放弃了,认为Windows架构不可能,但后来我发现了,说明在YouTube上的视频中,至少可以为不同的视频使用不同的光标用户在整个桌面上。如果这是真的,那么可以模仿多个用户,从而使多光标解决方案成为可能。

I almost gave up, thinking the Windows architecture makes it impossible, but then I found MultiMouse, stating in this video on YouTube, it would at least make it possible to use different cursors for different users over the whole desktop. If that is true, it follows that one could emulate multiple users and thereby making a multiple cursors solution possible.

所以我的问题是:


  • 有人在这里使用Multimouse,是否真的如上所述工作?

  • 如何工作,有人可以使用windows api,或需要重新配置Windows以执行此操作?

  • 有关如何在Windows 7上绘制和命令多个游标的任何想法吗?问题是,只有一个鼠标指针。有人可以改变,或者什么是远程应用程序做什么?

  • 我可以自由地使用任何互操作技术,无论它们有多脏,因为它足够了如果我的应用程序只在Windows 7上运行。有人知道可以提供这样的功能的Windows库吗?很遗憾,windows api文档记录不良。

  • Does someone here use Multimouse and is it really working as described?
  • How does it work, can someone use the windows api, or needs to reconfigure Windows to do so?
  • Have you any ideas on how to draw and command multiple cursors on Windows 7? Problem is, there is only one mouse pointer. Can someone change that, or what are remote applications doing? I mean, it would suffice to just show the cursors (globally) and control them automatically.
  • I'm free to use any interop techniques, no matter how dirty they are, since it suffices if my app runs only on Windows 7. Does someone know windows libraries which could provide such functionality? Sadly, the windows api is poorly documented.

编辑:解释Windows消息如何部分工作,但为什么他们不做一般。首先,我们以一个flash客户端为例,这是一个带有孩子的句柄,它的孩子是一个flash对象。每当在闪存区域的任何地方执行点击时,以下窗口消息显示:

In the following I will explain how windows messages partially work, but why they don't do in general. First, we take a flash client as an example, that is a handle with a child, and it's child is a flash object. Whenever a click is performed anywhere at the flash area, the following windows messages show up:

< 000002> 00100354 R WM_PARENTNOTIFY

<000002> 00100354 R WM_PARENTNOTIFY

< 000003 > 001B09D6 S WM_MOUSEACTIVATE hwndTopLevel:00100354 nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN

<000003> 001B09D6 S WM_MOUSEACTIVATE hwndTopLevel:00100354 nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN

< 000004> 00100354 S WM_MOUSEACTIVATE hwndTopLevel:00100354 nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN

<000004> 00100354 S WM_MOUSEACTIVATE hwndTopLevel:00100354 nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN

< 000005> 00100354 R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE

<000005> 00100354 R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE

< 000006> 001B09D6 R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE

<000006> 001B09D6 R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE

< 000007> 001B09D6 P WM_LBUTTONDOWN fwKeys:MK_LBUTTON xPos:[x] yPos:[y]

<000007> 001B09D6 P WM_LBUTTONDOWN fwKeys:MK_LBUTTON xPos:[x] yPos:[y]

< 000008> 001B09D6 P WM_LBUTTONUP fwKeys:0000 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),则还需要计算新的相对坐标。

In this example 00100354 is the parent and 001B09D6 is the child (flash object). So it happens, that the parent tells the child to click at a certain position ([x],[y]). But a faking click solution working with windows messages could never know which handle it has to click. If the clicks or notifications are only sent to 00100354, nothing happens. What we are trying to accomplish are the messages <000007> and <000008>, but we can't, except by spamming messages to all descendants of the foreground handle, including the foreground handle itself. But this could also lead to clicks we don't want. We cannot perform a hit test since the target application may have e.g. transparent handles in front of the target handle. Note that one also needs to calculate new relative coordinates if a child handle is not positioned at (0,0) of its parent.

为了实现如上所示的通信,可以使用Win32调用,像这样:

To realize communication as shown above, one can use Win32 calls, like this:

[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消息伪造鼠标输入似乎不正确或不可能,取决于目标应用程序。

In summary, faking mouse input using windows messages appears to be improperly or impossible, depending on the target application.

推荐答案

如果你正在寻找一个解决方案有一个类似指针的对象在桌面上移动,我可能会想到一个解决方案,但是我想警告你,这应该是你的最后一个选择。这是真的肮脏和不明智。 (我是一个真正的初学者,我做了这样的事情,我再也不会这样做了。)

If you are looking for a solution to have a pointer-like object that is moved around on the desktop, I might have an idea for a "dirty" solution, but I wish to warn you that this should be your last choice. It is real dirty and ill-advised. (I did something like this when I was a real beginner and I would never do it again.)

所以这里是交易:

你可能创建一个最顶端的小形式,它是鼠标指针形状。然后它可以在屏幕上以编程方式移动。点击/双击/悬停可以通​​过辅助功能或通过Windows消息(两个解决方案都有自己的caveeats,所以选择明智地)模拟。

You might create a topmost little form which is mouse pointer-shaped. It then can be programmatically moved around the screen. The clicks/doubleclicks/hovering can be emulated through accessibility or through windows messages (both solutions have their own caveeats, so choose wisely).

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

Accessibility provides a somewhat standardized way to access forms and controls, and would be the recommended solution but there is a problem: Not all windows programs support accessibility (especially older software and games), so some of them will not respond to the fake pointer.

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

Windows messages are the unmanaged Win32 way to go if you want something like that. In that case you can send mouse messages (WM_CAPTURECHANGED WM_LBUTTONDBLCLK WM_LBUTTONDOWN WM_LBUTTONUP WM_MBUTTONDOWN WM_MBUTTONUP WM_MOUSEMOVE WM_MOUSEWHEEL WM_RBUTTONDOWN WM_RBUTTONUP) to the form under your fake cursor. This solution has the caveeat, that you have to invoke the non-managed postmessage API.

你正在使用准备好一些程序直接管理光标,所以一些软件会很奇怪。

Whatever solution form the above listed you are using be prepared that some programs manage the cursor directly, so some software will act weird.

这篇关于如何在一个Windows客户端上使用多个游标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 01:28
查看更多