http://www.codeproject.com/Articles/4693/IP-Address-TextBox
可以下载试用效果。个人感觉功能很强大,但输入时让人不太舒服。可以参考。
ntroduction
Problem was, I didn‘t find a solution to edit an IP address like in Windows network environment, for C#. Although there are some controls for masked edit fields, I wanted to write my own, and if so I wanted it to behave like the controls from MFC library or Windows network environment and maybe a little more.
Problems to solve
The heaviest problem at writing the control was to catch the inputs of backspace and delete keys, to delete characters from the input field. I tried a lot with overridden event handlers, OnKeyDown
and OnKeyUp
but it didn‘t work like it should.
Then I remembered that another developer had overridden the PreProsessMessage
method to catch keyboard inputs and handle it in own ways. So I implemented an override for PreProcessMessage
to handle all the backspaces and delete key presses and used OnKeyUp
, OnKeyPress
and OnKeyDown
to handle the inputs of dots and slashes and set the input cursor to the right position.
OnKeyDown event
/// <summary> /// Override standard KeyDownEventHandler /// Catches Inputs of "." and "/" to jump to next positions /// </summary> /// <param name="e">KeyEventArgument</param> protected override void OnKeyDown(KeyEventArgs e) { //Zeichen an die richtige stelle schreiben int iPos = this.SelectionStart; char[] cText = this.Text.ToCharArray(); if(e.Modifiers == Keys.None) { if((char.IsLetterOrDigit(Convert.ToChar(e.KeyValue)) || e.KeyCode == Keys.NumPad0)//Numpad0=96 --> ` && iPos < this.TextLength) { if(cText[iPos] == ‘.‘ || cText[iPos] == ‘:‘ || cText[iPos] == ‘/‘) iPos+=1; this.SelectionStart = iPos; if(this.OverWriteMode) { if(cText[iPos] != ‘ ‘) this.SelectionLength = 1; } else { if(iPos < this.TextLength) if(cText[iPos] == ‘ ‘) this.SelectionLength = 1; } } } base.OnKeyDown (e); }
OnKeyUp event
/// <summary> /// Override standard KeyUpEventHandler /// Catches Inputs of "." and "/" to jump to next positions /// </summary> /// <param name="e">KeyEventArgument</param> protected override void OnKeyUp(KeyEventArgs e) { //Zeichen an die richtige stelle schreiben int iPos = this.SelectionStart; char[] cText = this.Text.ToCharArray(); //Cursor hintern Punkt setzen if((char.IsLetterOrDigit(Convert.ToChar(e.KeyValue)) || e.KeyCode == Keys.NumPad0)//Numpad0=96 --> ` && iPos < this.TextLength) { if(cText[iPos] == ‘.‘ || cText[iPos] == ‘:‘ || cText[iPos] == ‘/‘) iPos+=1; this.SelectionStart = iPos; } base.OnKeyUp (e); }
OnKeyPress event
/// <summary> /// Override standard KeyPressEventHandler /// Catches Inputs of "." and "/" to jump to next positions /// </summary> /// <param name="e">KeyPressEventArgument</param> protected override void OnKeyPress(KeyPressEventArgs e) { //Zulassige Zeichen if(char.IsControl(e.KeyChar) || m_regexValidNumbers.IsMatch(e.KeyChar.ToString())) { e.Handled = false; } else { switch(e.KeyChar) { case ‘/‘: this.JumpToSlash(); break; case ‘.‘: this.JumpToNextDot(); break; default: break; } e.Handled = true; } base.OnKeyPress(e); }
PreProcessMessage
/// <summary> /// Override standard PreProcessMessage /// Catches Inputs of BackSpace and Deletes /// </summary> /// <param name="msg">PreProcessMessage</param> public override bool PreProcessMessage(ref Message msg) { if (msg.Msg == WM_KEYDOWN) { Keys keyData = ((Keys) (int) msg.WParam) |ModifierKeys; Keys keyCode = ((Keys) (int) msg.WParam); int iPos = this.SelectionStart; char[] cText = this.Text.ToCharArray(); switch(keyCode) { case Keys.Delete: if(iPos < this.TextLength) { while(cText[iPos] == ‘.‘ || cText[iPos] == ‘:‘ || cText[iPos] == ‘/‘) { if((iPos+=1) >= cText.Length) break; } if(iPos < this.TextLength) { base.Text = this.Text.Substring(0,iPos) + " " + this.Text.Substring(iPos+1); this.SelectionStart = iPos+1; } else this.SelectionStart = this.TextLength-1; } return true; case Keys.Back: if(iPos > 0) { while(cText[iPos-1] == ‘.‘ || cText[iPos-1] == ‘:‘ || cText[iPos-1] == ‘/‘) { if((iPos-=1)<=0) break; } if(iPos>0) { base.Text = this.Text.Substring(0,iPos-1) + " " + this.Text.Substring(iPos); this.SelectionStart = iPos-1; } else this.SelectionStart = 0; } return true; default: break; } } return base.PreProcessMessage (ref msg); }
Another problem was the input of numbers via the numpad. Especially the 0 key was not recognized, because it‘s char value is neither a letter nor a digit, so I had to ask for Keys.NumPad0
hard coded.
Hide Copy Code
if((char.IsLetterOrDigit(Convert.ToChar(e.KeyValue)) || e.KeyCode == Keys.NumPad0)//Numpad0=96 --> ` iPos < this.TextLength) {[...]}
At least...
...I have a control that looks like a TextBox
with dots, where I can input numbers, type dots to jump to next IP parts, and get its contents via the Text
property.
Using the code
Include the IPAddressTextBox.cs in your project. Set a TextBox
in your form or user control and clear its contents. Change the type of this TextBox
from System.Windows.Forms.TextBox
to rj2_cs.IPAddressTextBox
in code editor. Then you can change the properties of the IP textbox like you want.