Create a textbox with "smart" password char - c#

I'm using .NET 3.5 CF and trying to create a textbox which should hide the character written inside it. This works by setting the parameter PasswordChar to = "*". However this change the char to a * directly.
What I want is a "smart" textbox who change the character to a * after a delay (approximate 1 second) which will make the user to get some feedback that correct character was written.
I tried this by creating another thread that should handle this since the user should still be able to write more characters and not wait this delay. I did something like this:
if (UseModernPasswordScreenMaskning)
{
this.Invoke(new UpdateTextCallback(this.UpdateText), new object[]{"*"});
}
private void UpdateText(string text)
{
int k = this.Text.Length;
System.Threading.Thread.Sleep(1000);
this.Text = this.Text.Remove(k - 1, 1);
this.Text = this.Text.Insert(k - 1, "*");
}
It works but the sleep is on my current thread which make next letter written delay by 1 second before it shows up. I want each letter to show directly and change to a *, 1 second after that particular char was written.

As i understand, a "smart" password textbox is
the last character will become * within 1s
if user type a new character, the older one will become * (although it doesn't last 1s)
So
Create a timer callback with 1s interval to change last character to *
In smartTextBox_TextChanged event, change the previous character to *
Here is my code
public void Do(object state)
{
int num = this.textBox1.Text.Count();
if (num > 0)
{
StringBuilder s = new StringBuilder(this.textBox1.Text);
s[num - 1] = '*';
this.Invoke(new Action(() =>
{
this.textBox1.Text = s.ToString();
this.textBox1.SelectionStart = this.textBox1.Text.Count();
timer.Dispose();
timer = null;
}));
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (timer == null)
{
timer = new System.Threading.Timer(timerCallback, null, 1000, 1000);
}
int num = this.textBox1.Text.Count();
if (num > 1)
{
StringBuilder s = new StringBuilder(this.textBox1.Text);
s[num - 2] = '*';
this.textBox1.Text = s.ToString();
this.textBox1.SelectionStart = num;
}
}
In initialize
timerCallback = new TimerCallback(Do);

I managed to solve it by adding since the line "int num = this.textBox1.Text.Count();" could not be used before that statement:
public void Do(object state)
{
if (this.logonPwTxtBox.InvokeRequired)
{ .. }
}

Related

Method to draw a line

My Professor gave us this question
Write a method called Drawline that accepts as input an integer n and generates a line of output in lstOutput with n hyphens. That is, if n = 5 we have a line of ‘-----‘ displayed in the list box.
Basically he wants me to type a number in a text box and when i click the button it should display that many hyphens in a list box. Using visual Studio C# WindowsFormApp.
Here's my code:
private void btn3_Click(object sender, EventArgs e)
{
double n;
Drawline(out n);
}
private void Drawline(out double n)
{
n = double.Parse(textBox1.Text);
string strline = "";
for (n = 1; n <= 5; n++);
strline += '-';
lstOutput.Items.Add(String.Format(strline, n));
}
It works but no matter what number i put in the text box only one hyphen shows up. Can anyone help me?
The problem is with your for loop in DrawLine method.
You need to remove the semi-colon at the end of the for statement, so the strLine += '-'; will belong to the loop, not just be executed once.
private void Drawline(out double n)
{
n = double.Parse(textBox1.Text);
string strline = "";
for (i = 1; i <= 5; i++)
strline += '-';
lstOutput.Items.Add(String.Format(strline, n));
}
It appears you may be making this more complicated than it has to be.
It is unclear “why” the DrawLine method returns a double value using the out property? Is this a requirement? If it is not a requirement, then it is unnecessary.
Also, as per the requirement… ”Write a method called Drawline that accepts as input an integer n” … if this is the requirement, I have to ask why is the method accepting a double value? This would not fit with the requirement.
Below is a simplified version and should fit your requirements. First in the button click event, we want to get the integer value from the text box. We need to assume the user typed in a value that is NOT a valid integer. If the value is NOT a valid integer greater than zero (0), then we will display a message box indicating such.
private void button1_Click(object sender, EventArgs e) {
if ((int.TryParse(textBox1.Text, out int value)) && value > 0) {
Drawline(value);
}
else {
MessageBox.Show("String is not a number or is less than 1 : " + textBox1.Text);
}
}
Next the DrawLine method that simply adds a string of “-“ character(s) to the list box. Note the passed-in/accepted value of n has already been verified as a valid integer number greater than 0.
private void Drawline(int n) {
lstOutput.Items.Add(new string('-', n));
}
If you MUST use a for loop to generate the string, it may look something like…
private void Drawline(int n) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.Append("-");
}
lstOutput.Items.Add(sb.ToString());
}

How can move n characters from front of the string to the end continuously every time I press the button?

