2011-11-05 11 views
22

Funkcja SendInput nie wykonuje kliknięcia przyciskiem myszy, chyba że przesuę kursor.Funkcja SendInput nie wykonuje kliknięcia przyciskiem myszy, chyba że poruszę kursor

Byłbym wdzięczny za pomoc w tej sprawie, ponieważ wydaje mi się, że nie mogę tego objąć.

Mam program, który wykonuje kliknięcie myszą w oknie pierwszego planu, w którym używam SendInput do emulowania kliknięcia lewym przyciskiem myszy. Problem polega na tym, że jeśli przesuniemy kursor do pozycji kliknięcia, to SendInput spowoduje kliknięcie, jednak jeśli nie będę przesuwał kursora, to nie dojdzie do żadnego kliknięcia, nawet gdy przechodzę xiy wskazuje na MouseInputData. Chciałbym wykonać lewy przycisk myszy bez potrzeby faktycznego przesuwania kursora.

Bellow jest klasa mam (to dość proste i stright przodu)

namespace StackSolution.Classes 
{ 
    public static class SendInputClass 
    { 

     [DllImport("user32.dll", SetLastError = true)] 
     static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); 

     [DllImport("user32.dll")] 
     static extern bool SetCursorPos(int X, int Y); 

     [DllImport("user32.dll")] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     static extern bool GetCursorPos(out Point lpPoint); 



     [StructLayout(LayoutKind.Sequential)] 
     struct INPUT 
     { 
      public SendInputEventType type; 
      public MouseKeybdhardwareInputUnion mkhi; 
     } 
     [StructLayout(LayoutKind.Explicit)] 
     struct MouseKeybdhardwareInputUnion 
     { 
      [FieldOffset(0)] 
      public MouseInputData mi; 

      [FieldOffset(0)] 
      public KEYBDINPUT ki; 

      [FieldOffset(0)] 
      public HARDWAREINPUT hi; 
     } 
     [StructLayout(LayoutKind.Sequential)] 
     struct KEYBDINPUT 
     { 
      public ushort wVk; 
      public ushort wScan; 
      public uint dwFlags; 
      public uint time; 
      public IntPtr dwExtraInfo; 
     } 
     [StructLayout(LayoutKind.Sequential)] 
     struct HARDWAREINPUT 
     {   
      public int uMsg; 
      public short wParamL; 
      public short wParamH; 
     } 
     struct MouseInputData 
     { 
      public int dx; 
      public int dy; 
      public uint mouseData; 
      public MouseEventFlags dwFlags; 
      public uint time; 
      public IntPtr dwExtraInfo; 
     } 
     [Flags] 
     enum MouseEventFlags : uint 
     { 
      MOUSEEVENTF_MOVE = 0x0001, 
      MOUSEEVENTF_LEFTDOWN = 0x0002, 
      MOUSEEVENTF_LEFTUP = 0x0004, 
      MOUSEEVENTF_RIGHTDOWN = 0x0008, 
      MOUSEEVENTF_RIGHTUP = 0x0010, 
      MOUSEEVENTF_MIDDLEDOWN = 0x0020, 
      MOUSEEVENTF_MIDDLEUP = 0x0040, 
      MOUSEEVENTF_XDOWN = 0x0080, 
      MOUSEEVENTF_XUP = 0x0100, 
      MOUSEEVENTF_WHEEL = 0x0800, 
      MOUSEEVENTF_VIRTUALDESK = 0x4000, 
      MOUSEEVENTF_ABSOLUTE = 0x8000 
     } 
     enum SendInputEventType : int 
     { 
      InputMouse, 
      InputKeyboard, 
      InputHardware 
     } 

