Click here to Skip to main content
15,887,746 members
Please Sign up or sign in to vote.
4.20/5 (2 votes)
See more:
I a developing a touchscreen application where I have to give a keyboard control. For that I need to fire the key press event of all keys which i will be showing as button.

Currently i am using this code,
C#
var key = Key.A;                    // Key to send
           var target = txtUserName;    // Target element
           var routedEvent = Keyboard.KeyDownEvent; // Event to send

            target.RaiseEvent(new System.Windows.Input.KeyEventArgs(Keyboard.PrimaryDevice,
            Keyboard.PrimaryDevice.ActiveSource, 0, key) { RoutedEvent = routedEvent });


Which i got after googling, I have written this on button click but nothing happening.

Please help..

Thanks
Posted
Updated 17-Jul-15 4:55am
v3
Comments
[no name] 16-Jul-15 18:21pm    
Is it possible that "nothing happens" means that you are trying to use keyboard events without an actual keyboard attached to the system?
Sergey Alexandrovich Kryukov 16-Jul-15 19:19pm    
It should be possible to emulate keyboard with WPF without having a physical keyboard. The problem could be different. Please see Solution 1.
—SA
[no name] 16-Jul-15 20:20pm    
I suspect a different problem. I would guess that he is trying to send key presses to something like an on screen keyboard. But since he didn't really describe exactly what he is trying to do, it's just a guess.
Sergey Alexandrovich Kryukov 16-Jul-15 21:01pm    
As you can see, the event it raised on the target textBox1. I can reasonably assume it's just a TexBox, nothing like an on-screen keyboard. Come to think about, it's logical, because the goal is to create some touch input. This is a prototype when a keyboard event is emulated with something hard-coded, but later it will be replaced with calculated touch response. Sound logical to me.
—SA
Sergey Alexandrovich Kryukov 17-Jul-15 2:16am    
See also my comments to Solution 2.
—SA

Thank you for all your clarifications.
In previous version of my answer, I wrote:
If you already have done that, sorry for the dry shot. But then, do the following: provide 100% self-contained project code demonstrating the desired effect, even if it does not work. Make it as small as possible. You don't even need to use any XAML and not even project file. You could fit it to just one file with explicit Application.Run call and just one or two UI elements added in code. It will give you really small code. Describe what you expect from it and what you get instead, why do you feel it's wrong.
Now, I'll try to demonstrate it. To present moment, I failed to reproduce the effect of RaiseEvent to send a character. Then I realized that 1) you don't really need it, 2) it would not help you anyway (but plan to dig into this later).

All your effort was concentrated on simulation of the input on only one target, which is your text box, and, according to your clarification, this is not your final goal. Moreover, using emulation of the events just for UI programming is considered evil; in a number of articles people provided very convinced arguments against that. Please see my comments where I listed some cases where the exclusion should be made. Nevertheless, let's fist implement it, to illustrate how it can be done with just one application:
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

class MainWindow : Window {
    const char demoFrom = 'A';
    const char demoTo = 'F';
    internal MainWindow() {
        this.SizeToContent = SizeToContent.Height;
        this.Width = 200;
        StackPanel panel = new StackPanel();
        this.Content = panel;
        TextBox textBox = new TextBox();
        panel.Children.Add(textBox);
        for (char index = demoFrom; index <= demoTo; ++index) {
            Button button = new Button();
            button.Content = (char)index;
            panel.Children.Add(button);
            button.Click += (sender, eventArgs) => {
                Button senderButton = (Button)sender;
                char toSend = (char)senderButton.Content;
                textBox.SelectedText = string.Empty + toSend;
            };
        } //loop
    } //Main Window
} //class MainWindow

class TheApplication : Application {
    protected override void OnStartup(StartupEventArgs e) {
        this.ShutdownMode = ShutdownMode.OnMainWindowClose;
        MainWindow = new MainWindow();
        MainWindow.Title = "Keyboard Test";
        MainWindow.Show();
    } //OnStartup
    [STAThread]
    static void Main(string[] args) {
        Application app = new TheApplication();
        app.Run();
    } //Main
} //class TheApplication

Naturally, you also need to add arrow keys, delete, backspace and maybe something else. As to upper case and shift, I already recommended you to make it keyboard-internal, just the internal modes of operation. You should simply modify the character your send, but your code should only send a character, nothing else (but you may choose to send some strings at once).

