1
\$\begingroup\$

I'm using SDL.NET with C#. Recently, a bug has appeared where the library does not detect if the shift key is held down; although it used to do so.

private static void KeyboardEventHandler(object sender, KeyboardEventArgs args)
    {
            case (Key.Comma):

                if (args.Mod == ModifierKeys.LeftShift || args.Mod == ModifierKeys.RightShift || args.Mod == ModifierKeys.ShiftKeys) { actionBuffer = GameAction.MoveU; Console.WriteLine("Going up..."); }
                else { actionBuffer = GameAction.Pickup; }
                break;

            case (Key.Period):
                if (args.Mod == ModifierKeys.LeftShift || args.Mod == ModifierKeys.RightShift || args.Mod == ModifierKeys.ShiftKeys) { actionBuffer = GameAction.MoveD; Console.WriteLine("Going down..."); }
                else { actionBuffer = GameAction.Wait; }
                break;

            default:
                actionBuffer = GameAction.Null;
                break;
        }
    }

However, recently, the checks to see if a shift key is held have returned incorrectly false, despite previously previously evaluating to true.

This means the function never returns the "MoveU" or "MoveD" values, just the "Pickup" and "Wait" values. Why is this? Thanks in advance.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

The modifier keys can be combined with OR-bits. You need to use AND-bits to test for the modifier flags since it could contain all of CTRL+ALT+SHIFT (Left AND Right) and even some other modifier keys.

For example, if NumLock or CapsLock is ON, the value will never be == to LeftShift.

See the documentation for the ModifierKeys.

It is also not necessary to test for LeftShift, RightShift and ShiftKeys all at the same time. Just ShiftKeys is sufficient if you are treating them both the same.

ModifierKeys.ShiftKeys == (ModifierKeys.LeftShift | ModifierKeys.RightShift)

Try:

private static void KeyboardEventHandler(object sender, KeyboardEventArgs args)
{
        case (Key.Comma):

            if ((args.Mod & ModifierKeys.ShiftKeys) != 0) { actionBuffer = GameAction.MoveU; Console.WriteLine("Going up..."); }
            else { actionBuffer = GameAction.Pickup; }
            break;

        case (Key.Period):
            if ((args.Mod & ModifierKeys.ShiftKeys) != 0) { actionBuffer = GameAction.MoveD; Console.WriteLine("Going down..."); }
            else { actionBuffer = GameAction.Wait; }
            break;

        default:
            actionBuffer = GameAction.Null;
            break;
    }
}
\$\endgroup\$
6
  • \$\begingroup\$ Thanks for the information about the Num Lock key, this indeed seems to be the cause of the problem. However, I'm not sure about how the code '(args.Mod & ModifierKeys.LeftShift)' works. The compiler cannot convert the ModifierKey value to a boolean: could you explain what I'm doing wrong? \$\endgroup\$
    – Nim
    Commented Aug 25, 2015 at 15:42
  • \$\begingroup\$ My C# is a little rusty but I think you may have done something wrong. The & operator should work for bitwise AND but it is also used for logical AND depending on the types of variables it is operating on. Is args.Mod a boolean? In anycase, you should be able to use bitand instead of & and there won't be the confusion. If there is something wrong with your code then you should get a better error message. Multi-purposing the & operator was a poor design choice for C#. \$\endgroup\$ Commented Aug 25, 2015 at 15:56
  • \$\begingroup\$ This might help clarify for you: msdn.microsoft.com/en-us/library/sbf85k1c.aspx \$\endgroup\$ Commented Aug 25, 2015 at 15:59
  • \$\begingroup\$ neither args.mod nor ModifierKeys.LeftShift are booleans, they are of the type ModifierKey, the error message recieved is "Cannot implicitly convert type 'SdlDotNet.Input.ModifierKeys' to 'bool'", if that helps. if it also helps, I replaced the if-conditions with the (args.Mod & ModifierKeys.LeftShift). \$\endgroup\$
    – Nim
    Commented Aug 25, 2015 at 16:21
  • \$\begingroup\$ Try: if ((args.Mod & ModifierKeys.ShiftKeys) != 0) { actionBuffer = GameAction.MoveU; Console.WriteLine("Going up..."); }. Important difference is the != 0. Sorry I'm kinda guessing now but I'm thinking that C# is treating the whole expression as a boolean since the condition was testing for a true value instead of doing a comparison to a real number (!= 0) \$\endgroup\$ Commented Aug 25, 2015 at 16:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .