Issue with custom Password Textbox class in C# Winforms similar to Android -


i want implement custom password textbox allow me enter alphanumeric characters behaves in way similar android edittext control. i.e. have display character entered few milliseconds before masking using "asterix" or other password character. should able edit/insert/delete character anywhere in content.

for have implemented customized textbox. there lot of issues face.

here, adminpassword field contain actual password text , not '*' literals.

using system; using system.collections.generic; using system.globalization; using system.linq; using system.text; using system.windows.forms;  namespace passwordtextbox {      public class passwordtextbox : textbox     {         private readonly timer timer;         private char[] adminpassword = new char[16];         private readonly char decimalseparator = cultureinfo.currentculture.numberformat.numberdecimalseparator.tochararray()[0];          /// <summary>         ///          /// </summary>         public passwordtextbox()         {             timer = new timer {interval = 200};             timer.tick += timer_tick;         }          /// <summary>         ///          /// </summary>         public string adminpassword         {                         {                 return new string(adminpassword).trim('\0').replace("\0", "");             }         }          /// <summary>         ///          /// </summary>         /// <param name="e"></param>         protected override void ontextchanged(eventargs e)         {             base.ontextchanged(e);             txtinput_textchanged(this,e);          }          /// <summary>         ///          /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         private void txtinput_textchanged(object sender, eventargs e)         {             hidepasswordcharacters();         }          /// <summary>         ///          /// </summary>         private void hidepasswordcharacters()         {             int num = this.text.count();              if (num > 1)             {                 stringbuilder s = new stringbuilder(this.text);                 s[num - 2] = '*';                 this.text = s.tostring();                 this.selectionstart = num;                 timer.enabled = true;             }         }          protected override void onkeydown(keyeventargs e)         {             base.onkeydown(e);             if (e.keycode == keys.delete)              {                 deleteselectedcharacters(this,e.keycode);             }         }          /// <summary>         /// windows timer elapsed eventhandler          /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         private void timer_tick(object sender, eventargs e)         {             timer.enabled = false;             int num = this.text.count();             if (num > 1)             {                 stringbuilder s = new stringbuilder(this.text);                 s[num - 1] = '*';                 this.invoke(new action(() =>                 {                     this.text = s.tostring();                     this.selectionstart = num;                 }));             }         }          protected override void onkeypress(keypresseventargs e)         {             base.onkeypress(e);              int selectionstart = this.selectionstart;             int length = this.textlength;             int selectedchars = this.selectionlength;             this.textchanged -= new system.eventhandler(txtinput_textchanged);              if (selectedchars == length)             {                 /*                  * means complete text selected clear before using                  */                 clearcharbufferplustextbox();             }              keys emodified = (keys)e.keychar;              if (e.keychar == decimalseparator)             {                 e.handled = true;             }             if ((keys.delete != emodified) && (keys.back != emodified))             {                 if (keys.space != emodified)                 {                     if (e.keychar != '-')                     {                         if (!char.isletterordigit(e.keychar))                         {                             e.handled = true;                         }                         else                         {                             adminpassword = new string(adminpassword).insert(selectionstart, e.keychar.tostring()).tochararray();                         }                     }                 }                 else                 {                     if (this.textlength == 0)                     {                         e.handled = true;                         array.clear(adminpassword, 0, adminpassword.length);                     }                 }             }             else if ((keys.back == emodified) || (keys.delete == emodified))             {                 deleteselectedcharacters(this, emodified);             }              /*              * replace characters '*'              */             hidepasswordcharacters();              this.textchanged += new system.eventhandler(this.txtinput_textchanged);         }          /// <summary>         /// deletes specific characters in char array based on key press action         /// </summary>         /// <param name="sender"></param>         private void deleteselectedcharacters(object sender, keys key)         {             int selectionstart = this.selectionstart;             int length = this.textlength;             int selectedchars = this.selectionlength;              if (selectedchars == length)             {                 clearcharbufferplustextbox();                 this.textchanged += new system.eventhandler(this.txtinput_textchanged);                 return;             }              if (selectedchars > 0)             {                 int = selectionstart;                 this.text.remove(selectionstart, selectedchars);                 adminpassword = new string(adminpassword).remove(selectionstart, selectedchars).tochararray();             }             else             {                 /*                  * portion of code handle condition                   * when cursor placed @ start or in end                   */                 if (selectionstart == 0)                 {                     /*                     * cursor in beginning, before first character                      * delete character when del pressed, no action when key pressed                     */                     if (key == keys.delete)                     {                         adminpassword = new string(adminpassword).remove(0, 1).tochararray();                     }                 }                 else if (selectionstart > 0 && selectionstart < length)                 {                     /*                     * cursor position anywhere in between                      * backspace , delete have same effect                     */                     if (key == keys.back || key == keys.delete)                     {                         adminpassword = new string(adminpassword).remove(selectionstart, 1).tochararray();                     }                 }                 else if (selectionstart == length)                 {                     /*                     * cursor @ end, after last character                      * delete character when key pressed, no action when delete key pressed                     */                     if (key == keys.back)                     {                         adminpassword = new string(adminpassword).remove(selectionstart - 1, 1).tochararray();                     }                 }             }         }          private void clearcharbufferplustextbox()         {             array.clear(adminpassword, 0, adminpassword.length);             this.clear();         }     } } 

issue 1. due delay , timer added advance cursor position next highest index, can't seem insert text in between or in beginning.

issue 2. during delete operation. if select index position delete particular char literal, due timer running in background, cursor advances end (because of line this.selectionstart = num;)

can of guide me overcome above mentioned issues ?

cheers vatsag

i solved above issue of simple boolean flags.

using system; using system.collections.generic; using system.globalization; using system.linq; using system.text; using system.windows.forms;  namespace passwordtextbox {      public class passwordtextbox : textbox     {         private readonly timer timer;         private char[] adminpassword = new char[16];         private readonly char decimalseparator = cultureinfo.currentculture.numberformat.numberdecimalseparator.tochararray()[0];         private int m_icaretposition = 0;         private bool canedit = true;          /// <summary>         ///          /// </summary>         public passwordtextbox()         {             timer = new timer { interval = 200 };             timer.tick += timer_tick;         }          /// <summary>         ///          /// </summary>         public string adminpassword         {                         {                 return new string(adminpassword).trim('\0').replace("\0", "");             }         }          /// <summary>         ///          /// </summary>         /// <param name="e"></param>         protected override void ontextchanged(eventargs e)         {             if (canedit)             {                 base.ontextchanged(e);                 txtinput_textchanged(this, e);             }         }          /// <summary>         ///          /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         private void txtinput_textchanged(object sender, eventargs e)         {             hidepasswordcharacters();         }          /// <summary>         ///          /// </summary>         /// <param name="e"></param>         protected override void onmouseclick(mouseeventargs e)         {             base.onmouseclick(e);             m_icaretposition = this.getcharindexfromposition(e.location);         }          /// <summary>         ///          /// </summary>         private void hidepasswordcharacters()         {             int num = this.text.count();              if (num > 1)             {                 stringbuilder s = new stringbuilder(this.text);                 s[num - 2] = '*';                 this.text = s.tostring();                 this.selectionstart = num;                 m_icaretposition = num;                 timer.enabled = true;             }         }          protected override void onkeydown(keyeventargs e)         {             base.onkeydown(e);             if (e.keycode == keys.delete)             {                 canedit = false;                 deleteselectedcharacters(this, e.keycode);             }         }          /// <summary>         /// windows timer elapsed eventhandler          /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         private void timer_tick(object sender, eventargs e)         {             timer.enabled = false;             int num = this.text.count();              if (num > 1)             {                 stringbuilder s = new stringbuilder(this.text);                 s[num - 1] = '*';                 this.invoke(new action(() =>                 {                     this.text = s.tostring();                     this.selectionstart = num;                     m_icaretposition = num;                 }));             }         }          protected override void onkeypress(keypresseventargs e)         {             base.onkeypress(e);              int selectionstart = this.selectionstart;             int length = this.textlength;             int selectedchars = this.selectionlength;             canedit = false;              if (selectedchars == length)             {                 /*                  * means complete text selected clear before using                  */                 clearcharbufferplustextbox();             }              keys emodified = (keys)e.keychar;              if (e.keychar == decimalseparator)             {                 e.handled = true;             }             if ((keys.delete != emodified) && (keys.back != emodified))             {                 if (keys.space != emodified)                 {                     if (e.keychar != '-')                     {                         if (!char.isletterordigit(e.keychar))                         {                             e.handled = true;                         }                         else                         {                             adminpassword = new string(adminpassword).insert(selectionstart, e.keychar.tostring()).tochararray();                         }                     }                 }                 else                 {                     if (this.textlength == 0)                     {                         e.handled = true;                         array.clear(adminpassword, 0, adminpassword.length);                     }                 }             }             else if ((keys.back == emodified) || (keys.delete == emodified))             {                 deleteselectedcharacters(this, emodified);             }              /*              * replace characters '*'              */             hidepasswordcharacters();              canedit = true;         }          /// <summary>         /// deletes specific characters in char array based on key press action         /// </summary>         /// <param name="sender"></param>         private void deleteselectedcharacters(object sender, keys key)         {             int selectionstart = this.selectionstart;             int length = this.textlength;             int selectedchars = this.selectionlength;              if (selectedchars == length)             {                 clearcharbufferplustextbox();                 return;             }              if (selectedchars > 0)             {                 int = selectionstart;                 this.text.remove(selectionstart, selectedchars);                 adminpassword = new string(adminpassword).remove(selectionstart, selectedchars).tochararray();             }             else             {                 /*                  * portion of code handle condition                   * when cursor placed @ start or in end                   */                 if (selectionstart == 0)                 {                     /*                     * cursor in beginning, before first character                      * delete character when del pressed, no action when key pressed                     */                     if (key == keys.delete)                     {                         adminpassword = new string(adminpassword).remove(0, 1).tochararray();                     }                 }                 else if (selectionstart > 0 && selectionstart < length)                 {                     /*                     * cursor position anywhere in between                      * backspace , delete have same effect                     */                     if (key == keys.back || key == keys.delete)                     {                         adminpassword = new string(adminpassword).remove(selectionstart, 1).tochararray();                     }                 }                 else if (selectionstart == length)                 {                     /*                     * cursor @ end, after last character                      * delete character when key pressed, no action when delete key pressed                     */                     if (key == keys.back)                     {                         adminpassword = new string(adminpassword).remove(selectionstart - 1, 1).tochararray();                     }                 }             }              this.select((selectionstart > this.text.length ? this.text.length : selectionstart), 0);          }          private void clearcharbufferplustextbox()         {             array.clear(adminpassword, 0, adminpassword.length);             this.clear();         }     } } 

Comments