Windows Develop Bookmark and Share   
 index > Windows Forms General > Windows Forms autotab
 

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.

MigrationUser 1  Thursday, October 02, 2003 5:51 PM
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");
}
}
MigrationUser 1  Friday, October 03, 2003 10:02 AM
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.
MigrationUser 1  Friday, October 03, 2003 12:30 PM
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".
MigrationUser 1  Monday, October 06, 2003 9:57 AM
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?
MigrationUser 1  Monday, October 06, 2003 10:57 AM
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. 
MigrationUser 1  Monday, October 06, 2003 2:27 PM
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.
MigrationUser 1  Monday, October 06, 2003 3:15 PM
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.

MigrationUser 1  Monday, October 06, 2003 5:20 PM
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.  
MigrationUser 1  Tuesday, October 07, 2003 1:46 AM
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);
}

MigrationUser 1  Tuesday, October 07, 2003 8:53 AM
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"?
MigrationUser 1  Tuesday, October 07, 2003 8:54 AM
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>

MigrationUser 1  Tuesday, October 07, 2003 10:56 AM
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.

MigrationUser 1  Tuesday, October 07, 2003 11:04 AM
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.

MigrationUser 1  Tuesday, October 07, 2003 3:08 PM
Planning on posting your finished version?
MigrationUser 1  Wednesday, October 08, 2003 9:50 AM
I've added provisions for the AutoTab property, and for the case of text being selected in the TextBox (which produced a nasty infinite loop if all of your TextBoxes were set to select all text on entry).  I used the SelectedText property from the TextBoxBase parent class to do that.

<CODE>
protected override void OnKeyPress(KeyPressEventArgs e)
{
     // we have exceeded the MaxLength and need to autotab
     if (Text.Length == MaxLength && autoTab && 
        SelectedText.Length==0 && 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);
}
</CODE>

I can email anyone who wants the full source code for the control, which includes the AutoTab and SelAllOnEnter properties.  If you're interested shoot me a note at <a HREF="mailto:lerdmann@123state.nd.us"> lerdmann@123state.nd.us</a> (minus the "123").
MigrationUser 1  Wednesday, October 08, 2003 1:04 PM
Cool. Good catch on the selected text! That would have been ugly. 
MigrationUser 1  Thursday, October 09, 2003 8:25 AM
Levi,

Nice solution.  I intend to borrow heavily from it.   

Question:
Aren't you restricting what can be entered as the first character in the next control?  What would happen if the next control was a CheckBox and the user hit the space bar. I believe the autotab control would consume the space and focus would not change. The same situation could occur if the next control accepted all characters (note field). 

MigrationUser 1  Thursday, October 09, 2003 9:23 AM
What a cool idea.  I was only thinking about autotabbing to text boxes when writing the control, but this works great with checkboxes too when you allow for spaces.
<CODE>
protected override void OnKeyPress(KeyPressEventArgs e)
{
// we have exceeded the MaxLength and need to autotab
if (Text.Length == MaxLength && autoTab && SelectedText.Length==0
 && (char.IsLetterOrDigit(e.KeyChar) || e.KeyChar==' '))
{
e.Handled = true;
SendKeys.SendWait("\t");    // tab to next control
SendKeys.Send(e.KeyChar.ToString());  // send the keystroke
}
base.OnKeyPress(e);
}  </CODE>
Good thinking!
MigrationUser 1  Thursday, October 09, 2003 10:48 AM
Mike,

Sorry I got a little excited and didn't answer the rest of your question.  I found out that if you hold down the shift key when the autotab takes place, the SendKeys sends the '\t' and is processed in conjunction with your pressed shift key, which sends focus back to the previous control!

I left out the symbols and punctuation because for my application, they would never be the first characters in any of my fields (which consist mainly of dates and names).  When I tried doing the symbol processing stuff, I found that SendKeys won't work with them.  Try, for example, entering the '#' character without pressing the shift key. 

As always, any thoughts on this interesting problem are welcome.  8)

MigrationUser 1  Thursday, October 09, 2003 11:34 AM

can any one give the complete code pelase for this auto tab in windows form when i am typing the maximum property is not dispalyed please help me
chaitu2  Friday, August 03, 2007 5:44 AM

You can use google to search for other answers

Custom Search

More Threads

• PrintDialog & PrintDocument are Printing The Document With Out Text.
• Graphic in .Net executable
• Open file dialog opening multiple files and customization
• ListView column creation race condition?
• display textbox value
• RichTextBox problem
• Problem in changing the custom icon for a Windows form...
• Is it possible to acquire .NET form object properties from a parent application by another application?
• Enabling/Disabling Apply button on form
• form's UserControl.AutoSize property keeps resetting itself to true.