To build this source code as project, you can create WPF project from template (and this is only to eliminate keep WPF referenced assemblies), and then remove each and every file and add only one my file with the content above. This is a one-file solution. Alternatively, you could start from empty project and add WPF references.

Now, as your goal was to create a system-wide virtual keyboard, this is a whole different story. I deserves a separate answer. I just will need more time for that.

—SA
 
Share this answer
 
v7
Comments
Ralf Meier 17-Jul-15 3:22am    
+4 from me because it was a good Inspiration to me - but incomplete ... :(
Sergey Alexandrovich Kryukov 17-Jul-15 11:00am    
Thank you very much, Ralf.
Most likely, this is not the end yet — please see comment in reply to the inquirer's comment below.
—SA
Sanju TV 17-Jul-15 10:50am    
Hi Thanks for the reply.. I will explain my requirement fully

I have an application where i wont be giving physical keyboard. I need to show the keyboard on login its a Touch screen kiosk application. So on key press i need to fire the key event on textbox. In vb i used to do it by sendKey("{A}") but thats not working in WPF.

I have 2 events now button click and textbox keydown, Where i have to write this code. I am working for the first time on WPF.

Thanks.
Sergey Alexandrovich Kryukov 17-Jul-15 11:05am    
Thank you for understanding. You confirmed most of my assumptions. First, is your touch keyboard equivalent to the normal virtual keyboard oriented to mouse or touchpad? Or is it something more complicated?
Secondly, in your prototype/experiment code, did you handle the event on the target as I advised, or you really missed it?
And third, do you really want to make a virtual keyboard operating only on a single text box of a single application? You could create a system-wide virtual keyboard?
In all cases, I can explain how to do it; you just clarify.
—SA
Sanju TV 17-Jul-15 11:09am    
Yes you are right Sir, its a normal virtual keyboard oriented to mouse or touchpad. and its not to be given for a particular textbox. need to apply on some other textboxs also. but i was just checking with 1 first. and sir i coundly follow your advice. I have made a event for textbox keydown which is empty now and a keyboard button click, lets assume its key A. on pressing key A i need to show fire A on textbox
Look for the SendKeys-Method.
With this you could send a KeyCode with a Button-Click ...

Based on the suggestion of Sergey - this code-snipped starts a know method in a known class :
C#
System.Reflection.MethodInfo onKeyDown = YourTextBoxInstance.GetType().GetMethod("OnKeyDown, new object[] { new KeyEventArgs(YourKey) });

in this case the KeyEventArgs should contain the Information about the (simulated) Key.

I must say that this idea is very much better as my solution with the SendKeys-Method ... ;)
 
Share this answer
 
v4
Comments
Sergey Alexandrovich Kryukov 17-Jul-15 1:34am    
It's hard to imagine anything worse. The inquirer tries correct approach, and you are not.
—SA
Ralf Meier 17-Jul-15 1:49am    
I don't have a worse intention ... and I know the problems with the SendKeys.

But I don't see how your solution is solving the inquirers issue.
The goal should be to create a KeyPress inside the TextBox without having a KeyPress (you only have a Button which should work like the KeyChar "A" for example).
Perhaps you give some further Explanation to your Solution - I'm now interested in the result of this Thread too ...
Sergey Alexandrovich Kryukov 17-Jul-15 2:14am    
It's very good that you don't have bad intention, but you see, it can confuse many users. The thing is: SendKeys is nearly always just the evil. There are many articles where it is very arguably explained that using simulated key presses for just UI development is bad practice. But then, what it's good for? Yes, there are cases when such simulation is important. I know at least three examples: 1) recording and playing keyboard macro, 2) creating automated input-driven testing systems (some program imitates UI use behavior); 3) creation of virtual keyboards.

But for such application SendKeys just does not work, it's too weak for that. The only comprehensive tool is P/Invoked Windows API SendInput (perhaps it's bad that there is no such thing in pure .NET).

So, what is it good for? In my opinion, strictly for nothing. I'm waiting if someone gives me the opposite argument, but it never happened.

