Как может работать несколько курсоров на одном клиенте Windows?

Недавно я искал в Интернете решения с несколькими курсорами и нашел множество возможностей для эмуляции курсоров в данном окне, например, MultiPoint SDK, но не было решений, где можно использовать несколько курсоров на всем рабочем столе (и, следовательно, не ограничиваться одним приложением).,

Я почти сдался, думая, что архитектура Windows делает это невозможным, но потом я обнаружил, что MultiMouse, заявив в этом видео на YouTube, что, по крайней мере, позволит использовать разные курсоры для разных пользователей на всем рабочем столе. Если это так, из этого следует, что можно эмулировать нескольких пользователей, что делает возможным решение с несколькими курсорами.

Итак, мои вопросы:

  • Кто-то здесь использует Multimouse, и он действительно работает, как описано?
  • Как это работает, кто-то может использовать Windows API, или необходимо перенастроить Windows для этого?
  • У вас есть идеи о том, как рисовать и управлять несколькими курсорами в Windows 7? Проблема в том, что есть только один указатель мыши. Кто-то может это изменить или что делают удаленные приложения? Я имею в виду, что было бы достаточно просто показать курсоры (глобально) и управлять ими автоматически.
  • Я могу свободно использовать любые методы взаимодействия, независимо от того, насколько они грязные, поскольку достаточно, если мое приложение работает только на Windows 7. Знает ли кто-нибудь библиотеки Windows, которые могли бы обеспечить такую ​​функциональность? К сожалению, API окон плохо документирован.

Изменить: далее я объясню, как частично работают сообщения Windows, но почему они вообще не работают. Во-первых, мы берем в качестве примера флеш-клиент, который является дескриптором с дочерним элементом, а его дочерний элемент является флеш-объектом. Всякий раз, когда в области флэш-памяти выполняется щелчок, появляются следующие сообщения Windows:

<000001> 00100354 S WM_PARENTNOTIFY fwEvent: WM_LBUTTON xPos: [x] yPos: [y]

<000002> 00100354 R WM_PARENTNOTIFY

<000003> 001B09D6 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

<000006> 001B09D6 R 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 - дочерним (флэш-объект). Так случилось, что родитель говорит ребенку нажать на определенную позицию ([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 ответ

Если вы ищете решение, имеющее объект, похожий на указатель, который перемещается на рабочем столе, у меня может быть идея для " грязного " решения, но я хочу предупредить вас, что это должен быть ваш последний выбор. Это действительно грязно и опрометчиво. (Я сделал что-то подобное, когда я был настоящим новичком, и я никогда не буду делать это снова.)


Итак, вот сделка:

Вы можете создать самую верхнюю маленькую форму, которая имеет форму указателя мыши. Затем его можно программно перемещать по экрану. Щелчки / двойные клики / зависания можно эмулировать с помощью специальных возможностей или сообщений Windows (оба решения имеют свои особенности, поэтому выбирайте разумно).

Специальные возможности предоставляют несколько стандартизированный способ доступа к формам и элементам управления, и это было бы рекомендуемым решением, но есть проблема: не все программы Windows поддерживают специальные возможности (особенно старые программы и игры), поэтому некоторые из них не будут реагировать на фальшивый указатель.

Сообщения Windows - это неуправляемый путь Win32, если вы хотите что-то подобное. В этом случае вы можете отправлять сообщения мыши (WM_CAPTURECHANGED WM_LBUTTONDBLCLK WM_LBUTTONDOWN WM_LBUTTONUP WM_MBUTTONDOWN WM_MBUTTONUP WM_MOUSEMOVE WM_MOUSEWHEEL WM_RBUTTONDOWN WM_RBUTTON под вашим курсором, чтобы поднять курсор под вашим курсом). В этом решении есть предостережение, что вы должны вызывать неуправляемый API пост-сообщений.


Какое бы решение из перечисленного выше вы не использовали, будьте готовы к тому, что некоторые программы будут управлять курсором напрямую, поэтому некоторые программы будут вести себя странно.

Другие вопросы по тегам