I'm trying to move the first char of the string to the end every time I press the button.
My logic seems to only display the first output again and again after I press the button.
string input = "";
string manipulated = "";
int initial;
input = txtInput.Text;
if (txtInput.Text == String.Empty)
{
MessageBox.Show("Textbox is empty, please input a string.");
}
else
{
for (initial = 1; initial < input.Length; initial++)
{
manipulated += input[initial];
}
manipulated += input[0];
lblOutput.Text = manipulated.ToString();
input = manipulated;
manipulated = "";
}
E.g. if I enter "1234" in the text box and press the button, my output should be "2341", then after I hit the button again, the output should move to "3412" .. etc.
This is a simple example of Basics String operations:
private void ManipulateBtn_Click(object sender, EventArgs e)
{
string input = InputTxt.Text; // Read the text from you Textbox in Windos form
if (input == string.Empty)
{
return;
}
string temp = input[0].ToString(); // Create a temp for the first char(toString) from you input
input = input.Remove(0,1); // Remove (from you input) At Index 0 (the idex from fist char in string) 1 time)
input += temp; //add the firs item from you input at the end of string
InputTxt.Text = input; // prin the result in the Textbox back.
}
You can see the example SimpleStringOperation
You can Improve your code by another solution using Substring Method
Create a new variable called _number and set the value to 1
public partial class Form1: Form
{
private int _number = 1;
// ....
}
Then in Button event, you can replace your code with this code
private void BtnMoveText_Click(object sender, EventArgs e)
{
if (txtInput.Text == string.Empty)
{
MessageBox.Show(#"TextBox is empty, please input a string.");
return;
}
if (_number > txtInput.TextLength)
_number = 1;
lblOutput.Text = txtInput.Text.Substring(_number) + txtInput.Text.Substring(0, _number);
_number++;
#region ** Depending on Microsoft **
/*
Substring(Int32)
(Retrieves a substring from this instance. The substring starts at a specified character position and continues to the end of the string.)
Parameters
startIndex Int32
The zero-based starting character position of a substring in this instance.
.......................
Substring(Int32, Int32)
(Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length..)
Parameters
startIndex Int32
The zero-based starting character position of a substring in this instance.
length Int32
The number of characters in the substring.
*/
#endregion
}
You're taking your OUTPUT and placing it in a Label...but continuing to take your INPUT from the TextBox which hasn't changed...thus the same result each time.
Simply change:
lblOutput.Text = manipulated.ToString();
To:
txtInput.Text = manipulated;

Threaded Code Is Causing the UI To Hang

I wrote a simple class to generate arrays as I needed some hard-coded random arrays for my own debugging purposes, however despite calling the timely operations in a separate worker thread my UI still hangs! Here's the code...
private static Random randGenerator = new Random();
private void generateButton_Click(object sender, EventArgs e)
{
string dataType = "System.";
if (typeComboBox.Text != "Byte")
dataType += signedCheckBox.Checked ? "" : "U";
else if (typeComboBox.Text == "Byte")
dataType += signedCheckBox.Checked ? "S" : "";
dataType += typeComboBox.Text;
generateButton.Enabled = false;
new Thread(() =>
{
Process(Type.GetType(dataType), (int)sizeNumericUpDown.Value, hexCheckBox.Checked);
}).Start();
}
private void Process(Type type, int size, bool hex)
{
StringBuilder sBuilder = new StringBuilder();
sBuilder.Append(string.Format(#"{0}[] values = new {0}[{1}] {{", type.Name, size));
for (int i = 0; i < size; i++)
{
int random = randGenerator.Next(0, GetIntegralMaxValue(type));
sBuilder.Append((hex ? "0x" + random.ToString("x2") : random.ToString()) + (i < size - 1 ? ", " : " };"));
}
outputTextBox.BeginInvoke((MethodInvoker)delegate
{
outputTextBox.Text = sBuilder.ToString();
});
}
private int GetIntegralMaxValue(Type type)
{
var field = type.GetField("MaxValue").GetValue(null);
return Convert.ToInt32(field);
}
I thought that maybe the issue lied with trying to access objects created on the main thread so instead I passed them to the method. I also tried declaring my randGenerator object within the class but still no luck. Could anybody identify the issue?
The TextBox is not designed to hold a large set of data - it becomes very slow when amount of data increases. I would say that populating of the StringBuilder takes about 5% of time while assigning this data to TextBox (which executes in UI thread) takes remaining 95% of time. You can easily check this. Just run this code in debug mode and click "Pause" button during hanging. It should break on "outputTextBox.Text = sBuilder.ToString();" line.

Getting integer from textbox

I want to write the event handler method button1_Click to calculate whether student’s Grade is “PASS” or “FAIL”. The student passes the course if the total score is greater than or equal to 50. The total score is Midterm(textbox1) + Final(textbox2) scores. However, teacher can give student Extra Credit(checkbox1) which is worth 10 points. The result will present in the textBox3
Here's my code:
private void button1_Click(object sender, EventArgs e)
{
int midtermInt = int.Parse(textBox1.Text);
int finalInt = int.Parse(textBox2.Text);
if (checkBox1.Checked)
{
if ((midtermInt + finalInt) + 10 >= 50)
{
grade.Text = "PASS";
}
else if ((midtermInt + finalInt) + 10 < 50)
{
grade.Text = "FAIL";
}
}
else if (!checkBox1.Checked)
{
if ((midtermInt + finalInt) >= 50)
{
grade.Text = "PASS";
}
else if ((midtermInt + finalInt) < 50)
{
grade.Text = "FAIL";
}
}
When I run it, it says "Inut string was not in a correct format.. :(
I'm very new to C# please advise me if my code is wrong anywhere
The input will only be integers never texts..
You should use int.TryParse insted int.Parse, it's check is specified string is in correct format.
You code may looks like this:
int midtermInt;
if (!int.TryParse(textBox1.Text, out midtermInt))
{
labelError.Text = "Icorrect value in field 'textBox1'".
return;
}
If you type non-numeric characters in your textbox and try to parse the text, it will throw you this exception. Try trimming the input and definitely consider adding UI validation to your forms.
You can add checking, if text in text box is in correct format in TextChanged event:
private void textBox_TextChanged(object sender, EventArgs e)
{
int val;
if (textBox.Text.Length == 0 || !int.TryParse(textBox.Text, out val))
tsPassingScore.Text = "0";
}
And in your click you can check if there is number in textBox again with int.TryParse
Also you can improve your code:
If final summ is not bigger then 50 - it is automatically smaller! And it would be more readable, if you introduce extra variable - for teachers extra credit:
int extraCredit = checkBox1.Checked ? 10 : 0;
int finalScore = midtermInt + finalInt + extraCredit;
if (finalScore >= 50)
grade.Text = "PASS";
else
grade.Text = "FAIL";

how to type to a label?

I am trying to have a multi line textbox that when you type in it streams it to the label, BUT the label has to have a max length of 15 so like once it reaches 15 characters in the textbox it should start overwriting the label since it reached it's max length
thanks to anyone who can help
Add onchange event on text box :
if (textBox1.Text.Length<=15)
{
label1.Caption=textBox1.Text;
}
For example
I'm not sure what kind of overwriting You want to achieve.
There are at least three methods you can use:
displaying always the last 15 characters from the textbox, as described in the Olivier's answer
clearing the label's text each 15 characters inserted and start filling in the label over again, you can use this code to achieve this:
private void textBox1_TextChanged(object sender, EventArgs e)
{
String text = textBox1.Text.Replace("\r\n", "|");
int startIndex = ((text.Length - 1) / 15) * 15;
label1.Text = text.Substring(Math.Max(0, startIndex));
}
you can also overwrite char by char when text length is over 15 characters, however, I suppose it's not what you would like to achieve, because it would cause a mess in the textbox ;), however, it can be used as a kind of visual effect :). If you want code snippet for this, let me know :).
Update
Here's the code for the third overwriting method:
String lastText = "";
private void textBox1_TextChanged(object sender, EventArgs e)
{
String textBoxText = textBox1.Text.Replace("\r\n", "|");
if (textBoxText.Length > lastText.Length)
{
int charIndex = (textBoxText.Length - 1) % 15;
if (charIndex >= 0)
{
label1.Text = label1.Text.Insert(charIndex, textBoxText.Substring(textBoxText.Length - 1));
if (charIndex < textBoxText.Length - 1)
{
label1.Text = label1.Text.Remove(charIndex + 1, 1);
}
}
}
else
{
int charIndex = textBoxText.Length % 15;
if (textBoxText.Length >= 15)
{
label1.Text = label1.Text.Insert(charIndex, textBoxText[textBoxText.Length - 15].ToString());
if (charIndex < textBoxText.Length - 1)
{
label1.Text = label1.Text.Remove(charIndex + 1, 1);
}
}
else
{
label1.Text = label1.Text.Remove(label1.Text.Length - 1, 1);
}
}
lastText = textBoxText;
}
Add a handler to the TextChanged event of the TextBox that sets the Label's content based on the text. E.g. (untested, might have your concept wrong or be off by one somewhere)
int startIndex = Math.Max(0, myTextBox.Text.Length - 15);
int endIndex = Math.Min(myTextBox.Text.Length - 1, startIndex);
myLabel.Text = myTextBox.Text.Substring(startIndex, endIndex - startIndex);
Also, though it doesn't change your question/answer, you might want to look at using a TextBlock instead of a Label. It allows things like line wrapping. See some of the differences here: http://joshsmithonwpf.wordpress.com/2007/07/04/differences-between-label-and-textblock/ (in WPF, should be similar whatever you're doing, though)
My solution always displays the last 15 characters in the label
private void textBox1_TextChanged(object sender, EventArgs e)
{
string s = textBox1.Text.Replace("\r\n", "|");
int length = s.Length;
if (length > 15) {
label1.Text = s.Substring(length - 15);
} else {
label1.Text = s;
}
}
I also replace the line-breaks with |. Since your textbox is in multiline mode, line-breaks are entered when you hit <Enter>.

Categories