0

私がこれをするとき;

Point startpoint = Cursor.Position;
startpoint.Y -= 1;
DoMouse(MOUSEEVENTF.MOVE | MOUSEEVENTF.ABSOLUTE, startpoint);

マウスは上に移動するだけでなく、左にも少し移動します。しかし、ループで実行すると、最初の繰り返しで左にしか移動しません。

これは、問題を提示する完全に機能するコンソール プログラムです。コンパイルする必要がありAdd Reference -> .NET -> System.Drawingます。System.Windows.Forms

プログラムの起動時startに、マウスを 5 ピクセル上に 1 回移動するかstart X、(X は数字) と入力して、マウスを 5 ピクセル上に X 回移動します。新しいループごとに、マウスが少し左に移動することがわかります。まったくそうすべきではありません。

using System;
using System.Text.RegularExpressions;
using System.Threading;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace mousemove_temp
{
    class Program
    {
        //Capture user input
        static void Main(string[] args)
        {
            while (true)
            {
                string s = Console.ReadLine();

                switch (s)
                {
                    case("start"):
                        moveMouseTest(1);
                        break;
                    default:
                        //Get # of times to run function
                        Match match = Regex.Match(s, @"start (.+)", RegexOptions.IgnoreCase);
                        if (!match.Success || match.Groups.Count != 2) break;

                        //Copy # to int
                        int amnt = -1;
                        try
                        {
                            amnt = Int32.Parse(match.Groups[1].Value);
                        }
                        catch (Exception) { break; } //fail
                        if (amnt <= -1) break; //fail
                        moveMouseTest(amnt); //aaaawww yeah

                        break;
                }

                Thread.Sleep(10);
            }
        }

        //Move the mouse
        static void moveMouseTest(int repeat)
        {
            int countrepeat = 0;

            //Loop entire function X times
            while (countrepeat < repeat)
            {
                Point startpoint = Cursor.Position;
                int amount = 5; //Move 5 pixels
                int counter = 0;

                //Move 1 pixel up each loop
                while (counter < amount)
                {
                    startpoint.Y -= 1;
                    DoMouse(MOUSEEVENTF.MOVE | MOUSEEVENTF.ABSOLUTE, startpoint);

                    counter++;
                    Thread.Sleep(100); //Slow down so you can see it only jumps left the first time
                }

                countrepeat++;
                Console.WriteLine(String.Format("{0}/{1}", countrepeat, repeat));
                Thread.Sleep(1000); //Wait a second before next loop
            }
        }

        /*
         * Function stuff 
        */

        //Control the Mouse
        private static object mouselock = new object(); //For use with multithreading
        public static void DoMouse(MOUSEEVENTF flags, Point newPoint)
        {
            lock (mouselock)
            {
                INPUT input = new INPUT();
                MOUSEINPUT mi = new MOUSEINPUT();
                input.dwType = 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 = 0;
                // can be used for WHEEL event see msdn
                input.mi.dwFlags = flags;
                int cbSize = Marshal.SizeOf(typeof(INPUT));
                int result = SendInput(1, ref input, cbSize);
                if (result == 0)
                    Console.WriteLine("DoMouse Error:" + Marshal.GetLastWin32Error());
            }
        }

        /*
         * Native Methods 
        */

        [DllImport("user32.dll", SetLastError = true)]
        static internal extern Int32 SendInput(Int32 cInputs, ref INPUT pInputs, Int32 cbSize);

        [DllImport("user32.dll")]
        public static extern bool GetAsyncKeyState(Int32 vKey);

        [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()]
        internal enum KEYEVENTF : int
        {
            EXTENDEDKEY = 1,
            KEYUP = 2,
            UNICODE = 4,
            SCANCODE = 8
        }
    }
}

何が問題なのか誰にもわかりますか?

4

2 に答える 2

1

計算が間違っているため、丸め誤差が発生します。

たとえば、65535 / 1920 = 34.1328125 です。しかし、切り捨て (int を int で割っているため) の結果は 34 になります。したがって、1920x1080 の画面でマウスを一番右に置いた場合、1920 * (65535 / 1920) = 1920 * 34 = となります。 65280。

これにより、より良い結果が得られます。

            input.mi.dx = (int)((65535.0f * (newPoint.X / (float)Screen.PrimaryScreen.Bounds.Width)) + 0.5f);
            input.mi.dy = (int)((65535.0f * (newPoint.Y / (float)Screen.PrimaryScreen.Bounds.Height)) + 0.5f);

ただし、単に言うのではなく P/Invoke を使用することに決めた場合

Cursor.Position = new Point(newPoint.X, newPoint.Y);

次に、実際に SetCursorPos を使用する必要があります - http://msdn.microsoft.com/en-us/library/windows/desktop/ms648394(v=vs.85).aspx - それは (GetCursorPos とともに) . NET は、Cursor.Position を介してカーソル位置を取得および設定するために使用しています。

于 2012-07-14T10:51:56.143 に答える
0

プロジェクトの最も簡単な方法は、codeplex 上の便利なオープンソース ライブラリWindows 入力シミュレーター (C# SendInput ラッパー - キーボードとマウスのシミュレート)です。これを使って!

于 2012-07-14T10:22:51.397 に答える