2

I want to use the C# System.Windows.Forms.SendKeys.SendWait() Method to send Keystrokes from an OnScreenKeyboard to a Textbox. Since I may use this OnScreenKeyboard at other places too I created a UserControl with View (for the Design of the Keyboard) and Viewmodel (basically for calling the Sendkeys.SendWait() Method) in an extra project.

Within this project I created a MainView where I included the UserControl via a ContentControl as you can see in the Code below. CurrentPage basically refers to the Viewmodel of the Keyboard.

    <Window.Resources>
        <DataTemplate DataType="{x:Type viewModel:KeyboardViewmodel}">
            <view:KeyboardView/>
        </DataTemplate>
    </Window.Resources>

    <Grid>
        <Border Background="White">
            <HeaderedContentControl Content="{Binding Path=CurrentPage}"/>
        </Border>

        <TextBox Width="120"/>
    </Grid>

I now have the OnScreenKeyboard and a Textbox in my Window. Clicking into the Textbox and pressing buttons of my OnScreenKeyboard will result in text appearing in my Textbox. All Controls within the KeyboardView are set to avoid getting focus. This is necessary to maintain focus on the Textbox.

The Buttons in the KeyboardView all bind to the Command ClickCommandin my KeyboardViewmodel. Here is the code of the KeyboardViewmodel:

public class KeyboardViewmodel : BaseModel
{
    public BaseCommand ClickCommand { get; set; }

    public KeyboardViewmodel()
    {
        ClickCommand = new BaseCommand(PressAndRelease);
    }

    public void PressAndRelease(object key)
    {
        if (((string)key).Length <= 1)
            SendKeys.SendWait((string)key);
        else
            SendKeys.SendWait("{" + (string)key + "}");
    }
}

Now I did create a NuGet Package with these Files and imported them to the project where I want to use my OnScreenKeyboard.

I did do basically the same as when I tested the OnScreenKeyboard before. But let me explain the structure of the project a little more: I have a MainView + MainViewmodel. The MainViewmodel manages the navigation between available pages. To show these pages I have - as in the short example before - a ContentControl whose content is bound to a CurrentPage Property. The MainViewis a normal Window, all other Views are UserControls.

In one of these pages I need an OnScreenKeyboard (DetailsView + DetailsViewmodel). So it seemed logical to me to use another ContentControl within the DetailsView:

<Border Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="3" Height="Auto" Width="Auto">
    <ContentControl Content="{Binding Path=OnScreenKeyboard}"/>
</Border>

I create the KeyboardViewmodel in the constructor of the DetailsViewmodel. The constructor of the DetailsViewmodel is called in the MainViewmodel at startup.

So now everything works out fine so far, the OnScreenKeyboard is shown on the correct page in the correct place. If I click a button of the OnScreenKeyboard the proper bound command is called and the SendKeys.SendWait() Method is called.

But no text appears in the TextBox. I have a very bad understanding of the SendKeys.SendAwait() Method. Also, the MSDN Documentation seems to be not very exhaustive on this topic.

It states: "Sends the given keys to the active application, and then waits for the messages to be processed."

Now. The Active / Focused Application is my Application. So my guess is that the KeyStrokes should be processed by my Textbox.

My Questions:

  1. Any guesses how to debug the 'SenWait()' Method further e.g. track where the strokes are really sent to or something like that?
  2. Is this the correct way for sending KeyStrokes to an active Application? It seems like SendKeys comes from Windows Forms, I use WPF.
  3. Should I just pass my Textbox as reference to the OnScreenKeyboard and write directly to the referenced Textbox? This would make me much less flexible in regards of reusability.

Update: As pointed out in the comments this could probably be a duplicate question. I am well aware of the various different solutions and have already considerd them:

  1. http://wpfkb.codeplex.com/
  2. http://www.codeproject.com/Articles/32568/A-Touch-Screen-Keyboard-Control-in-WPF
  3. http://www.codeproject.com/Articles/145579/A-Software-Virtual-Keyboard-for-Your-WPF-Apps

But as one may understand these projects are looking all way too powerfull for my simple needs.

Here a screenshot to provide a better understanding of my needs: OnScreenKeyboard

It is really as simple as that. 4 rows of buttons that will never change, no other controls / functionality than sending the CommandParameter of the pressed button to the Textbox / Active Form.

Researching on that specific problem hasn't shown any problems like that. In most other SO Questions the problem is to send Data to another Window, not to send Data WITHIN the current Window. So I don't consider this question as duplicate.

Haini
  • 922
  • 2
  • 12
  • 28
  • 1
    SendKeys is a curse that .NET acquired due to its need to stay compatible with VB6. Just don't reinvent this wheel, it is very hard to make round. Simply google "wpf onscreen keyboard" to find *lots* of existing implementations. – Hans Passant Aug 22 '14 at 12:38
  • @HansPassant : Edited my question to specify my problem. – Haini Aug 22 '14 at 12:51
  • "I need something less powerful" isn't much of a problem description. – Hans Passant Aug 22 '14 at 13:29

0 Answers0