2012-02-02 3 views
1

Я пытаюсь сделать что-то вроде приключений Kinect с Kinect SDK, то есть когда мышь остается в определенной области в течение определенного периода времени, необходимо запустить собственное событие click. Проблема в том, что я не получаю ожидаемых результатов, так как я получаю случайный щелчок в большинстве случаев. Я пытался проверить точки останова и т. Д. Чаще всего, когда моя рука не видна, курсор переходит в угол экрана и начинает нажимать. Это, скорее всего, потому, что Math.Abs(lastX - cursorX) < threshold устанавливает значение true.Нажмите, когда мышь находится в области в течение некоторого времени

Я попытался изменить пороговые значения на 200, но он запускает щелчок на старт, а потом я не ожидаю левого клика, когда я удерживаю курсор в определенной позиции в течение некоторого времени. Любые предложения будут ценны. Вот код:

//SkeletonFrameReadyevent 

foreach (SkeletonData sd in e.SkeletonFrame.Skeletons) 
{ 
    if (sd.TrackingState == SkeletonTrackingState.Tracked) 
    { 
     // make sure both hands are tracked 
     if (sd.Joints[JointID.HandLeft].TrackingState == JointTrackingState.Tracked && 
      sd.Joints[JointID.HandRight].TrackingState == JointTrackingState.Tracked) 
     { 
      int cursorX, cursorY; 

     // get the left and right hand Joints 
     Joint jointRight = sd.Joints[JointID.HandRight]; 
     Joint jointLeft = sd.Joints[JointID.HandLeft]; 

     // scale those Joints to the primary screen width and height 
     Joint scaledRight = jointRight.ScaleTo((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, SkeletonMaxX, SkeletonMaxY); 
     Joint scaledLeft = jointLeft.ScaleTo((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, SkeletonMaxX, SkeletonMaxY); 

     // figure out the cursor position based on left/right handedness 

      cursorX = (int)scaledRight.Position.X; 
      cursorY = (int)scaledRight.Position.Y; 
     //default false, for mouse move, set to true for mouse click 
     bool leftClick; 

     if (lastY == 0) 
     { 
      lastX = cursorX; 
      lastY = cursorY; 
     } 

     leftClick = false; 
     if (Math.Abs(lastX - cursorX) < threshold && Math.Abs(lastY - cursorY) < threshold) 
     { 
      if (Math.Abs(lastClick.Subtract(DateTime.Now).TotalSeconds) > 1) 
      { 
       //Mouse click here 
       leftClick = true; 
      } 
     } 

     //Mouse click when leftDown is true, else Mousemove 
     NativeMethods.SendMouseInput(cursorX, cursorY, (int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, leftClick); 
     return; 
     } 
    } 
} 

NativeMthods.cs класс имеет эту функцию:

public static void SendMouseInput(int positionX, int positionY, int maxX, int maxY, bool leftDown) 
{ 
    if(positionX > int.MaxValue) 
     throw new ArgumentOutOfRangeException("positionX"); 
    if(positionY > int.MaxValue) 
     throw new ArgumentOutOfRangeException("positionY"); 

    Input[] i = new Input[2]; 

    // move the mouse to the position specified 
    i[0] = new Input(); 
    i[0].Type = InputMouse; 
    i[0].MouseInput.X = (positionX * 65535)/maxX; 
    i[0].MouseInput.Y = (positionY * 65535)/maxY; 
    i[0].MouseInput.Flags = MouseEventAbsolute | MouseEventMove; 

    // determine if we need to send a mouse down or mouse up event 
    if(leftDown) 
    { 
     i[1] = new Input(); 
     i[1].Type = InputMouse; 
     i[1].MouseInput.Flags = MouseEventLeftDown; 
     i[1].MouseInput.Flags |= MouseEventLeftUp; 
    } 

    // send it off 
    uint result = SendInput(2, i, Marshal.SizeOf(i[0])); 
    if(result == 0) 
     throw new Win32Exception(Marshal.GetLastWin32Error()); 
} 

ответ

0

попробовать что-то вроде этого:

public class myMouseClass: IMessageFilter //Must implement IMessageFilter 
    { 
     [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
     public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo); 

     //Constants 
     private const int MOUSEEVENTF_LEFTDOWN = 0x02; 
     private const int MOUSEEVENTF_LEFTUP = 0x04; 
     private const int MOUSEEVENTF_RIGHTDOWN = 0x08; 
     private const int MOUSEEVENTF_RIGHTUP = 0x10; 
     private const int WM_MOUSEMOVE = 0x0200; 

     private int Threshold = 20; //how far the mouse should move to reset timer 
     private int StartLocationX = 0; //stores starting X value 
     private int StartLocationY = 0; //stores starting Y value 
     private Timer timerHold = new Timer(); //timer to trigger mouse click 

     //Start Mouse monitoring by calling this. This will also set the timer.  
     private void StartFilterMouseEvents() 
     { 

      timerHold.Interval = 1000; //how long mouse must be in threshold. 
      timerHold.Tick = new EventHandler(timerHold_Tick); 
      Application.AddMessageFilter((IMessageFilter) this); 
     } 
     //Stop Mouse monitoring by calling this and unset the timer. 
     private void StopFilterMouseEvents() 
     { 
      timerHold.Stop(); 
      timerHold -= timerHold_Tick; 
      Application.RemoveMessageFilter((IMessageFilter) this); 
     } 
     //This will start when Application.AddMessageFilter() is called 
     public bool PreFilterMessage(ref Message m) 
     { 
      if (m.Msg == WM_MOUSEMOVE) 
      { 
       if((Cursor.Position.X > StartLocationX + 20)||(Cursor.Position.X > StartLocationX - 20))&& 
         ((Cursor.Position.Y > StartLocationY + 20)||(Cursor.Position.Y > StartLocationY - 20)) 
         { 
          timerHold.Stop(); //stops timer if running 
          timerHold.Start(); //starts it again with new position. 
          StartLocationX = Cursor.Position.X; 
          StartLocationY = Cursor.Position.Y; 
         } 
      } 
      return false; 
     } 
     //This event gets fired when the timer has not been reset for 1000ms 
     public void timerHold_Tick(object sender, EventArgs e) 
     { 
      mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 
     } 

     } 
+0

Я не вижу способа MouseMove здесь на первом обезжиренное read?: -/ – Cipher

+0

if (m.Msg == WM_MOUSEMOVE) просто ссылается на фильтр msg, который равен 0x0200. Это то же самое, что (m.Msg == 0x0200) – Corylulu

+0

И я также не уверен, как использовать эти сообщения Add, Remove, PreFilter в вышеперечисленном элементе SkeletonFrameReadyevent. Теперь попробуйте ti: -/ – Cipher

Смежные вопросы