在kinect的C#中处理多个悬停以单击事件

在kinect的C#中处理多个悬停以单击事件,c#,multithreading,queue,kinect,C#,Multithreading,Queue,Kinect,我正在用C#开发一款Kinect游戏,用户需要同时点击两个按钮,每只手悬停在一个按钮上 但是,在我的当前代码中,当用户一只手悬停在按钮上时,其他按钮将被禁用,而另一只手只能在第一只手停止悬停在按钮上时单击 为了解决这个问题,我考虑在处理第一次单击时对第二次单击进行排队。为此,我使用了以下基于 private Queue按钮_Queue=new Queue(); 私有bool isProcessing=false; 私有无效按钮\u单击((对象发送者,路由目标){ 如果(i处理){ 按钮_Queu

我正在用C#开发一款Kinect游戏,用户需要同时点击两个按钮,每只手悬停在一个按钮上

但是,在我的当前代码中,当用户一只手悬停在按钮上时,其他按钮将被禁用,而另一只手只能在第一只手停止悬停在按钮上时单击

为了解决这个问题,我考虑在处理第一次单击时对第二次单击进行排队。为此,我使用了以下基于

private Queue按钮_Queue=new Queue();
私有bool isProcessing=false;
私有无效按钮\u单击((对象发送者,路由目标){
如果(i处理){
按钮_Queue.Enqueue(此按钮);
}
其他的
{
isProcessing=true;
//代码在这里
isProcessing=false;
同时(按钮\u Queue.Count>0){
按钮_Queue.Dequeue().PerformClick();
}
}
但是,
按钮\u Queue.Enqueue(此)
行显示错误

“队列的最佳重载方法匹配。排队无效。” 争论。”

我猜这是因为按钮单击事件不能在使用类型
按钮
声明的队列中排队


您对如何创建此按钮单击事件队列或以其他方式处理用户多次单击有何建议?

您不需要对事件进行排队。如果
isProcessing
为true,则另一个按钮已被单击,因此您可以从该点开始处理两次按钮单击的事件


您可以测量两次单击之间的时间,以确定是否验证为“两个按钮同时单击”事件。

您是否考虑过一种更低级的方法?首先想到的是创建两个热点区域而不是按钮,并同时监视用户的手是否在这些区域内。

我不清楚当您的手悬停在另一个对象上时为什么另一个按钮被禁用。没有看到代码,我想说的是,你正在做一些会导致这种情况的事情——没有理由这么做

此外,您应该使用以手势系统为中心的交互概念,而不是为鼠标/键盘输入编写的内容。使用常规UI对象并以并行传统输入的方式与它们交互只会让用户感到困惑

请看以下两个示例,它们使用“悬停以单击”和“按以单击”交互

  • SDK 1.7的控件基础(in)
在这两种情况下,您都在自定义控件上使用命中测试来处理事件。以下是我在其中一个应用程序中使用的命中测试功能的示例:

private void HitTestHand(HandPosition hand)
{
    // quick fix to null pointer exception on exit.
    if (Application.Current.MainWindow == null)
        return;

    Point pt = new Point(hand.X, hand.Y);
    IInputElement input = Application.Current.MainWindow.InputHitTest(pt);

    if (hand.CurrentElement != input)
    {
        var inputObject = input as DependencyObject;
        var currentObject = hand.CurrentElement as DependencyObject;

        // If the new input is a child of the current element then don't fire the leave event.
        // It will be fired later when the current input moves to the parent of the current element.
        if (hand.CurrentElement != null && Utility.IsElementChild(currentObject, inputObject) == false)
        {
            // Raise the HandLeaveEvent on the CurrentElement, which at this point is the previous element the hand was over.
            hand.CurrentElement.RaiseEvent(new HandInputEventArgs(HoverDwellButton.HandLeaveEvent, hand.CurrentElement, hand));
        }

        // If the current element is the parent of the new input element then don't
        // raise the entered event as it has already been fired.
        if (input != null && Utility.IsElementChild(inputObject, currentObject) == false)
        {
            input.RaiseEvent(new HandInputEventArgs(HoverDwellButton.HandEnterEvent, input, hand));
        }

        hand.CurrentElement = input;
    }
    else if (hand.CurrentElement != null)
    {
        hand.CurrentElement.RaiseEvent(new HandInputEventArgs(HoverDwellButton.HandMoveEvent, hand.CurrentElement, hand));
    }
}
请注意,正在手动光标下方的元素上触发一个事件。可以在上面的两个链接中找到这些元素的示例(这是我在上面的代码示例中使用的)

两个不同元素或同一元素上的两个事件可以随时触发。您可以轻松跟踪哪个用户在哪个按钮上,该按钮是否正在按下,或者是否已按下


所有这一切的关键是不要使用不是为手势系统设计的UI范型!不要试图将键盘/鼠标事件结构硬塞进基于手势的系统中——从长远来看,这只会给你带来更多的痛苦,并让你的用户感到困惑。

非常感谢你的建议!我发现另一个曾经之前,代码上的rking对双手的输入使用了相同的变量,这就是为什么我不能同时使用这两个变量的原因。我现在改变了这一点,以便双手由单独的变量处理。
private void HitTestHand(HandPosition hand)
{
    // quick fix to null pointer exception on exit.
    if (Application.Current.MainWindow == null)
        return;

    Point pt = new Point(hand.X, hand.Y);
    IInputElement input = Application.Current.MainWindow.InputHitTest(pt);

    if (hand.CurrentElement != input)
    {
        var inputObject = input as DependencyObject;
        var currentObject = hand.CurrentElement as DependencyObject;

        // If the new input is a child of the current element then don't fire the leave event.
        // It will be fired later when the current input moves to the parent of the current element.
        if (hand.CurrentElement != null && Utility.IsElementChild(currentObject, inputObject) == false)
        {
            // Raise the HandLeaveEvent on the CurrentElement, which at this point is the previous element the hand was over.
            hand.CurrentElement.RaiseEvent(new HandInputEventArgs(HoverDwellButton.HandLeaveEvent, hand.CurrentElement, hand));
        }

        // If the current element is the parent of the new input element then don't
        // raise the entered event as it has already been fired.
        if (input != null && Utility.IsElementChild(inputObject, currentObject) == false)
        {
            input.RaiseEvent(new HandInputEventArgs(HoverDwellButton.HandEnterEvent, input, hand));
        }

        hand.CurrentElement = input;
    }
    else if (hand.CurrentElement != null)
    {
        hand.CurrentElement.RaiseEvent(new HandInputEventArgs(HoverDwellButton.HandMoveEvent, hand.CurrentElement, hand));
    }
}