当鼠标在某个区域中一段时间​​后单击

时间:2012-02-02 04:40:18

标签: c# wpf mouse kinect

我正在尝试使用Kinect SDK进行Kinect冒险,即当鼠标停留在特定区域一段特定时间时,将触发本机点击事件。 问题是我没有得到预期的结果,因为我随机点击了大多数时间。我试着检查断点等。 大多数情况下,当我的手不可见时,光标会转到屏幕的一角并开始点击。这很可能是因为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());
}

1 个答案:

答案 0 :(得分: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);
        }

      }