2011-11-05 47 views
22

SendInput không thực hiện nút chuột nhấp trừ khi tôi di chuyển con trỏ.SendInput không thực hiện nút chuột nhấp chuột trừ khi tôi di chuyển con trỏ

Tôi sẽ đánh giá cao sự trợ giúp về vấn đề này, vì dường như tôi không thể che giấu đầu xung quanh nó.

Tôi có một chương trình thực hiện nhấp chuột trên cửa sổ nền trước, trong đó tôi đang sử dụng SendInput để mô phỏng nhấp chuột trái. Vấn đề là, nếu tôi di chuyển con trỏ đến vị trí nhấp chuột hơn SendInput sẽ làm cho nhấp chuột, tuy nhiên nếu tôi không di chuyển con trỏ hơn không có nhấp chuột xảy ra ngay cả máng tôi vượt qua x và y trỏ đến MouseInputData. Tôi muốn thực hiện nhấp chuột trái mà không cần di chuyển con trỏ.

Bellow là lớp tôi có (nó khá đơn giản và stright phía trước)

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

Cùng chức năng ClickLeftMouseButton sẽ không nhấp nếu tôi loại bỏ nhận được vị trí con trỏ như thế.

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

Cảm ơn bạn trước.

+0

Không rõ bạn đang nhận tọa độ x và y từ đâu và ý nghĩa của chúng. Lá cờ MOUSEEVENTF_ABSOLUTE bị thiếu trông giống như một vấn đề. –

Trả lời

24

Có một vài điều bạn nên cân nhắc khi sử dụng chức năng SendInput.

Nếu bạn không chỉ định cờ MOUSEEVENTF_ABSOLUTE thì dxdy (cấu trúc MouseInputData) là tọa độ tương đối với vị trí chuột hiện tại. Nếu bạn chỉ định MOUSEEVENTF_ABSOLUTE sau đó dxdy là tọa độ tuyệt đối giữa 0 và 65535. Vì vậy, nếu x và y tọa độ là màn hình tọa độ bạn nên sử dụng các chức năng sau đây để tính toán dxdy:

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

Hơn nữa trước khi bạn gửi các MouseDown và MouseUp sự kiện để thông qua SendInput bạn phải di chuyển chuột để điều khiển bạn muốn click vào:

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

Đoạn mã trên giả định rằng xy là tọa độ điểm ảnh màn hình. Bạn có thể tính toán những tọa độ cho một nút (mục tiêu) trên một Winform bằng cách sử dụng đoạn mã sau:

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

Hope, điều này sẽ giúp.

+2

Cảm ơn rất nhiều vì sự giúp đỡ, nó thực sự giải thích một vài điều tôi đã thắc mắc. – Dmitris

+1

Cảm ơn. Nhưng bạn có biết làm thế nào để làm điều đó mà không cần di chuyển chuột đến đó? (Tôi muốn tạo chuột đôi). – Jet

+0

cách mô phỏng nhấp chuột mà không di chuyển vị trí con trỏ trước tiên? thích được đề cập trong câu hỏi. – tcboy88

Các vấn đề liên quan