0

I'm using ToUnicodeEx function to translate the virtual key code of a pressed key to its unicode character,

This is the function definition:

<DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)>
Friend Shared Function ToUnicodeEx(
                       ByVal wVirtKey As UInteger,
                       ByVal wScanCode As UInteger,
                       ByVal lpKeyState As Byte(),
                       <Out, MarshalAs(UnmanagedType.LPWStr)>
                       ByVal pwszBuff As StringBuilder,
                       ByVal cchBuff As Integer,
                       ByVal wFlags As UInteger,
                       ByVal dwhkl As IntPtr
) As Integer
End Function

The function works perfect for my culture es-ES with my keyboard layout 3082, however, if instead specifying 3082 I try the code below specifying a 1033 keyboard layout to simulate a key pres for en-US culture, or whatever any other keyboard layout different than 3082, then ToUnicodeEx function will fail and returns 0, where a return value of 0 means this:

The specified virtual key has no translation for the current state of the keyboard. Nothing was written to the buffer specified by pwszBuff.

Dim buf As New StringBuilder(256)
Dim keyboardState As Byte() = New Byte(255) {}

If shift Then
    keyboardState(CInt(Keys.ShiftKey)) = &HFF
End If

If altGr Then
    keyboardState(CInt(Keys.ControlKey)) = &HFF
    keyboardState(CInt(Keys.Menu)) = &HFF
End If

InputDevice.NativeMethods.ToUnicodeEx(CUInt(Keys.A), 0UI, keyboardState,  buf,  256,  0UI, 
                                      New IntPtr(1033))

What I'm doing wrong?, How I can fix it?

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417

2 Answers2

2

You can't simply pass a number (IntPtr) as the last parameter... As written in the MSDN

dwhkl [in, optional] Type: HKL The input locale identifier used to translate the specified code. This parameter can be any input locale identifier previously returned by the LoadKeyboardLayout function.

You must load the layout with LoadKeyboardLayout first.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • But that function changes the keyboard layout in the entire O.S!. Additional info is required, what I would like to do is use a different keyboard layout without affecting the Os behavior. thanks anyways!. – ElektroStudios Jul 04 '15 at 04:46
  • I changed accidentally the keyboard layout with `LoadKeyboardLayout` then I will ask first this time. The documentation of the first parameter of `ActivateKeyboardLayout` says: `The input locale identifier must have been loaded by a previous call to the LoadKeyboardLayout function`, its saying that I should use the other function that I will avoid because it changes the layout on the OS. then what I should do?. – ElektroStudios Jul 04 '15 at 06:25
0

Experimenting, reasearching, and with some fails, I found in the .Net framework class library the best and easier solution that does not involves P/Invoking.

Just knowing a culturename, like en-US or es-ES with the Systwm.Windows.Forms.InputLanguage class we can retrieve the handle of the layout (the HKL)

InputLanguage.FromCulture(New CultureInfo("en-US")).Handle

Then, that value can be set for the dwHKL parameter of the ToUnicodeEx function, and it works perfect!.

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417