2011-11-05 29 views
22

SendInput no realiza clic en el botón del mouse a menos que mueva el cursor.SendInput no realiza clic en el botón del mouse a menos que mueva el cursor

Agradecería una ayuda en este caso, ya que parece que no puedo entenderlo.

Tengo un programa que hace clic con el mouse en la ventana de primer plano, en la que estoy usando SendInput para emular el clic izquierdo del mouse. El problema es que si muevo el cursor para hacer clic en la posición que SendInput hará clic, sin embargo, si no muevo el cursor, no ocurre ningún clic incluso a través de los puntos x e y de MouseInputData. Me gustaría hacer clic con el botón izquierdo del mouse sin la necesidad de mover realmente el cursor.

Bellow es la clase que tengo (que es bastante simple y stright adelante)

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); 
     }  
    } 
    } 

función ClickLeftMouseButton mismo no haga clic si quito conseguir la posición del cursor por el estilo.

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()));    
     } 

Gracias de antemano.

+0

No está claro de dónde se obtienen las coordenadas X e Y y lo que significan exactamente. La bandera MOUSEEVENTF_ABSOLUTE que falta parece un problema. –

Respuesta

24

Hay algunas cosas que debe considerar al utilizar la función SendInput.

Si no se especifica la bandera MOUSEEVENTF_ABSOLUTE continuación dx y dy (estructura MouseInputData) son las coordenadas relativas a la posición actual del ratón. Si especifica a continuación MOUSEEVENTF_ABSOLUTEdx y dy son coordenadas absolutas entre 0 y 65535. Así que si sus coordenadas x e y son las coordenadas de pantalla se debe utilizar la siguiente función para calcular dx y 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); 
} 

Por otra parte, antes de enviar los eventos MouseDown y MouseUp a través SendInput que tienen que mover el ratón para el control que desea hacer clic en:

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()));    
} 

el código anterior asume que x y y son coordenadas de píxel de pantalla. Se puede calcular esas coordenadas para un botón (el objetivo) en un WinForm utilizando el código siguiente:

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

Esperanza, esto ayuda.

+2

Muchas gracias por la ayuda, en realidad explica algunas cosas que me he estado preguntando. – Dmitris

+1

Gracias. ¿Pero sabes cómo hacerlo sin mover el mouse a ese cordinate? (Quiero crear doble ratón). – Jet

+0

cómo simular el clic del mouse sin mover primero la posición del cursor? Me gustó mencionado en la pregunta. – tcboy88

Cuestiones relacionadas