System.ArgumentOutOfRangeException in a String - c#

I tried to debug this and i cant figure out whats wrong with it.
Im trying to build a calculator but i keep getting this error.
double currentResult = 0;
int stringLengthStarter = 0;
int stringLengthCounter = 0;
public Form1()
{
InitializeComponent();
}
// Appends the numbers to the text box when the buttons are clicked
private void button1_Click(object sender, EventArgs e) // Click on the digit 1
{
if (clearingTextBoxFlag)
{
textBox1.Clear();
}
stringLengthCounter++;
textBox1.AppendText("1");
clearingTextBoxFlag = false;
}
private void plusButton_Click(object sender, EventArgs e) // Plus button clicked
{
pick = 1; // 1 - Plus operation
currentResult = currentResult + Convert.ToInt32(textBox1.Text.Substring(stringLengthStarter, stringLengthCounter));
stringLengthStarter = stringLengthCounter + 1;
stringLengthCounter = 0;
textBox1.AppendText("+");
}
private void equalsButton_MouseClick(object sender, MouseEventArgs e) // Mouse click on the equals button
{
textBox1.Clear();
if (pick == 1) // Plus operation
{
checkTextBox.Text = textBox1.Text;
currentResult = currentResult + Convert.ToInt32(textBox1.Text.Substring(stringLengthStarter, stringLengthCounter)); // The problem
textBox1.Text = "" + currentResult;
}
I'm trying to do 1+1= and it gets the execption at this line: currentResult = currentResult + Convert.ToInt32(textBox1.Text.Substring(stringLengthStarter, stringLengthCounter)); // The problem

In your equalsButton_MouseClick method, the first thing you do is to clear the textBox1, which will set the textBox1.Text to string.Empty. After that you try to make a substring of textBox1.Text, but the length of the string is 0, which is why your method is crashing. It's trying to access an index of the string that doesn't exist anymore.
Try moving the textBox1.Clear at the end of your method.

Related

Stop and repeat process by using a timer in C# Windows Form

I am trying to use a timer to achieve a sort of old animation used in the past to show that a process is running.
The way I would like to do that is by adding dots to a sentence (in a label control), for example:
"Process is running." to "Process is running.." and "Process is running..." with a limit of 3 dots and then revert back to a single dot.
I am not sure as to the fact using a timer here would be the best choice, but I thought it should work fine for such a simple example.
The code I used is as follows:
public string InitialProcessText;
private void StartBtn_Click(object sender, EventArgs e)
{
if(fileName != "No file selected")
{
ValidationLbl.Text = null;
ProcessLbl.Text = "Application is now running.";
//InitialProcessText = ProcessLbl.Text;
ProcessTimer.Start();
}
else
{
ValidationLbl.Text = "No file was added";
}
}
private void StopBtn_Click(object sender, EventArgs e)
{
ProcessTimer.Stop();
}
private void ProcessTimer_Tick(object sender, EventArgs e)
{
_ticks++;
//For every two ticks, ProcessLbl.Text = InitialProcessText
ProcessLbl.Text += ".";
}
What could I add to set a limit of adding 2 dots and then remove the dots and add dots again (I would assume to do this in the ProcessTimer_Tick method)?
You can just use your _ticks variable:
private readonly int _ticksPerUpdate = 2;
private readonly int _maxNumberOfDots = 3;
private void ProcessTimer_Tick(object sender, EventArgs e)
{
_ticks++;
if(_ticks == (_ticksPerUpdate * (_maxNumberOfDots + 1)))
{
_ticks = 0;
ProcessLbl.Text = InitialProcessText;
}
else if(_ticks % _ticksPerUpdate == 0)
{
ProcessLbl.Text += ".";
}
}
Remember to reset the ticks counter every time you start the timer:
private void StartBtn_Click(object sender, EventArgs e)
{
if(fileName != "No file selected")
{
ValidationLbl.Text = null;
ProcessLbl.Text = "Application is now running.";
InitialProcessText = ProcessLbl.Text;
// reset the variable
_ticks = 0
ProcessTimer.Start();
}
else
{
ValidationLbl.Text = "No file was added";
}
}
I assume that _ticks counts the number of ticks. You could then go :
if(ticks%3 == 0)
{
ProcessLbl.Text = "Application is now running."
}
else
{
ProcessLbl.Text+=".";
}
Then, at 1st tick, 1%3=1 so it adds a dot, at 2nd tick, 2%3=2 so it adds a dot and 3rd tick, 3%3=0, so it gets back to original.
Just because...here's another approach:
private void ProcessTimer_Tick(object sender, EventArgs e)
{
ProcessLbl.Text = ProcessLbl.Text.EndsWith("...") ? ProcessLbl.Text.TrimEnd(".".ToCharArray()) + "." : ProcessLbl.Text + ".";
}

How to retrieve current value that has assigned after button click in C# windows forms

In ASP.NET I could use sessions for it but for windows form how can I get current value to which I can add + 1?
After btnPrintToken click it would override, re-run the code, I want it to keep the last entered value(LastTokenNumberIssued) and for it to add + 1 and so on so it will update the queue.
private void btnPrintToken_Click(object sender, EventArgs e)
{
Queue<int> queueTokens = new Queue<int>();
lblStatus.Text = "There are " + queueTokens.Count.ToString() +
" customers before you in the queue";
int LastTokenNumberIssued = // Not sure how to retrieve current value what it was after nextTokenNumberTobeIssued.
int nextTokenNumberTobeIssued = LastTokenNumberIssued + 1;
LastTokenNumberIssued = nextTokenNumberTobeIssued;
queueTokens.Enqueue(nextTokenNumberTobeIssued);
AddTokensToListBox(queueTokens);
}
private void AddTokensToListBox(Queue<int> queueTokens)
{
listTokens.Items.Clear();
foreach (int token in queueTokens)
{
listTokens.Items.Add(token.ToString());
}
}
Create your LastTokenNumberIssued outside the method:
public YourWindow
{
int LastTokenNumberIssued;
private void btnPrintToken_Click(object sender, EventArgs e)
{
int nextTokenNumberIssued;
LastTokenNumberIssued = LastTokenNumberIssued++;
nextTokenNumberTobeIssued = LastTokenNumberIssued;
}
}
If you create LastTokenNumberIssued inside the method, it will get overridden everytime you click the button because its value is lost when the method returns.
Check this for more info on method scope.
One way to do this, is by defining these variables nextTokenNumberTobeIssued, LastTokenNumberIssued before the btnPrintToken_Click method, something like this:
int LastTokenNumberIssued = 0; //give it a default value here.
int nextTokenNumberTobeIssued = 0; //give it a default value here.
private void btnPrintToken_Click(object sender, EventArgs e)
{
....
nextTokenNumberTobeIssued = LastTokenNumberIssued + 1;
LastTokenNumberIssued = nextTokenNumberTobeIssued;
...
}
This way each time the user click the button PrintToken, you will have the LastTokenNumberIssued holds the previous click.
int LastTokenNumberIssued = 0; //here will be the start value
private void btnPrintToken_Click(object sender, EventArgs e)
{
Queue<int> queueTokens = new Queue<int>();
lblStatus.Text = "There are " + queueTokens.Count.ToString() +
" customers before you in the queue";
int nextTokenNumberTobeIssued = LastTokenNumberIssued + 1;
LastTokenNumberIssued = nextTokenNumberTobeIssued;
queueTokens.Enqueue(nextTokenNumberTobeIssued);
AddTokensToListBox(queueTokens);
}
private void AddTokensToListBox(Queue<int> queueTokens)
{
listTokens.Items.Clear();
foreach (int token in queueTokens)
{
listTokens.Items.Add(token.ToString());
}
}

increment how many times an image is displayed in a picturebox

I'm trying to display an image using a button click and increment a variable when a certain image is shown, but with the code below the variable num is always 0.
my code
int num = 0;
int i = 0;
int x = 0;
PictureBox[] pictureBoxs = new PictureBox[4];
Random rnd = new Random();
public UserControl1()
{
InitializeComponent();
pictureBoxs[0] = pbimg1;
pictureBoxs[1] = pbimg2;
pictureBoxs[2] = pbimg3;
pictureBoxs[3] = pbimg4;
x = rnd.Next(2);
}
public void displaypics()
{
pictureBoxs[i].Image = imageList1.Images[x];
}
private void btn2_Click(object sender, EventArgs e)
{
i=1;
displaypics();
if (pictureBoxs[i].Image == imageList1.Images[1])
{
num++;
}
if (num == 2)
{
tb1.Visible = true;
tb1.Text = "GAME OVER!" + num;
}
}
The reason is most likely that num is being instantiated to zero everytime the class is being instantiated
What happens when you set breakpoints and step through the code? Is the int set as 0, or does it contain the updated value?
I'm not sure what the context is in which that piece of code is used. So I guess what should solve this would be adding x = rnd.Next(2) to the btn2_Click method. Making it look like this:
private void btn2_Click(object sender, EventArgs e)
{
x = rnd.Next(2);
displaypics();
if (pictureBoxs[i].Image == imageList1.Images[1])
{
num++;
}
if (num == 2)
{
tb1.Visible = true;
tb1.Text = "GAME OVER!" + num;
}
i++;
}
Maybe you could give some more details on what that control should do/how it's used.

Select a particular line in textbox?

I have a two forms, 1 and 2. Form1 has one textbox and form2 has a textbox and button. I want to go to a specified line, meaning that when I enter the value of form2's textbox then my mouse cursor goes to form1's textbox.
private void button1_Click(object sender, EventArgs e)
{
int line = Form1.ab;
for (int i = 1; i < line; i++)
{
if (i == Convert.ToInt16( textBox1.Text))
{
// fr.textbox1 is a textbox form1 and
// textbox1.text is a textbox of the form1
fr.textBox1.SelectionStart =
int.Parse( textBox1.Text) ;
fr.textBox1.ScrollToCaret();
break;
}
}
}
The TextBox.GetFirstCharIndexFromLine method finds the index of the first character of a line.
So your selection starts there. Then find the end of that line, which is Environment.NewLine or the end of the text.
Since the line number is entered by the user you should use int.TryParse to handle invalid input.
private void button1_Click(object sender, EventArgs e)
{
int lineNumber;
if (!int.TryParse(textBox2.Text, out lineNumber) || lineNumber < 0)
{
textBox1.Select(0, 0);
return;
}
int position = textBox1.GetFirstCharIndexFromLine(lineNumber);
if (position < 0)
{
// lineNumber is too big
textBox1.Select(textBox1.Text.Length, 0);
}
else
{
int lineEnd = textBox1.Text.IndexOf(Environment.NewLine, position);
if (lineEnd < 0)
{
lineEnd = textBox1.Text.Length;
}
textBox1.Select(position, lineEnd - position);
}
}
Apply this logic to your code, and recode it as you need.
private void button1_Click(object sender, EventArgs e)
{
if (textBox_Form1.Text.Contains(textBox_Form2.Text))
{
textBox_Form1.Focus();
textBox_Form1.SelectionStart = textBox_Form1.Text.IndexOf(textBox_Form2.Text);
textBox_Form1.SelectionLength = textBox_Form2.Text.Length;
}
}
try something like;
int lineNumber = Form1.ab;
// split the contents of the text box
string text = textBox1.Text;
string[] lines = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
if (lineNumber < 0 || lineNumber > lines.Length)
{
MessageBox.Show("The line number is does not exist");
return;
}
// get the character pos
int selStart = 0;
for (int i = 0; i < (lineNumber - 1); i++)
{
selStart += lines[i].Length + Environment.NewLine.Length;
}
textBox1.Focus();
textBox1.SelectionStart = selStart;
textBox1.SelectionLength = lines[lineNumber - 1].Length;
Note: you can access the other text box directly in the other form by going to the Form2 designer, clicking the text box and going to Properties. In the Properties dialog, look for a property called Modifiers and change the value to internal or public. This will allow you to access the text box value in the other form directly like so;
private void Form1_Load(object sender, EventArgs e)
{
Form2 form2Instance = new Form2();
string sampleText = form2Instance.textBox1.Text;
}
If you need to know further samples on how to access controls/details on other forms, let me know.
You are creating a NEW form1 where the textbox is likely to be blank, and calling GetPass() on that empty form. You need an instance of the already-opened form1 where the textbox might have a value. for more information
click here
Try the below code
var sdr = (System.Windows.Controls.TextBox) sender;
if (!string.IsNullOrEmpty(sdr.Text)) {
var start = sdr.Text.LastIndexOf(Environment.NewLine, sdr.CaretIndex);
var lineIdx = sdr.GetLineIndexFromCharacterIndex(sdr.CaretIndex);
var lineLength = sdr.GetLineLength(lineIdx);
sdr.SelectionStart = start + 1;
sdr.SelectionLength = lineLength;
sdr.SelectedText.Substring(0, sdr.SelectedText.IndexOf(Environment.NewLine) + 1);
Clipboard.SetText(sdr.SelectedText);
}
maybe this better:
{
...
string SelectedText = fr.textBox1.Lines[line];
int SelectedTextPos = fr.textBox1.Text.IndexOf(SelectedText);
int SelectedTextLen = SelectedText.Lenght;
fr.textBox1.Select(SelectedTextPos, SelectedTextLen);
fr.textBox1.ScrollToCaret();
...
}

Button Click Frequency Array

I need to make a ListBox that displays how often a Button is clicked.
The user chooses how many buttons are available to click. Here is what I've tried:
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
for (int i = 0; i < freq_array[clicked]; i++)
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
freq_array uses the 'clicked' variable to add to the frequency that button has been clicked. Or, it's supposed to.
When I debug it, 'clicked' always comes out to 0. I want 'clicked' to equal the text value of the button that's clicked. When I try to run the program, I get an error saying "Input string was not in correct format."
Edit:
I was able to fix my program with help from you guys. I realized I didn't show enough of my code to be clear enough, and I apologize for that. I had to add some things and move things around and got it soon enough. Thank you all.
Here is the code just for those who may need help in the future:
public partial class Form1 : Form
{
int[] freq_array = new int[11];
int[] numList = new int[11];
int oBase = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
invisiblity();
}
private void invisiblity()
{
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
ctrl.Visible = false;
}
}
private void btnSetBase_Click(object sender, EventArgs e)
{
Form2 frmDialog = new Form2();
frmDialog.ShowDialog(this);
if (frmDialog.DialogResult == DialogResult.OK)
{
oBase = frmDialog.Base;
//lblOutDigits.Text = oBase.ToString();
for (int i = 0; i < oBase; i++)
{
numList[i] = i;
}
}
ShowBaseButtons(oBase);
}
private void ShowBaseButtons(int last_digit)
{
invisiblity();
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
if (int.Parse(ctrl.Text) <= last_digit - 1)
ctrl.Visible = true;
}
}
private void btnN_Click(object sender, EventArgs e)
{
lblOutDigits.Text += ((Button)(sender)).Text;
int clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
}
private void btnShowFreq_Click(object sender, EventArgs e)
{
lstFrequencies.Items.Clear();
for (int i = 0; i < oBase; i++)
lstFrequencies.Items.Add(numList[i] + " \t\t\t" + freq_array[i]);
}
Your code should work as long as your Button Text is actually just a number. Since what you are trying to do is create an index, what I usually do is use the Tag Property of the control, set it to the Index I want in the designer and then cast that to an Int.
i.e.
if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
freq_array[clicked]++;
I believe what is happening is that you are not initializing your ListBox, This example Code does work using your initial method. Just create a new Form and paste it in and test.
public partial class Form1 : Form
{
ListBox lstFrequencies = new ListBox();
int[] freq_array = new int[10];
public Form1()
{
InitializeComponent();
Size = new Size(400, 400);
lstFrequencies.Location = new Point(150, 0);
lstFrequencies.Size = new Size(150, 200);
Controls.Add(lstFrequencies);
int top = 0;
for (int i = 0; i < 10; i++)
{
Button btn = new Button();
btn.Size = new Size(70, 30);
btn.Location = new Point(5, top);
Controls.Add(btn);
top += 35;
btn.Tag = i;
btn.Text = i.ToString();
btn.Click += new EventHandler(btn_Click);
lstFrequencies.Items.Add(i.ToString());
}
}
void btn_Click(object sender, EventArgs e)
{
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked]; //Cleaned up you do not need to iterate your list
// Using my example code
//if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
//{
// freq_array[clicked]++;
// lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
//}
}
}
Your code always comes out to 0 because you never assign last clicked value to button text. Try this code:
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
clicked = Convert.ToInt32(((Button)sender).Text);
lstFrequencies.Items.Add(((Button)sender).Name + " " + ++clicked);
button1.Text = clicked.ToString(); // you lose this line
}
EDIT: Counter from variable member
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
// if you want to display button name, change .Text to .Name
lstFrequencies.Items.Add(((Button)sender).Text + " " + ++clicked);
}

Categories