示例#1
0
        /**************************************************************************************************************************/
        /* Credit where credit is due: SendMouseInput shamelessly taken from UI Verify - http://uiautomationverify.codeplex.com/ */
        /**************************************************************************************************************************/

        /// <summary>
        /// Inject pointer input into the system
        /// </summary>
        /// <param name="x">x coordinate of pointer, if Move flag specified</param>
        /// <param name="y">y coordinate of pointer, if Move flag specified</param>
        /// <param name="data">wheel movement, or mouse X button, depending on flags</param>
        /// <param name="flags">flags to indicate which type of input occurred - move, button press/release, wheel move, etc.</param>
        /// <exception cref="ProdOperationException">Thrown if Security permissions won't allow execution</exception>
        ///
        /// <exception cref="Win32Exception">Thrown if SendInput call fails</exception>
        ///
        /// <outside_see conditional="false">
        /// This API does not work inside the secure execution environment.
        ///   <exception cref="System.Security.Permissions.SecurityPermission"/>
        ///   </outside_see>
        /// <remarks>
        /// x, y are in pixels. If Absolute flag used, are relative to desktop origin.
        /// </remarks>
        internal static void SendMouseInput(double x, double y, int data, MOUSEEVENTF flags)
        {
            int intflags = (int)flags;

            try
            {
                if ((intflags & (int)MOUSEEVENTF.MOUSEEVENTFABSOLUTE) != 0)
                {
                    int vscreenWidth  = NativeMethods.GetSystemMetrics((int)SystemMetric.SMCXVIRTUALSCREEN);
                    int vscreenHeight = NativeMethods.GetSystemMetrics((int)SystemMetric.SMCYVIRTUALSCREEN);
                    int vscreenLeft   = NativeMethods.GetSystemMetrics((int)SystemMetric.SMXVIRTUALSCREEN);
                    int vscreenTop    = NativeMethods.GetSystemMetrics((int)SystemMetric.SMYVIRTUALSCREEN);

                    // Absolute input requires that input is in 'normalized' coords - with the entire
                    // desktop being (0,0)...(65535,65536). Need to convert input x,y coords to this
                    // first.
                    //
                    // In this normalized world, any pixel on the screen corresponds to a block of values
                    // of normalized coords - eg. on a 1024x768 screen,
                    // y pixel 0 corresponds to range 0 to 85.333,
                    // y pixel 1 corresponds to range 85.333 to 170.666,
                    // y pixel 2 corresponds to range 170.666 to 256 - and so on.
                    // Doing basic scaling math - (x-top)*65536/Width - gets us the start of the range.
                    // However, because int math is used, this can end up being rounded into the wrong
                    // pixel. For example, if we wanted pixel 1, we'd get 85.333, but that comes out as
                    // 85 as an int, which falls into pixel 0's range - and that's where the pointer goes.
                    // To avoid this, we add on half-a-"screen pixel"'s worth of normalized coords - to
                    // push us into the middle of any given pixel's range - that's the 65536/(Width*2)
                    // part of the formula. So now pixel 1 maps to 85+42 = 127 - which is comfortably
                    // in the middle of that pixel's block.
                    // The key ting here is that unlike points in coordinate geometry, pixels take up
                    // space, so are often better treated like rectangles - and if you want to target
                    // a particular pixel, target its rectangle's midpoint, not its edge.
                    x = ((x - vscreenLeft) * 65536) / vscreenWidth + 65536 / (vscreenWidth * 2);
                    y = ((y - vscreenTop) * 65536) / vscreenHeight + 65536 / (vscreenHeight * 2);

                    intflags |= (int)MOUSEEVENTF.MOUSEEVENTFVIRTUALDESK;
                }

                NPUT mi = new NPUT
                {
                    Type = (int)InputStructType.InputMouse
                };
                mi.Union.MouseInput.DX          = (int)x;
                mi.Union.MouseInput.DY          = (int)y;
                mi.Union.MouseInput.MouseData   = data;
                mi.Union.MouseInput.DWFlags     = intflags;
                mi.Union.MouseInput.Time        = 0;
                mi.Union.MouseInput.DWExtraInfo = new IntPtr(0);

                if (NativeMethods.SendInput(1, ref mi, Marshal.SizeOf(mi)) == 0)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            catch (Exception e)
            {
                throw new ProdOperationException(e.Message, e);
            }
        }
示例#2
0
 internal static extern int SendInput(uint nInputs, ref NPUT pInputs, int cbSize);