2012-07-14 68 views
0

當我這樣做時;MouseInput將鼠標移至循環開始處的左側

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

鼠標不只是向上移動..它也向左移動一點。但是如果我在一個循環中執行它,它只會在第一次迭代時移動到左側。

這是一個完整的工作控制檯程序,介紹了這個問題。您必須Add Reference -> .NET -> System.DrawingSystem.Windows.Forms才能編譯它。

當開始節目類型start移動鼠標5個像素一次或鍵入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 
     } 
    } 
} 

有人可以告訴出了什麼問題嗎?

回答

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是你的API通過Cursor.Position唱歌獲取並設置光標位置。

+0

你的新計算給出了相同的結果(指針向左移動),但SetCursorPos()完成了這個技巧。非常感謝您花時間幫忙! – natli 2012-07-14 11:01:21

0

您的項目最簡單的方法是codeplex上有用的開源庫Windows Input Simulator (C# SendInput Wrapper - Simulate Keyboard and Mouse)。用它!

+0

這不起作用。 'MouseSimulator.MoveMouseTo(startpoint.X,startpoint.Y);'無論我給出'MoveMouseTo()'什麼值,都會將光標移動到屏幕的左上角(X:17 Y:4)。 (現在在兩臺電腦上試用過,結果相同)'MoveMouseBy(0,-1)'工作得很好,但這不是我正在尋找的。我需要將它移到絕對位置。 – natli 2012-07-14 10:50:29