如何移动光标或模拟其他应用程序的点击?

我正在使用Leap Motion Controller创建一个C#Windows应用程序。 我正在Windows 8和Visual Studio 2010上进行开发。我使用来自user32.dll SetCursorPosmouse_event移动光标并模拟点击。

我希望在任何应用程序中移动光标。 当我从Visual Studio运行/调试它时,它只在应用程序本身或Visual Studio中工作。 在其他应用程序中,鼠标不移动,点击不起作用,但如果我尝试用真正的鼠标移动光标,它会返回到它所在的位置。 独立运行时,它不会在Visual Studio中移动,鼠标可以在其他应用程序中使用真正的鼠标移动。

我有这个代码使用SetCursorPosmouse_event

 [DllImport("user32.dll")] public static extern long SetCursorPos(int x, int y); [DllImport("User32.Dll")] public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo); public static void MouseClick(uint x, uint y) { mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, x, y, 0, 0); } 

在我的表单类中,我将鼠标位置存储在两个字段中。 在Timer的勾选中,我设置了光标位置,并按照以下方式进行必要的点击:

 if (!frame.Hands.IsEmpty) { Hand hand = frame.Hands.Leftmost; if (!hand.Fingers.IsEmpty) { // Get coordinates... SetCursorPos(mousex, mousey); } } foreach (Gesture gesture : gestures) { if (gesture.Type == Gesture.GestureType.TYPESCREENTAP) { MouseClick(mousex, mousey); } } 

if语句适用于Leap设备; 我想移动鼠标,只有当有手来获取坐标时才做其他东西。

是否可以移动光标或模拟其他应用程序的鼠标点击? 如果是的话,怎么样?

你激励我重构一些自动化代码:

NativeMethods.cs – 从网上得到大部分内容:

 using System; using System.Runtime.InteropServices; public class NativeMethods { [DllImport( "user32.dll", SetLastError = true )] internal static extern Int32 SendInput( Int32 cInputs, ref INPUT pInputs, Int32 cbSize ); [StructLayout( LayoutKind.Explicit, Pack = 1, Size = 28 )] internal struct INPUT { [FieldOffset( 0 )] public InputType dwType; [FieldOffset( 4 )] public MOUSEINPUT mi; [FieldOffset( 4 )] public KEYBDINPUT ki; [FieldOffset( 4 )] public HARDWAREINPUT hi; } [StructLayout( LayoutKind.Sequential, Pack = 1 )] internal struct MOUSEINPUT { public Int32 dx; public Int32 dy; public Int32 mouseData; public MOUSEEVENTF dwFlags; public Int32 time; public IntPtr dwExtraInfo; } [StructLayout( LayoutKind.Sequential, Pack = 1 )] internal struct KEYBDINPUT { public Int16 wVk; public Int16 wScan; public KEYEVENTF dwFlags; public Int32 time; public IntPtr dwExtraInfo; } [StructLayout( LayoutKind.Sequential, Pack = 1 )] internal struct HARDWAREINPUT { public Int32 uMsg; public Int16 wParamL; public Int16 wParamH; } internal enum InputType : int { Mouse = 0, Keyboard = 1, Hardware = 2 } [Flags()] internal enum MOUSEEVENTF : int { MOVE = 0x1, LEFTDOWN = 0x2, LEFTUP = 0x4, RIGHTDOWN = 0x8, RIGHTUP = 0x10, MIDDLEDOWN = 0x20, MIDDLEUP = 0x40, XDOWN = 0x80, XUP = 0x100, VIRTUALDESK = 0x400, WHEEL = 0x800, ABSOLUTE = 0x8000 } [Flags()] public enum KEYEVENTF : int { EXTENDEDKEY = 1, KEYUP = 2, UNICODE = 4, SCANCODE = 8 } /// The MapVirtualKey function translates (maps) a virtual-key code into a scan /// code or character value, or translates a scan code into a virtual-key code ///  /// [in] Specifies the virtual-key code or scan code for a key. /// How this value is interpreted depends on the value of the uMapType parameter /// [in] Specifies the translation to perform. The value of this /// parameter depends on the value of the uCode parameter. /// Either a scan code, a virtual-key code, or a character value, depending on /// the value of uCode and uMapType. If there is no translation, the return value is zero ///  [DllImport( "User32.dll", SetLastError = false, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto )] public static extern UInt32 MapVirtualKey( UInt32 uCode, MapVirtualKeyMapTypes uMapType ); /// The set of valid MapTypes used in MapVirtualKey ///  ///  public enum MapVirtualKeyMapTypes : uint { /// uCode is a virtual-key code and is translated into a scan code. /// If it is a virtual-key code that does not distinguish between left- and /// right-hand keys, the left-hand scan code is returned. /// If there is no translation, the function returns 0. ///  ///  MAPVK_VK_TO_VSC = 0x0, /// uCode is a scan code and is translated into a virtual-key code that /// does not distinguish between left- and right-hand keys. If there is no /// translation, the function returns 0. ///  ///  MAPVK_VSC_TO_VK = 0x1, /// uCode is a virtual-key code and is translated into an unshifted /// character value in the low-order word of the return value. Dead keys (diacritics) /// are indicated by setting the top bit of the return value. If there is no /// translation, the function returns 0. ///  ///  MAPVK_VK_TO_CHAR = 0x2, /// Windows NT/2000/XP: uCode is a scan code and is translated into a /// virtual-key code that distinguishes between left- and right-hand keys. If /// there is no translation, the function returns 0. ///  ///  MAPVK_VSC_TO_VK_EX = 0x3, /// Not currently documented ///  ///  MAPVK_VK_TO_VSC_EX = 0x4 } 

}

MouseInput.cs

 using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; namespace SendInput { public class MouseInput { public static void LeftClick() { DoMouse( NativeMethods.MOUSEEVENTF.LEFTDOWN, new System.Drawing.Point( 0, 0 ) ); DoMouse( NativeMethods.MOUSEEVENTF.LEFTUP, new System.Drawing.Point( 0, 0 ) ); } public static void LeftClick( int x, int y ) { DoMouse( NativeMethods.MOUSEEVENTF.MOVE | NativeMethods.MOUSEEVENTF.ABSOLUTE, new System.Drawing.Point( x, y ) ); DoMouse( NativeMethods.MOUSEEVENTF.LEFTDOWN, new System.Drawing.Point( x, y ) ); DoMouse( NativeMethods.MOUSEEVENTF.LEFTUP, new System.Drawing.Point( x, y ) ); } public static void ClickBoundingRectangleByPercentage( int xPercentage, int yPercentage, System.Drawing.Rectangle bounds ) { double additional = 0.0; if ( xPercentage == 99 ) additional = 0.5; int xPixel = Convert.ToInt32( bounds.Left + bounds.Width * ( xPercentage + additional ) / 100 ); int yPixel = Convert.ToInt32( bounds.Top + bounds.Height * ( yPercentage ) / 100 ); LeftClick( xPixel, yPixel ); } public static void RightClick() { DoMouse( NativeMethods.MOUSEEVENTF.RIGHTDOWN, new System.Drawing.Point( 0, 0 ) ); DoMouse( NativeMethods.MOUSEEVENTF.RIGHTUP, new System.Drawing.Point( 0, 0 ) ); } public static void RightClick( int x, int y ) { DoMouse( NativeMethods.MOUSEEVENTF.MOVE | NativeMethods.MOUSEEVENTF.ABSOLUTE, new System.Drawing.Point( x, y ) ); DoMouse( NativeMethods.MOUSEEVENTF.RIGHTDOWN, new System.Drawing.Point( x, y ) ); DoMouse( NativeMethods.MOUSEEVENTF.RIGHTUP, new System.Drawing.Point( x, y ) ); } public static void MoveMouse( Point p ) { MoveMouse( pX, pY ); } public static void MoveMouse( System.Windows.Point p ) { MoveMouse( Convert.ToInt32( pX ), Convert.ToInt32( pY ) ); } public static void MoveMouse( int x, int y ) { DoMouse( NativeMethods.MOUSEEVENTF.MOVE | NativeMethods.MOUSEEVENTF.ABSOLUTE, new System.Drawing.Point( x, y ) ); } public static System.Drawing.Point GetMousePosition() { return Cursor.Position; } public static void ScrollWheel( int scrollSize ) { DoMouse( NativeMethods.MOUSEEVENTF.WHEEL, new System.Drawing.Point( 0, 0 ), scrollSize ); } private static void DoMouse( NativeMethods.MOUSEEVENTF flags, Point newPoint, int scrollSize = 0 ) { NativeMethods.INPUT input = new NativeMethods.INPUT(); NativeMethods.MOUSEINPUT mi = new NativeMethods.MOUSEINPUT(); input.dwType = NativeMethods.InputType.Mouse; input.mi = mi; input.mi.dwExtraInfo = IntPtr.Zero; // mouse co-ords: top left is (0,0), bottom right is (65535, 65535) // convert screen co-ord to mouse co-ords... input.mi.dx = newPoint.X * 65535 / Screen.PrimaryScreen.Bounds.Width; input.mi.dy = newPoint.Y * 65535 / Screen.PrimaryScreen.Bounds.Height; input.mi.time = 0; input.mi.mouseData = scrollSize * 120; // can be used for WHEEL event see msdn input.mi.dwFlags = flags; int cbSize = Marshal.SizeOf( typeof ( NativeMethods.INPUT ) ); int result = NativeMethods.SendInput( 1, ref input, cbSize ); if ( result == 0 ) Debug.WriteLine( Marshal.GetLastWin32Error() ); } } } 

是的,您想使用“SendInput”function。

请参阅: 除非我移动光标,否则SendInput不会执行鼠标单击按钮

也,

http://www.pinvoke.net/default.aspx/user32.sendinput

http://www.pinvoke.net/default.aspx/Structures/INPUT.html

我修复了第一个超链接 – 请参阅以下评论:

使用SendInput函数时,您应该考虑一些事项。

如果未指定MOUSEEVENTF_ABSOLUTE标志,则dx和dy(MouseInputData结构)是当前鼠标位置的相对坐标。 如果确实指定了MOUSEEVENTF_ABSOLUTE,则dx和dy是0到65535之间的绝对坐标。因此,如果x和y坐标是屏幕坐标,则应使用以下函数计算dx和dy:

http://msdn.microsoft.com/en-us/library/ms646310%28VS.85%29.aspx

我设法自己解决了这个问题。

有两个问题。 第一个(也是主要的)是Leap设备在后台运行时没有向我的应用程序发送帧。 通过将此代码添加到侦听器的onConnect()方法来解决这个问题,如下所示:

 controller.SetPolicyFlags(Controller.PolicyFlag.POLICYBACKGROUNDFRAMES); 

第二个问题是,当独立运行时,应用程序无权将输入发送到其他应用程序。 我按照这里的说明(向下滚动,有关于uiAccess的信息),然后在这里签署我的应用程序并将其添加到清单中: