Windows Forms autotab

In Windows Forms is there an autotab capability   

It existed in MFC where when typing into an Edit control (textBox), once the max number of characters for the control was exceeded, the focus went to the next control and the characters were entered there.  I often see the feature while typing Microsoft serial numbers during software installations.



Answer this question

Windows Forms autotab

  • Greg_AD

    BTW, I write a monthly tips column for <a href="http://vbnetadvisor.com/">Advisor Publications </a> and would like to use this as a tip, in VB.NET. May I use your name as the "author"

  • RussMan

    I do not believe so.

    It would be simplistic to emulate using the TextChanged event and SendKeys.


    private void textBox1_TextChanged(object sender, System.EventArgs e)
    {
    if (textBox1.Text.Length == textBox1.MaxLength)
    {
    SendKeys.Send("\t");
    }
    }

  • dhum11

    I was not familiar with SendKeys, this is very helpful.  For my purposes, however, it will work better to overload the KeyPress event.

    Thanks.  I'll post the code when I have it finished.

  • Ariff

    Oh, but I just got this wonderful autotab control written up with SendKeys!  Is SendKeys a security risk or something

    Also, is there a way to know if text in a TextBox is selected at all

  • jeffnc

    Planning on posting your finished version
  • Ron Luebke

    You certainly may.

    Here's my email if you need more info, minus the 123 (an idea gleaned from your web page):

    <A HREF="mailto:lerdmann@123state.nd.us">lerdmann@123state.nd.us</A>


  • RobertaK

    I would also do anything in my power to avoid SendKeys, which is still a dangerous tool. An alternative is to use the GetNextControl method of the control, and set focus to that control if your control has "filled up".
  • simon denyer

    My intent is for the autotab to take place only when the input has exceeded the MaxLength value.  Some users are used to hitting the tab button between text boxes, others just keep on typing.  If the autotab only happens when the MaxLength has been exceeded, then both groups are happy.  

    Using the TextChanged event, there is no way to know when the length has been exceeded, but that is something I can do in KeyPress. 

    Here is the code as I've written it, and it does exactly what I want:


    protected override void OnKeyPress(KeyPressEventArgs e)
    {
    if (Text.Length == MaxLength) // we have exceeded the MaxLength 
    {
    string keyEntered = "";
    keyEntered = e.KeyChar.ToString();  
    keyEntered = keyEntered.Substring(0,1);  // store the first keystroke
    Regex rx = new Regex("[0-9a-fA-F]");     
    bool isValid = rx.IsMatch(keyEntered);   // make sure it's alphanumeric
    if (isValid)
    {
    e.Handled = true;
    SendKeys.SendWait("\t");    // tab to next control
    SendKeys.Send(keyEntered);  // send the keystroke
    }
    }
    base.OnKeyPress(e);
    }



    I can see how the SendKeys class can be problematic.  Thanks for the info.


  • liquidVapour

    Ken is (of course) right to avoid the use of SendKeys.  GetNextControl is a nice addition to my toolbox.   

    I did have to change CanFocus to CanSelect. I looped through the controls till I found the first selectable one. It seems that some controls can screw up the works.  The problem occured with a PictureBox on the form (It returned true for CanFocus in v1.0). 

    '*** Not sure if VB loop will short circut on 'ctl is nothing' -> Ken will know.

    Dim ctl as Control = Me.Parent.GetNextControl(Me, True)
    Do Until ctl is nothing or ctl.CanSelect or ctl = Me
       ctl = Me.Parent.GetNextControl(ctl,True)
    Loop

    If not ctl is nothing
       ctl.Focus()
    End If


    Another thought
    ===========
    I did not use the KeyPress event because it takes a lot more code to handle the event. It is fired for control keys and such. TextChanged will also handle copy/paste events.

    Your other question
    =============
    SelectionText, SelectionStart and SelectionLength are the properties you can use to see if the TextBox has anything selected.

  • Jiadong

    Yes, it looks like your solution works best in your situation. For cases like those you come across when entering a product code for a Microsoft product, however, the solution I presented works fine without SendKeys. But I don't see any reasonable solution that works the way you want without it.

    I do have one final suggestion, however. No need to use RegEx (although since this only occurs once per input control, it hardly makes any difference). But you can get away with this in a more simple manner, using the Char.IsLetterOrDigit method, and the TextLength property:

    protected override void OnKeyPress(KeyPressEventArgs e)
    {
      if (TextLength == MaxLength) // we have exceeded the MaxLength 
      {
        if (Char.IsLetterOrDigit(e.KeyChar))
        {
          e.Handled = true;
          SendKeys.SendWait("\t");    // tab to next control
          SendKeys.Send(e.KeyChar.ToString());  // send the keystroke
        }
      }
      base.OnKeyPress(e);
    }


  • Ian_E

    Looks like it will work if 

    base.OnKeyPress(e)

    knows what to do with the invalid characters (punctuation, spaces, etc.). Otherwise, you could easily exceed MaxLength and continue on and on.  Paste could also make your system jump over MaxLength.

    I do like that your code does not fail when the user hits tab at the expected time. 


    P.S.
    Are you sure that the user cannot insert a new character between the two SendKeys calls  Some people can really fill a buffer. Maybe 

    SendKeys.SendWait("\t" + keyEntered);

    would be safer.  

  • Inky

    After playing around with the GetNextControl method and trying some other ways to do this that avoid SendKeys, none of them function exactly the way I want, so the final code is not much different from what Ken last posted.  

    I did add a couple of properties, the AutoTab property that allows you to turn off the functionality, and the SelAllOnEnter property will select the text for you when you enter the TextBox.


  • Carl In Milford

    I figured there was something like that that would evaluate the individual character (I knew how to do it in C++), but I decided to go the overkill route and use the Regex because I was feeling lazy.  I'll do the final cleanup and post the code again.


  • _howard

    The problem with SendKeys is that it can't know what application it's sending keys to. Imagine that at just the wrong moment, the user pressed Alt+Tab, and switched to another application. If you had already placed the keystroke into the keyboard buffer, the keys you've passed to SendKeys would now be sent to the application that had the focus.

    In other words, to use SendKeys, you either must not care if the keystrokes go to the wrong app, or constantly check to see if the app is correct and switch back if it's not. Neither is a perfect solution. 

    So, just for fun, I created a new class and added this functionality:

    Public Class TextBoxAutoTab
      Inherits TextBox

      Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
        MyBase.OnTextChanged(e)

        If Me.TextLength = Me.MaxLength Then
          Dim ctl As Control = Me.Parent.GetNextControl(Me, True)
          If Not ctl Is Nothing Then
            If ctl.CanFocus Then
              ctl.Focus()
            End If
          End If
        End If
      End Sub
    End Class

    You could obviously add more functionality (for example, have the code look for the next control that can receive the focus, rather than simply giving up if the next control cannot). 

    To use this, you can either create a real control (so you can add the control to the toolbox) or, the simple solution is just to open the hidden region of your form's code and replace the pertinent instances of System.Windows.Forms.TextBox with the name of this class (which I called TextBoxAutoTab). Worked great, in my limited tests. 

  • Windows Forms autotab