     public static void ClickLeftMouseButton(int x, int y) 
     { 
      INPUT mouseInput = new INPUT(); 
      mouseInput.type = SendInputEventType.InputMouse; 
      mouseInput.mkhi.mi.dx = x; 
      mouseInput.mkhi.mi.dy = y; 
      mouseInput.mkhi.mi.mouseData = 0; 

      //getting current cursor location 
      Point p; 
      if (GetCursorPos(out p)) 
       SetCursorPos(x, y); 


      mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN; 
      SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT())); 

      mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP; 
      SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT())); 

      //returning cursor to previous position 
      SetCursorPos(p.X, p.Y); 
     }  
    } 
    } 

sama funkcja ClickLeftMouseButton nie kliknąć, jeśli usunę uzyskanie pozycji kursora takiego.

public static void ClickLeftMouseButton(int x, int y) 
     { 
      INPUT mouseInput = new INPUT(); 
      mouseInput.type = SendInputEventType.InputMouse; 
      mouseInput.mkhi.mi.dx = x; 
      mouseInput.mkhi.mi.dy = y; 
      mouseInput.mkhi.mi.mouseData = 0;      


      mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN; 
      SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT())); 

      mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP; 
      SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));    
     } 

Z góry dziękuję.

+0

Nie jest jasne, skąd pochodzą współrzędne X i Y oraz co dokładnie oznaczają. Brakująca flaga MOUSEEVENTF_ABSOLUTE wygląda na problem. –

Odpowiedz

24

Jest kilka rzeczy, które należy wziąć pod uwagę podczas korzystania z funkcji SendInput.

Jeśli nie zostanie określona flaga , wówczas dx i dy (struktura MouseInputData) są współrzędnymi względnymi do aktualnej pozycji myszy. Jeśli podasz MOUSEEVENTF_ABSOLUTE następnie dx i dy są bezwzględne współrzędne pomiędzy 0 a 65535. Więc jeśli xiy współrzędne są współrzędne ekranu należy użyć następujących funkcji obliczyć dx i dy:

enum SystemMetric 
{ 
    SM_CXSCREEN = 0, 
    SM_CYSCREEN = 1, 
} 

[DllImport("user32.dll")] 
static extern int GetSystemMetrics(SystemMetric smIndex); 

int CalculateAbsoluteCoordinateX(int x) 
{ 
    return (x * 65536)/GetSystemMetrics(SystemMetric.SM_CXSCREEN); 
} 

int CalculateAbsoluteCoordinateY(int y) 
{ 
    return (y * 65536)/GetSystemMetrics(SystemMetric.SM_CYSCREEN); 
} 

ty Ponadto przed wysłaniem zdarzenia mouseDown i mouseUp via SendInput trzeba przesunąć mysz do kontroli chcesz przejrzeć:

public static void ClickLeftMouseButton(int x, int y) 
{ 
    INPUT mouseInput = new INPUT(); 
    mouseInput.type = SendInputEventType.InputMouse; 
    mouseInput.mkhi.mi.dx = CalculateAbsoluteCoordinateX(x); 
    mouseInput.mkhi.mi.dy = CalculateAbsoluteCoordinateY(y); 
    mouseInput.mkhi.mi.mouseData = 0;      


    mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE |MouseEventFlags.MOUSEEVENTF_ABSOLUTE; 
    SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT())); 

    mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN; 
    SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT())); 

    mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP; 
    SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));    
} 

Powyższy kod zakłada, że ​​x i y są współrzędnymi pikseli ekranu. Można obliczyć te współrzędne dla przycisku (celu) na winform za pomocą następującego kodu:

Point screenCoordsCentre= 
button1.PointToScreen(new Point(button1.Width/2, button1.Height/2)); 

nadzieja, że ​​to pomaga.

+2

Wielkie dzięki za pomoc, to naprawdę wyjaśnia kilka rzeczy, o które się zastanawiałem. – Dmitris

+1

Dzięki. Ale czy wiesz, jak to zrobić bez poruszania myszką do tego kordynatu? (Chcę stworzyć podwójną mysz). – Jet

+0

jak symulować kliknięcie myszą bez konieczności przesuwania pozycji kursora? lubiany wspomniany w pytaniu. – tcboy88

Powiązane problemy