Now, as to WPF raising events, this is a totally different story. Actually, our inquires tries do to very interesting work (I doubt if it's qualified enough, but this is a different story). I explained my understanding of it in my comment to the question, in response to the comment by Wes Aday, please see. From my point of view, it looks pretty reasonable. This is perhaps one more way when keyboard simulation could be acceptable, because the idea is probably to make the touch gestures a kind of "virtual keyboard". If you look at virtual keyboards available to Android, you will see many interesting approaches of this kind.

So, with all your good intentions, I think you advice is too naive and not fruitful, pretty much based on not understanding a really interesting problem the inquirer is working at.

Thank you for understanding.

—SA
Ralf Meier 17-Jul-15 2:32am    
I understand your explaining why not to use "SendKeys" - what I not understood was your solution.
Sorry Sergey - but now I want to know AND to understand the (better) solution too. Would you be so kind and improve your solution with more Information how to realize it ...?
Sergey Alexandrovich Kryukov 17-Jul-15 2:39am    
Thank you. Maybe later. I want to wait for the inquirer's reply. I'm not 100% sure that I understand the problem and some other detail. Besides, you can add your own questions in the comment. But now, let's wait for the inquirer. If it doesn't happen, feel free to remind me.
—SA
In my answers, I ignored your code sample using RaiseEvent and never properly explained what was wrong with it. But you probably need to understand it.

I finally tried to reproduce the use of raising event and finally realized why you see "nothing happening" as a result.

The answer is: it actually does work. It does what's intended: it really raises the specified event on the specified target. As a result, all the event handlers added to the invocation list of the event instance of the target are invoked. This is the real effect of RaiseEvent. This is easy to check up if you subscribe to one or more of keyboard events — I just tried it, and it works.

The only problem is: you cannot use is to simulate the usual, for example, text box behavior in response to the keyboard action, such as adding or removing characters. It is only related to the events fired in response to the hardware events. When you handle your keyboard event, the low-level keyboard event has already happened, and it's handling (resulting in, say, adding a character to the text box) will happen even if you don't subscribe to any events. You can only get the notification on this (in order to do something else), or, very importantly, you can block event handling by assigning eventArgs.Handled = false; the events like UIElement.KeyDown are invoked in between just to give you this opportunity to get notification and/or modify the behavior. (In such considerations, you should not mix up the event as the member of some type, the event instance and event as the dynamic act of the change of the system state.)

RaiseEvent just gives you another way to raise these UIElement events. Note that it is not allowed to call event Invoke on any event instance from any place of code, except the code which is placed in the declaring class. RaiseEvent gives you a back door, just for the class UIElement.

Conclusion: there is no a way to use RaiseEvent to emulate the keyboard action. The way to do so is described in Solution 3.

—SA
 
Share this answer
 
v3
Comments
Sanju TV 19-Jul-15 16:50pm    
Hi SIr, Thanks a lot, I have gone through now.. Now i understood whats happening on raise event. Now i could show the pressed key on the focused textbox. But another issue currently i am facing is on arabic characters. I have changed the keyboard language into arabic and after pressing on physical keyboard its showing as arabic and when i press the touchkeyboard (Which i made) its showing the actual key.

txtUSerName.Text += e.Key;
txtUSerName.CaretIndex = txtUSerName.Text.Length;

I have written the following code on keydown event.
Sergey Alexandrovich Kryukov 19-Jul-15 22:46pm    
This is totally unrelated problem. There is no difference between Arabic characters and others, such as Latin. In essence, you can enter any character. Perhaps you need to ask a separate question.

Are you going to accept the answers formally?

—SA
My Solution 1 illustrated how to add create a mouse- or touch-only virtual keyboard for just one application. My demo addressed the case when you send input only to one fixed text box, following your own sample, but it could easily fixed by having variable target pushed to the keyboard, the target can be changed by handling the events GotFocus/LostFocus. You could even handle other types of controls; for example, search by name in some list controls. All such generalizations cannot solve the problem of making system-wide virtual keyboard.

The problem is subdivided in two parts 1) how to simulation the keyboard action without the keyboard; this aspect is common for all kinds of .NET desktop application; 2) how to build the UI which won't grab input focus; below, I'll try to explain why it is critically important. The second item depends on the Windows application's framework/library used.

Let's be logical: in a system-wide context, you need to do what the physical keyboard does, no less. The keyboard just throws the even into the system, without knowing what application is active and what control is in focus. Needless to say, nothing specific to WPF won't work: you will need to send input to any application according to the current keyboard focus. From the other hand, you cannot use anything like sending events in any forms (Windows messages), because some applications, such as WPF, don't use Windows message pumping at the level of control, they take input messages only at the level of the top window; and then everything is translated to WPF internal event mechanism. Naturally, your system-wide virtual keyboard is a separate application process which have no access to all that.

Therefore, you can only simulate input at the low level, doing what a physical keyboard driver does. This is the Windows API SendInput:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310%28v=vs.85%29.aspx[^].

