1

I am developing a Kinect game in C# where the user needs to click 2 buttons at the same time by hovering over one button with each hand.

However, with my current code, when the user hovers with one hand over a button, the other buttons get disabled and the other hand can only click when the first hand stops hovering over a button.

To solve this, I'm thinking of queuing the second click while the first click is being processed. To do this, I have used the following code based on this link

private Queue<System.Windows.Controls.Button> Button_Queue = new Queue<System.Windows.Controls.Button>();
private bool isProcessing = false;

private void Button_Click((object sender, RoutedEventArgs e){

if(isProcessing){
Button_Queue.Enqueue(this);
}
else
{
isProcessing = true;

// code here

isProcessing = false;
while(Button_Queue.Count > 0){
    Button_Queue.Dequeue().PerformClick();
}
}

However, the Button_Queue.Enqueue(this) line shows the error

"The best overloaded method match for Queue.Enqueue has invalid arguments."

I'm guessing this is because the button click event cannot be queued in a queue declared with the type Button.

Do you have any suggestions for how to create this queue of button click events or another way to handle multiple clicks from the user?

4

3 回答 3

1

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

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

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

在这两种情况下,您都在自定义控件上使用命中测试来处理事件。这是我在我的一个应用程序中使用的命中测试函数的示例:

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

请注意,在手形光标下方的元素上触发了一个事件。这些元素的示例可以在上面的两个链接中找到(我在上面的代码示例中使用了HoverDwellButton )。

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

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

于 2013-04-08T16:15:49.157 回答
1

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

于 2013-04-08T07:50:22.143 回答
1

您无需将事件排队。如果isProcessing为真,则另一个按钮已被单击,因此您可以从该点开始处理两个按钮单击的事件。

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

于 2013-04-08T07:47:16.803 回答