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