To use it, you will have to use P/Invoke. However, this is already done for you: http://www.pinvoke.net/default.aspx/user32.sendinput[^].

Yes, P/Invoke is not desirable, but, first, there is no a better choice, and then, you already use WPF, which is not implemented on non-Windows platforms so, as far as I know.

Now, we are coming to the second part. It raises the problem of the UI. If you use SendInput, keyboard input will go to the control which has input focus at the moment. Your UI application is totally unaware of it, but when you click on the keyboard button, it can take the control focus from previously focused edit control, so your input will go nowhere. The problem is solvable, but it can be pretty tricky. Naturally, the solution depends on the Windows application's framework/library used.

First of all, I would suggest to solve this problem not in WPF, but in a Forms application. The trick is: you can make your virtual keyboard topmost (maybe temporarily) but, at the same time, unable to activate. Again, the solution is Windows-specific. For a form, this is done using special CreateParams. In my past answer, I described the complete solution: Application focus getting and losing[^].

Recently, I tried to solve this problem for WPF. I'm not sure if you can make the main window unable to activate of not grabbing the focus, but it can certainly be done with another specific UI element, System.Windows.Controls.Primitives.Popup, which does not grab focus but can have clickable child element which can have, say children of Button type:
https://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.popup%28v=vs.110%29.aspx[^].

Unfortunately, with this approach you will still need some main window, because the Popup instance needs some parent. (You can use this window to show some options, or anything like that.) When popup is activated (the property Popup.IsOpen), you can click on the buttons in it, and the input control will still be in some other application, if your activate it. I prototyped it; it worked immediately. One delicate moment is Popup.Placement. You can place it anywhere you want, which include the setting of arbitrary location relative to the desktop: https://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.popup.placement%28v=vs.110%29.aspx[^].

That gives you the freedom of placing your virtual keyboard independently from the location of you main window. Moreover, you can think of such a suitable UI design as the UI application put on the system tray (in Forms, this is called NotifyIcon application type, which you still can use in the Forms application the way I described above). If I'm not much mistaken, such type of WFP application is absent from the .NET FCL, but third-party solutions do exist. In particular, check out this CodeProject article: WPF NotifyIcon[^].

Also, I wanted to say thank you for bringing the problem with RaiseEvent to my attention. This is really the only universal way to raise events in UI elements from the code outside of the event's declaring class. Only it has nothing to do with what you want to achieve.
Good luck.
—SA
 
Share this answer
 
v7
Comments
Sanju TV 18-Jul-15 6:42am    
Hi sir, Thanks for your time and reply.. I still finds difficult to follow your method, Can you please send me a sample application, If you dont mind.
Sergey Alexandrovich Kryukov 18-Jul-15 8:20am    
You are welcome, but this is not a "reply", this is a complete solution.

Not sure. You might have to wait too long. Do you understand how much extra work could it be? My instructions are clear enough; and I made major research job for you. You know what? — if you find it so difficult that you don't even want to try, getting more code will be useless. Anyway, the only way I would publish more material would be a complete article with the fully-fledged application, but I'm not sure if I find time for that. Maybe some other member will be more interested in this work than you are. Or you just need to pick up the project where you are more comfortable that this one, which could be not the easiest.

—SA
Sanju TV 18-Jul-15 10:38am    
I m still trying, just asked if i can get. Any ways thanks sir will be trying and once i get the result will update here.
Sergey Alexandrovich Kryukov 18-Jul-15 12:52pm    
If you are trying, you may have questions which you can ask, they will be welcome.
And how about Solution 1 which you can immediately compile and see how it works?
—SA
Ralf Meier 20-Jul-15 1:00am    
@Sergey:
I must speak like the inquirer :
I see, that you have spend a lot of time and made a lot of work to write this text - but I'm also no step further to the point I'm interested in (it seames to be the same as the point of the inquirer).

When resuming it all :
What I haven't realized before was the part with the Reflection. That guided me to a problem from one of my first question in this Forum about "Overriding of derived Events" - now I know how to solve this.
This part I have writen in my solution in this Thread.

The second part I'm interesting in (like the inquirer) was the complete simulation of a Keystroke (like SendKeys does) but completly directed to a specified class / control. I'm sorry, but I can't vote your work because for me the problem isn't fixed yet - but perhaps later.
One thing I have learned : you (I) only have to wait and suddenly you come to a goal (unfortunately not with your own question).

My thanks also to the inquirer for this interesting (but unfortunately not finished) question.

Greetings
Ralf

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900