locked
How do I make buttons to be as reaponsive as virtual keyboard buttons?

    Question

  • For my app, I've created a custom keyboard since the virtual keyboard covers up too much real estates.  It works fine if you type at a reasonable pace, but I can't type fast because it the letters would skip.  Any idea on how I can make my buttons event handler as fast as the virtual keyboard?
    Saturday, June 14, 2014 2:21 PM

Answers

  • There is no way to inject actual keyboard input, so you won't be as fast. You may be able to speed up your code some though. The problem is not with the button but with trying to manipulate the TextBox's buffer from outside. For real keyboard input the TextBox handles it directly and can modify its buffer in place.

    In your case this line is slow for several reasons:

    App.focusbox.Text += temp;

    Each access needs to transition to the Windows Runtime, marshall back the entire text of the focusbox, create a whole new string, and then send that new string back to the focusbox.

    You can optimise this a bit. Instead of using string addition (slow because strings are immutable so addition creates new ones each time) create a StringBuffer large enough for your expected text and append the char within the StringBuffer. Reallocate the buffer only when the intents grow too large and then do so in chunks.

    Reducing the chattiness with the TextBox will be trickier as you both want to keep up (make fewer calls) and want to keep the output responsive. You can batch calls rather than updating on every character, but you will need to play with this to find a balance between batching up calls and immediate responsiveness. You might put in some feedback based on time so if Clicks come in slowly you send them immediately bit if they are fast you batch up a few. 

    Unfortunately this isn't something you can defer to worker thread so you have one thread stowing up the "keystrokes" and a second passing the buffer to the TextBox.

    To maximise speed you might want to replace the TextBox completely. If your text handling needs are simple you can manage the string buffer completely on your own and display it with DirectWrite.


    Tuesday, June 17, 2014 2:14 PM
    Owner

All replies

  • If you're debugging with the frame rate counter is there any drop in the frames per second as you type quickly? If so, this could mean the UI is doing a lot of the processing work.

    What do you have running when a button is pressed? Maybe you have some processing that could be moved to a background thread using Threading.Task.Run(). If so this may free up the UI to be more responsive.

    I would also try debugging with the setting that allows you to see which areas of the screen are updated with each layout pass. DebugSettings.IsOverdrawHeatMapEnabled is the name of the setting to enable in App.xaml.cs.


    Sunday, June 15, 2014 3:41 PM
  • Thank you for your reply. Here are the codes.

    <Button IsDoubleTapEnabled="False"   Tapped="button1" x:Name="Q" Content="Q" />
                    <Button IsDoubleTapEnabled="False"   Tapped="button1"   x:Name="W" Content="W"/>
                    <Button IsDoubleTapEnabled="False"   Tapped="button1"   x:Name="E" Content="E"/>
    
    .........

    	private void button1(object sender, TappedRoutedEventArgs e)
            {
                var button = (Button)sender;
    
                settext(button.Name);
    
    
            }
    
    
            private void settext(string temp)
            {
                try {
                    App.focusbox.Text += temp;
                }
                catch { 
                    return; 
                }
            }



    • Edited by RandyPete Monday, June 16, 2014 10:31 PM
    Monday, June 16, 2014 10:19 PM
  • There is no way to inject actual keyboard input, so you won't be as fast. You may be able to speed up your code some though. The problem is not with the button but with trying to manipulate the TextBox's buffer from outside. For real keyboard input the TextBox handles it directly and can modify its buffer in place.

    In your case this line is slow for several reasons:

    App.focusbox.Text += temp;

    Each access needs to transition to the Windows Runtime, marshall back the entire text of the focusbox, create a whole new string, and then send that new string back to the focusbox.

    You can optimise this a bit. Instead of using string addition (slow because strings are immutable so addition creates new ones each time) create a StringBuffer large enough for your expected text and append the char within the StringBuffer. Reallocate the buffer only when the intents grow too large and then do so in chunks.

    Reducing the chattiness with the TextBox will be trickier as you both want to keep up (make fewer calls) and want to keep the output responsive. You can batch calls rather than updating on every character, but you will need to play with this to find a balance between batching up calls and immediate responsiveness. You might put in some feedback based on time so if Clicks come in slowly you send them immediately bit if they are fast you batch up a few. 

    Unfortunately this isn't something you can defer to worker thread so you have one thread stowing up the "keystrokes" and a second passing the buffer to the TextBox.

    To maximise speed you might want to replace the TextBox completely. If your text handling needs are simple you can manage the string buffer completely on your own and display it with DirectWrite.


    Tuesday, June 17, 2014 2:14 PM
    Owner