2

Is there a built in way to obtain the equivalent of a key combined with the Shift key e.g:

a + Shift -> A

1 + Shift -> !

I currently have all the keys mapped in a dictionary in pretty much the same way as illustrated above.

I'm using windows forms.

Deadzone
  • 793
  • 1
  • 11
  • 33
  • That depends a bit on the keyboard layout. Not all layouts have the same layout of characters – rene Jul 10 '17 at 16:54
  • That's true and that's a problem, how should I tackle this than @rene? – Deadzone Jul 10 '17 at 16:56
  • I was thinking about [ConsoleKey](https://msdn.microsoft.com/en-us/library/system.consolekey(v=vs.110).aspx) and [ConsoleModifiers](https://msdn.microsoft.com/en-us/library/system.consolemodifiers(v=vs.110).aspx) but depends a bit how you want to use it. Can you share an [MCVE] for how intend to use or how you currently use it with the dictionary? – rene Jul 10 '17 at 16:59
  • @rene I would need to include way too much information, the solution I'm using is literally just a `Dictionary` this would be a dictionary where there are only "shifted" key values which have the same look as in the question's illustration, without the Shift tho, it's just for clarification. – Deadzone Jul 10 '17 at 17:06

1 Answers1

2

You can achieve what you want by first calling vkKeyScan to get the virtual-keycode for the char you're interested in.

With the outcome of that call you can feed ToUnicode to translate what the characters would be when the Shift key is pressed.

Both above mentioned methods are native WinAPI calls in the KeyBoard and Mouse input category.

Combining above calls and implementing in C# you'll get the following implementation (tested in LinqPad):

void Main()
{
    GetCharWithShiftPressed('1').Dump("1");
    GetCharWithShiftPressed('a').Dump("a");
}

// Inspired on https://stackoverflow.com/a/6949520
// TimWi: https://stackoverflow.com/users/33225/timwi
public static string GetCharWithShiftPressed(char ch)
{
    // get the keyscancode 
    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms646329(v=vs.85).aspx
    var key = Native.VkKeyScan(ch);

    // Use toUnicode to get the actual string shift is pressed
    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms646320(v=vs.85).aspx
    var buf = new StringBuilder(256);
    var keyboardState = new byte[256];
    keyboardState[(int) Keys.ShiftKey] = 0xff;
    var result = Native.ToUnicode(key, 0, keyboardState, buf, 256, 0);
    if (result == 0) return "No key";
    if (result == -1) return "Dead key";
    return buf.ToString();
}

// Define other methods and classes here
static class Native
{
    [DllImport("user32.dll")]
    public static extern uint VkKeyScan(char ch);

    [DllImport("user32.dll")]
    public static extern int ToUnicode(uint virtualKeyCode, 
        uint scanCode,
        byte[] keyboardState,
        [Out, MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]
        StringBuilder receivingBuffer,
        int bufferSize, 
        uint flags);
}

Running above code you'll get the following output:

1
!

a
A

This implementation uses the current active keyboard layout. If you instead want to specify alternative keyboard layouts, use the ToUnicodeEx that takes an handle to a keyboardlayout as its last parameter.

The ToUnicode handling was borrowed and adapted from this answer from user Timwi

rene
  • 41,474
  • 78
  • 114
  • 152
  • '[' for example would return an empty result, instead of a curly brace '{' – Deadzone Jul 10 '17 at 19:02
  • @Deadzone not on my box ... what is your keyboard setting? Is it a dead key maybe? – rene Jul 10 '17 at 19:26
  • My keyboard layout is United States International. – Deadzone Jul 10 '17 at 19:32
  • I added extra error handling, can you try that code change and let me know the outcome? – rene Jul 10 '17 at 19:36
  • It doesn't seems to work for any of the control/system keys, it returns a result of 0 for all of them. – Deadzone Jul 10 '17 at 19:38
  • I use the same keyboard layout and when I switched to another the result was different but it still gave me results that seemed reasonable. I can't repro to make it return 0 for control/system keys, assuming you mean the chars like ;:"\|.>? etc – rene Jul 10 '17 at 19:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/148819/discussion-between-deadzone-and-rene). – Deadzone Jul 10 '17 at 19:59