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?

Community
  • 1
  • 1
Agrim
  • 471
  • 9
  • 19

3 Answers3

1

You don't need to queue the event. If isProcessing is true, then the other button was already clicked, so you can handle the event for both button clicks from that point on.

You could measure the time between the two clicks, to work out if it validates as a "two buttons clicked at the same time" event.

John Willemse
  • 6,608
  • 7
  • 31
  • 45
1

Have you considered a more low-level approach? The first thing that came to mind was to create two hot areas instead of buttons and monitor whether the user's hands are inside those areas at the same time.

Captain Kenpachi
  • 6,960
  • 7
  • 47
  • 68
1

It is unclear to me why another button is disabled when you hand is hovering over another object. Without seeing the code, I would say that you are doing something that would cause that -- and there is no reason to.

Additionally, you should be using interaction concepts centered around a gesture system and not something that is written for a mouse/keyboard input. Using regular UI objects and interacting with them in ways that parallel traditional inputs will only serve to confuse the users.

Have a look at the following two examples, which use a "hover-to-click" and a "press-to-click" interaction

In both cases, you are using a hit test on custom controls to handle events. Here is an example of a hit test function I use in one of my apps:

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

Notice that an event is being fired on the element below the hand cursor. Examples of these elements can be found in the two links above (the HoverDwellButton is what I use with the above code sample).

Two events on two different elements, or the same element, can fire at any time with this. You can easily keep track of which user is over which button, if that button is in the process of being pressed, or if it has been pressed.

The key to all this is not using a UI paradigm that isn't designed for gesture systems! Don't try to shoehorn the keyboard/mouse event structure into a gesture based system -- it will only cause you more pain in the long run and cause your users confusion.

Nicholas Pappas
  • 10,439
  • 12
  • 54
  • 87
  • Thanks a lot for this suggestion! I found out that another programmer who had been working on the code earlier had been using the same variable for input from both hands, that's why I wasn't able to use them both simultaneously. I have now changed this so that the hands are handled by separate variables. – Agrim Apr 09 '13 at 02:32