Shift / Left Shift issues

Jun 9, 2011 at 12:30 AM

Im getting some weird behavior on Windows using a keyboard and pressing Left Shift.

The key that is getting mapped is VK_SHIFT  ,   16  

XNA expects LShift to be 160 which is the proper keycode for VK_LSHIFT (http://msdn.microsoft.com/en-us/library/ms646301(VS.85).aspx)

The problems comes down to both Left shift and Right shift generate a KeyCode of 16 in PreFilterMessage which is then mapped to 0 in the KeyboardStateHelper.

Running the unit test and adding Keys.LeftShift works correctly and correctly generates 160.

 

Im not sure how to fix this. This ends up manifesting as when i call keyboardState.IsKeyDown(Keys.LeftShift) , it will always be false, since the keyboard state has masked it out to 0.

 

Thanks for the great framework. Im wondering if this is a known issue and im just being slow.

Jun 9, 2011 at 1:05 AM
Edited Jun 9, 2011 at 1:13 AM

I found a (horrific) way to fix it. I dont know if its the only way but its fairly simple.

 

In WindowsMessageFilter.PreFilterMessage

 

in both keydown and keydup, immediately after getting the virtualkeyCode i had to replace OnKeyPressed((Keys)virtualKeyCode); with the much uglier

 if (virtualKeyCode == 16 )
 {
     uint scancode = UnsafeNativeMethods.MapVirtualKey(161,
                                                                (IntPtr)UnsafeNativeMethods.MapTypes.VirtualKeyToScanCode);
     if ((((uint)message.LParam & (uint)0x01FF0000>> 16== scancode)
     {
         OnKeyPressed((Keys)161);
     }
     else
     {
         OnKeyPressed((Keys)160);
     }
}else
     OnKeyPressed((Keys)virtualKeyCode);
and OnKeyReleased((Keys)virtualkeyCode); with
if (virtualKeyCode == 16)
{
     uint scancode = UnsafeNativeMethods.MapVirtualKey(161,
                                                                (IntPtr)UnsafeNativeMethods.MapTypes.VirtualKeyToScanCode);
     if ((((uint)message.LParam & (uint)0x01FF0000>> 16== scancode)
     {
          OnKeyReleased((Keys)161);
     }
     else
     {
         OnKeyReleased((Keys)160);
     }
}
else
    OnKeyReleased((Keys)virtualKeyCode);

161 is the key code for VK_RSHIFT and 160 is VK_LSHIFT

 

This can be cleaned up, just wanted to get it up here in case it helps anyone


EDIT) also had to change

[DllImport("user32")]
    public static extern uint MapVirtualKey(
      uint code, [MarshalAs(UnmanagedType.SysUInt)] uint mapType
    );
to
[DllImport("user32")]
    public static extern uint MapVirtualKey(
      uint codeIntPtr mapType
    );

not sure why. but it was excepting.
Jun 9, 2011 at 1:47 AM

I just noticed that the version on trac accounts for this. Sorry for not checking that earlier!.