I have a UWP app in Visual Studio 2017. I'm trying to make a multi-language on-screen keyboard.
Currently the English keystrokes are working fine, however any letter from other languages throws System.ArgumentException: 'Value does not fall within the expected range.'
Here is the code that sends the keystrokes:
public void SendKey(ushort keyCode)
{
List<InjectedInputKeyboardInfo> inputs = new List<InjectedInputKeyboardInfo>();
InjectedInputKeyboardInfo myinput = new InjectedInputKeyboardInfo();
myinput.VirtualKey = keyCode;
inputs.Add(myinput);
var injector = InputInjector.TryCreate();
WebViewDemo.Focus(FocusState.Keyboard);
injector.InjectKeyboardInput(inputs); // exception throws here
}
How would I inject letters from other languages?
The trick is that InputInjector isn't injecting text (characters), but actually it is injecting key strokes on the keyboard. That means the input will be not what the VirtualKey value contains as the name value, but what the given key represents on the keyboard the user is currently using.
For example in Czech language we use the top numeric row to write characters like "ě", "š" and so on. So when you press number 3 on the keyboard, Czech keyboard writes "š".
If I use your code with Number3 value:
SendKey( (ushort)VirtualKey.Number3 );
I get "š" as the output. The same thing holds for Japanese for example where VirtualKey.A will actually map to ”あ”.
That makes InputInjector for keyboard a bit inconvenient to use, because you cannot predict which language the user is actually using a which keyboard key mapping is taking place, but after reflection it makes sense it is implemented this way, because it is not injection of text, but simulation of actual keyboard keystrokes.
The answer given by Martin Zikmund is not true. You can send any unicode character.
InputInjector inputInjector = InputInjector.TryCreate();
var key = new InjectedInputKeyboardInfo();
key.ScanCode = (ushort)'Ä';
key.KeyOptions = InjectedInputKeyOptions.Unicode;
inputInjector.InjectKeyboardInput(new[] { key });
The InjectKeyboardInput method is using this function behind the scenes. Please note the that you require the inputInjectionBrokered capability in your app.
Related
I've got an Entry control on my Xamarin application home page, which is used for entering a person's age. I've set the keyboard to be Keyboard="Numberic"
However, this is causing confusion as, for Android at least, the "Done" key is below backspace, but above the settings key as well as the .- key. This means when the user is trying to press "Done", they're forgetting that the key isn't in the bottom right-hand corner as you'd expect, and they keep pressing the settings key by mistake and going into their phone settings, which is a bit irritating, understandably.
Is it possible to either disable the settings key and the .- key, or swap their positions around? I'm not expecting it to be possible, so in which case, is there another way that I can get around this?
Screenshot to clarify what I mean - can the keys with the settings cog and the ".-" be moved or disabled, to prevent the user opening their phone settings and putting negative/decimal numbers in?
I have not used C# in a bit and never with Android but the idea of removing characters from a String is most languages is normally simple enough.
Based on our small discussion in the comments, and a little research; I believe this is what you are looking for to strip unwanted values from the EditText field where the user's input goes in your application:
var editText = FindViewById<EditText> (Resource.Id.editText);
editText.TextChanged += (object sender, Android.Text.TextChangedEventArgs et) => {
//step 1 grab editText value
String newString = et.Text.ToString();
//step 2 replace unwanted characters (currently '.' & '-')
newString = newString.Replace(".", "").Replace("-", "");
//step 3 set the editText field to the updated string
editText.Text = newString;
};
Resource:
https://github.com/xamarin/recipes/tree/master/Recipes/android/controls/edittext/capture_user_input_text
I have not found a way to change the default keyboard for Android so you can remove unwanted keys (i.e. the settings key) or reorder them, so I am still thinking if you decide that you must do this, you would need to build a custom keyboard for the application.
I've been having some trouble getting the correct code for incoming keystrokes on the console for shift+number characters. For example, using:
cki = Console.ReadKey(True)
Console.WriteLine("You pressed the '{0}' key.", cki.Key)
If I press shift+2, I'm hoping to get the ascii 64 (for the '#' character), but instead I get 50 (for the '2' character).
Now, I know you can get the modifiers for the key pressed, but that would mean I'd have to program all the special cases for keys like that, and that doesn't seem right.
I need this function, or something like unto it, because of its ability to read keys as they are pressed, without the need to press enter, otherwise I'd just use console.read. Surely I've missed something. Could anyone tell me what it is I've missed?
You're looking for the KeyChar property, which returns the actual character rather than the physical key pressed.
You may want to cast it to int.
It is pretty important to distinguish between keys and characters. The key is the same anywhere in the world, the one on the top row at the left. You can rely on that key always producing ConsoleKey.D2
The character is however very different, it greatly depends on the active keyboard layout. A Northern American user presses Shift+2. A French user presses AltGr+0. A German user presses AltGr+Q. A Spanish user presses AltGr+2. Etcetera.
If you care only about the key then use ConsoleKeyInfo.Key, you do so for all non-typing keys like the function keys for example. Perhaps the typical gaming WASD keys. If you care only about the character, like #, then use ConsoleKeyInfo.KeyChar.
I have written a small program in C# 2010 which can split input from different keyboards by making an array of devices using, in part, the following:
--This code works fine for non-unified keyboards--
InputDevice id;
NumberOfKeyboards = id.EnumerateDevices();
id = new InputDevice( Handle );
id.KeyPressed += new InputDevice.DeviceEventHandler( m_KeyPressed );
private void m_KeyPressed( object sender, InputDevice.KeyControlEventArgs e ) {
lbDescription.Text = e.Keyboard.Name;
// e.Keyboard.* has many useful strings, none work for me anymore.
}
Very happy with this, I ran out and bought 4 Logitech K230 keyboards which use the Unifying receiver. Sadly, all the keyboard data is now multiplexed and shows up in my code as a single keyboard!
How can I identify which "unified" keyboard the input is coming from? Ideally in C#, but I suppose I am willing to look at other languages if solutions exist.
I don't have unifying keyboard, but check if you can see multiple keyboards in Windows devices. Then you could try this http://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard and check output.
I'm currently trying to send a character. Therefore I use the native methods GetKeyboardLayout and VkKeyScanExW located in user32.dll to get the virtual key code (and shift- and control-state) for the current keyboard-layout from the system. Afterwards I send this virtual keycode to the application using the native method SendInput from user32.dll.
Everything work's fine - except of the euro sign. When I pass this character as parameter to VkKeyScanExW it returns -1, which means not found. On my Keyboard it is located using Ctrl+Menu+E (German layout)
Now I assume this occurs because the euro sign is a unicode sign and not mapped in the ascii-layout. I read Sendinput also allows a unicode-mode using a hardware scancode. So I hope using the unicode mode of SendInput will solve my problems. But I guess my virtualkey code is not the hardware scan code as unicode range is wider. Where can I find a sample how to send a unicode character (e.g. €) via SendInput to another control/window. MSDN and pinvoke.net do not provide useful samples.
In the meantime I solved the problem using the unicode parameter of SendInput. Now I don't have to use VkKeyScan any more - I can pass the character itself.
private static void SendUnicodeChar(char input)
{
var inputStruct = new NativeWinApi.Input();
inputStruct.type = NativeWinApi.INPUT_KEYBOARD;
inputStruct.ki.wVk = 0;
inputStruct.ki.wScan = input;
inputStruct.ki.time = 0;
var flags = NativeWinApi.KEYEVENTF_UNICODE;
inputStruct.ki.dwFlags = flags;
inputStruct.ki.dwExtraInfo = NativeWinApi.GetMessageExtraInfo();
NativeWinApi.Input[] ip = { inputStruct };
NativeWinApi.SendInput(1, ip, Marshal.SizeOf(inputStruct));
}
Thanks to all for the help.
I was asked this question by a friend, and it piqued my curiosity, and I've been unable to find a solution to it yet, so I'm hoping someone will know.
Is there any way to programatically detect what type of keyboard a user is using? My understanding of the keyboard is that the signal sent to the computer for 'A' on a DVORAK keyboard is the same as the signal sent to the computer for an 'A' in a QUERTY keyboard. However, I've read about ways to switch to/from dvorak, that highlight registry tweaking, but I'm hoping there is a machine setting or some other thing that I can query.
Any ideas?
You can do this by calling the GetKeyboardLayoutName() Win32 API method.
Dvorak keyboards have specific names. For example, the U.S. Dvorak layout has a name of 00010409.
Code snippet:
public class Program
{
const int KL_NAMELENGTH = 9;
[DllImport("user32.dll")]
private static extern long GetKeyboardLayoutName(
System.Text.StringBuilder pwszKLID);
static void Main(string[] args)
{
StringBuilder name = new StringBuilder(KL_NAMELENGTH);
GetKeyboardLayoutName(name);
Console.WriteLine(name);
}
}
that probably depends on the OS. I'm sure that there is an operatingsystem setting somewhere that registers the nationality of the keyboard. (Dvorak is considered a nationality because French keyboards are different from US keyboards are different from ...)
Also, just a side note: 'A' was a bad example, as 'A' happens to be the same key in dvorak and qwerty... B-)
You might be able to do it via DirectInput, or whatever the current DirectX-equivalent is. I type on a Dvorak keyboard, and about 50% of the games I buy detect my keyboard and reconfigure the default keymappings to support it (using ,aoe instead of wasd, for instance)
And yes, as Brian mentioned, 'A' is the same on both keyboards.
Why would it matter? Depending on some special implementation of a keyboard is no good idea at all. We use barcode scanners all over the place that emulate keyboard inputs. What would your program do with these devices? :)
PS: the mentioned registry entry arranges the keys of a regular keyboard into dvorak layout.