我正在尝试使用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());
}
答案 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);
}
}