Reputation: 322
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
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
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