M Tayyab Asghar
M Tayyab Asghar

Reputation: 322

TextBox.Enter() Event fires Textbox.Leave() Event with it in WinForm

I'm making Signup form using WinForms of C#. I have made 2 private functions to call for Enter() and Leave() Events in different TexBox.Enter() and TexBox.Leave() Events.

private void EnterBox(TextBox Box, string Text, PictureBox PicBox, Bitmap Pic, Label WarningLabel)
{
    if ((Box.Text == Text) && (Box.TextAlign == HorizontalAlignment.Center))
    {
        Box.Clear();

        if (Box == PassBox)
            Box.UseSystemPasswordChar = true;
        Box.TextAlign = HorizontalAlignment.Left;
    }
    PicBox.BackgroundImage = Pic;
    WarningLabel.ForeColor = Color.FromArgb(34, 36, 49);
    Box.ForeColor = Color.FromArgb(78, 184, 206);
}

private void LeaveBox(TextBox Box, string Text, PictureBox PicBox, Bitmap Pic, Label WarningLabel)
{
    if (Box.Text == "")
    {
        if (Box == PassBox)
            Box.UseSystemPasswordChar = false;

        WarningLabel.ForeColor = Color.Red;
        Box.Text = Text;
        Box.TextAlign = HorizontalAlignment.Center;
        Box.ForeColor = Color.Gray;
    }
    else
    {
        if (!Regex.IsMatch(Box.Text, (string)Box.Tag))
            WarningLabel.ForeColor = Color.Red;
        Box.ForeColor = Color.White;
    }
    PicBox.BackgroundImage = Pic;
    Box.Select(0, 0);                     // Move the Cursor to Start.
}

It seems to work fine with other TextBoxes but it does not work fine with PassBox.

private void PassBox_Enter(object sender, EventArgs e)
{
    EnterBox(PassBox, "Password", PasswordPic, Properties.Resources.password__2_, PasswordWarningLabel);
}

private void PassBox_Leave(object sender, EventArgs e)
{
    LeaveBox(PassBox, "Password", PasswordPic, Properties.Resources.password, PasswordWarningLabel);
}

Debuging it with VS-Studio-2019 shows When I enter the EnterBox() of PassBox_Enter() after Compeleting the

if ((Box.Text == Text) && (Box.TextAlign == HorizontalAlignment.Center))
    {
        Box.Clear();

        if (Box == PassBox)
            Box.UseSystemPasswordChar = true;
        Box.TextAlign = HorizontalAlignment.Left;
    }

it enters the PassBox_Leave() and execute it then again it enters the PassBox_Enter() and execute the function again.

I was working fine but all of sudden it started to do so. I tried to delete the previous TexBox and again generating another box but it stared to do so again.

Upvotes: 0

Views: 1603

Answers (2)

M Tayyab Asghar
M Tayyab Asghar

Reputation: 322

As @Hans Passant and @MarkusAnd said changing the UseSystemPasswordChar triggers the PassBox_Leave() event each time. I removed the if (Box == PassBox) Box.UseSystemPasswordChar = true; and if (Box == PassBox) Box.UseSystemPasswordChar = false; from LeaveBox() and EnterBox() and updated PassBox_Enter() and PassBox_Leave() as follow

private void PassBox_Enter(object sender, EventArgs e)
{
 if (PassBox.TextAlign == HorizontalAlignment.Center)
    PassBox.UseSystemPasswordChar = true;
 EnterBox(PassBox, "Password", PasswordPic, Properties.Resources.password__2_, PasswordWarningLabel);
}

and

private void PassBox_Leave(object sender, EventArgs e)
{
 if (PassBox.Text == "")
     PassBox.UseSystemPasswordChar = false;
 LeaveBox(PassBox, "Password", PasswordPic, Properties.Resources.password, PasswordWarningLabel);
}

It will still trigger the PassBox_Leave() but it will work.

Upvotes: 1

MarkusAnd
MarkusAnd

Reputation: 812

I think the problem is in the line

if (Box == PassBox)
            Box.UseSystemPasswordChar = true;

in the EnterBox method. When you call Box.UseSystemPasswordChar = true; you set the TextBox to restricted mode (as you can read under important here). When the TextBox is put in restricted mode it loses the focus and the PassBox_Leave event will be thrown. This is the reason why the debug behaves as you described.

If you want to make sure that the PassBox_Entered event is completed before any call to PassBox_Leave is made you have to make sure that no line of code in EnterBox is switching the focus from the TextBox. This is currently made by the line Box.UseSystemPasswordChar = true; in EnterBox.

However they are ways to circumvent this problem by for example boolean flags. This solution may not be optimal but should work.

Since PassBox_Leave may be called by either Box.UseSystemPasswordChar = true; (where you do not want anything in LeaveBox to be executed) or when the user leaves the TextBox (where you want LeaveBox to execute) you can use a boolean flag in your class and set it to true before the line Box.UseSystemPasswordChar = true; in EnterBox is executed. Then in the first rows of LeaveBox you check if the boolean flag is true and if it is you return, hence nothing in LeaveBox will be executed (however PassBox_Leave will still be called, therefore this might not be an optimal solution).

Public Class YourClass {
    private bool falseCall; //Add this boolean flag as an attribute to your class

    public YourClass() {
       falseCall = false; //Set the inital value to false in the constructor of your class;
    }

    private void EnterBox(TextBox Box, string Text, PictureBox PicBox, Bitmap Pic, Label WarningLabel)
    {

       if ((Box.Text == Text) && (Box.TextAlign == HorizontalAlignment.Center))
       {
           Box.Clear();

           if (Box == PassBox) {
              falseCall = true; //Set the flag to true before the call to LeaveBox is executed
              Box.UseSystemPasswordChar = true;
           }
           Box.TextAlign = HorizontalAlignment.Left;
       }
    //-------Rest of method-----------
    }


    private void LeaveBox(TextBox Box, string Text, PictureBox PicBox, Bitmap Pic, Label WarningLabel)
    {
        if(falseCall) { 
            falseCall = false; //Reset the boolean flag 
            return; 
        }
        //--------Rest of method-----------
    }
}

So basically the program will still enter LeaveBox when Box.UseSystemPasswordChar = true; is executed but it will quickly return since the flag was set to true. When the user leaves the TextBox the flag will be false and LeaveBox will be executed as intended.

Upvotes: 1

Related Questions