How do I capture the "Enter" key in a windows form? - c#

I am trying to get the text of a textbox and save it to a variable when the user presses the enter key (when the textbox has info and is focused) since this is already inside a method i haven't been able to put another method inside like txtbox1_keypress (or i've been doing it wrong) so I need to be just code lines that i can insert in this method
private void df1_Click(object sender, EventArgs e)
{
txtres.Focus();
//timer
timeLeft = 50;
timer1.Start();
//mult
do
{
ban = 0;
m1 = r.Next(1, 4);
txtm1.Text = m1.ToString();
m2 = r.Next(2, 6);
txtm2.Text = m2.ToString();
res = m1 * m2;
//here is where i want to read txtm2 and continue with the rest
if(txtres.Text == res.ToString())
{
pun++;
}
ban++;
} while (timeLeft > 0 || ban != 10);
if(pun == 10 && level == 0)
{
level++;
System.IO.File.WriteAllText(#".\level.lvl", level.ToString());
}
}

Since you mentioned you want to run it inside KeyPress event, here is the example:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (int) Keys.Enter)
{
//do the logic
}
}

Add a button as the accept button of the form, this will trigger whenever enter is pressed.
Also, your loop (do -- while) should be done within the timer1_tick method, and take out the loop, the timer will execute the code within every interval it ticks until the timer reaches your maximum of 50.
As was mentioned, the loop will kill your GUI and it wont allow input.

Related

c# lock a windows forms control

I'm programming a winforms app, and I have encountered a problem:
I have, for example, a numeric UpDown control, and when pressing the up/down button, I don't want it to change, but I want access to the new value, without changing the number on the control itself.
I need as well to be able to unlock it under some condition, so it would look like that:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
if (!canChange)
{
int newValue = get_expected_new_value();
doSomeStuff(newValue);
//some_code_to_cancel_the_value_change;
}
else
{
//allow the change
doSomeOtherStuff();
}
}
How can I do thins thing?
You can use the Tag property of the numericUpDown1 to store the last value.
Although it's not a particulary elegant solution.
Credit to: C# NumericUpDown.OnValueChanged, how it was changed?
In your case it can look something like this:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
var o = (NumericUpDown) sender;
int thisValue = (int) o.Value;
int lastValue = (o.Tag == null) ? 0 : (int)o.Tag;
o.Tag = thisValue;
if (checkBox1.Checked) //some custom logic probably
{
//remove this event handler so it's not fired when you change the value in the code.
o.ValueChanged -= numericUpDown1_ValueChanged;
o.Value = lastValue;
o.Tag = lastValue;
//now add it back
o.ValueChanged += numericUpDown1_ValueChanged;
}
//otherwise allow as normal
}
Basicaly you store the last known good value in the Tag property.
Then you check you condition and set the value back to the last good value.

Add character every 2 characters entered to textbox Windows Phone 8

Hi i want to make textbox to enter mac adress and every 2 characters i want to automaticly add ':'
I wanted to use TextChanged event
private void MacAdressTextBox_TextChanged(object sender, TextChangedEventArgs e) {
if (MacAdressTextBox.Text.Length > 2)
MacAdressTextBox.Text += ":";
}
here i am adding : after 2 characterrs entered but after those 2 characters the app frezes ... have no idea why any help?
When the text changes MacAdressTextBox_TextChanged is triggered.
In MacAdressTextBox_TextChanged you change the text.
see step 1
your text change causes an infinite recursion on MacAdressTextBox_TextChanged.
One way to do it would be to grab the Text, remove the colons, then add them back in at the correct positions. In order to keep the app from hanging in an endless recursive loop, you can add a variable to track whether or not the text is being changed by our code or the user.
For example:
// When this is true it means our code is changing the text
private bool updatingTextWithCode = false;
private void MacAdressTextBox_TextChanged(object sender, EventArgs e)
{
if (updatingTextWithCode)
{
// Our code is doing the update, so just reset the variable
updatingTextWithCode = false;
}
else
{
// The user is updating the text, so process the contents
var newText = "";
// Store the mac address without the ':' characters
var plainText = MacAdressTextBox.Text.Replace(":", "");
// Then add ':' characters in correct positions to 'newText'
for (int i = 1; i <= plainText.Length; i++)
{
newText += plainText[i - 1];
if (i % 2 == 0) newText += ":";
}
// Set our global variable and update the text
updatingTextWithCode = true;
MacAdressTextBox.Text = newText;
MacAdressTextBox.Select(MacAdressTextBox.TextLength, 0);
}
}
UPDATE: CodeCaster correctly pointed out that this code does not allow the user to backspace over a colon. One way to fix this is to add the following event handler as well:
private void MacAdressTextBox_KeyDown(object sender, KeyEventArgs e)
{
// Disable formatting code when backspacing
if (e.KeyCode == Keys.Back) { updatingTextWithCode = true; }
}

My form doesn't loop this correctly

I can't seem to get this loop to work.
Once the submit button is clicked ten times it should revert to the main form; instead it's reverting as soon as the submit is clicked once.
private void submit_Click(object sender, EventArgs e)
{
Form1 mainMenu = new Form1();
int repeat = 0;
do
{
num1.Text = A1.firstRandomNumber().ToString();
num2.Text = A1.secondRandomNumber().ToString();
repeat++;
} while (repeat <= 10);
if (repeat == 11)
{
mainMenu.Show();
this.Hide();
}
}
Everything inside of submit_Click occurs for each click. That includes defining repeat anew, setting it to 0, looping to increment it entirely to 11, and swapping which form is visible.
If you want to count the number of clicks, you'll have to establish your counter outside of the handler so it can be incremented:
private int repeatSubmit = 0;
private void submit_Click(object sender, EventArgs e)
{
if (repeatSubmit < 10)
{
num1.Text = A1.firstRandomNumber().ToString();
num2.Text = A1.secondRandomNumber().ToString();
repeatSubmit++;
}
else
{
mainMenu.Show();
this.Hide();
repeatSubmit = 0; // ready for the next time `this` form is shown
}
}
Just to clarify, you are waiting for the user to click the button 10 times? Or the loop is supposed to simulate 10 clicks?
This loop will enter (do) and set num1 and num2, add one to repeat, and then do that 10 times until repeat == 11, and then it will display the main menu.
I think the code you make be looking for is as follows:
private void submit_Click(object sender, EventArgs e)
{
...
repeat ++;
num1.Text = A1.firstRandomNumber().ToString();
num2.Text = A2.secondRandomNumer().ToString();
if(repeat >=10)
{
mainMenu.Show();
this.Hide();
}
}
As your code is, on 1 click you enter your loop where you proceed to increment the counter until it's equal to 11, then you exit your loop and show the main menu. Basically you're not counting clicks.
What you want to do is store the counter somewhere, probably as a class variable. Then every time you enter the click function you increment. When the click function has been entered 10 times then you would go into your if statement.
private int clickCount = 0;
private void submit_Click(object sender, EventArgs e){
clickCount++;
// Other code that happens on a click
if (clickCount == 10){ // 10th click show main menu
// Code to show main menu
}
}
It runs through the loop on the first click of submit, if I understand what you are trying to achieve, you don't need a loop at all, just a counter for each time the button is pressed.

Show items (checkboxes, radiobuttons etc...) by case (if...else...etc...)

I am trying to make a little game in C#.
The program asks the user for a any number.
The user then presses "GO" (button1) and the program checks whether the number is an even number or not. (x % 2 == 0)
I'm trying to get the program to show 4 checkboxes/radio buttons out of total of 8 depending on each case.
For example:
If the number is an EVEN NUMBER: The program will show options 2,5,3,6.
If the number is an ODD NUMBER: The program will show options 1,4,7,8.
(Options 1-8 were already included in the design.)
I need help with the if (x % 2 == 0) part. What do I write in it to make the checkboxes/radiobuttons appear or disappear?
By the way, is there a way to ask the user for a number without him having to click "GO"?
Like, use ENTER instead. If yes, what event is that?
Also, is there a way to limit the textbox to INT only?
I know it's asking you to do the job, but I have tried, and I'm still a real beginner, therefore I think my way of learning is by actually experiencing it.
public partial class Form1 : Form
{
int x;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
x = int.Parse(textBox1.Text);
if (x % 2 == 0)
{
}
}
}
The Visible property of the CheckBox (inherited from Control) will aid you in making the needed controls visible when you wish them to be. Your if would look something like,
if (num % 2 == 0)
{
box1.Visible = false;
box2.Visible = true;
// ...
}
else
{
box1.Visible = true;
box2.Visible = false;
// ...
}
However, this can be optimized a bit by using the condition to set the visibility of all the CheckBoxs at the same time instead of coding two conditionals - something like:
box1.Visible = !(num % 2 == 0);
box2.Visible = (num % 2 == 0);
// ...
As for on pressing enter, check the OnKeyDown event for you control, you can do this through the designer. Your event method would look like:
private void myControl_OnKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
// Handle enter key pressed here
}
}
This should help you with your problems.
ADDITIONAL RESPONSE
List<CheckBox> boxes = new List<CheckBox>();
// Add all boxes and do other stuff, disable all
foreach (CheckBox box in boxes)
{
box.Visible = false;
}
In order to limit the textbox to int, you could override OnKeyPressed. As for your checkboxes, you could use the Visible or Checked properties.

Disabling Timer .. why I can't?

When I use System.Windows.Forms.Timer class and finish using it then I can't disable it.. it ticks even if I set its property Enabled to false. What is wrong with the code? here is an example:
int counter = 0;
private void timer1_Tick(object sender, EventArgs e) {
MessageBox.Show("Hello");
counter++;
if (counter == 10){
timer1.Enabled = false;
}
}
This is a subtle bug that's induced by the MessageBox.Show() call. MessageBox pumps a message loop to keep the UI alive. Which allows the Tick event handler to run again, even though it is already active from the previous tick. The counter variable doesn't get incremented until you click the OK button. As a result, the screen fills with message boxes and that won't stop until you click the OK button ten times.
You need to increment the counter before showing the message box. Fix:
int counter = 0;
private void timer1_Tick(object sender, EventArgs e) {
counter++;
if (counter > 10) timer1.Enabled = false;
else MessageBox.Show("Hello");
}
This kind of problem is also the reason that DoEvents() got such a bad reputation. It is pretty difficult to write code that can properly deal with the re-entrancy induced by the message loop. You need to keep boolean flags around that indicate that code is already active. Which is another way to solve your problem:
int counter = 0;
bool showingBox = false;
private void timer1_Tick(object sender, EventArgs e) {
if (showingBox) return;
showingBox = true;
try {
MessageBox.Show("Hello");
counter++;
if (counter == 10) timer1.Enabled = false;
}
finally {
showingBox = false;
}
}
You now get only one message box at a time, probably what you are really looking for.
I should mention that this re-entrancy problem is pretty specific to timers. A dialog takes counter-measures to avoid re-entrancy problems, it disables all the windows in the application. That ensures that the user cannot do things like closing the main window or clicking a button that brings up the dialog again. Both rather disastrous mishaps. That takes care of most of the 'unexpected' Windows notifications, basically any of the messages that are generated by the user. The edge case is a timer (WM_TIMER is not disabled) whose event handler has a UI effect.
It is because the MessageBox.Show blocks until the user presses OK.
The code below the MessageBox will not execute until after 10 OK buttons are pressed.
But the timer continues to fire even if the execution is blocked.
Try this code
int counter = 0;
private void timer1_Tick(object sender, EventArgs e) {
counter++;
if (counter == 10){
timer1.Enabled = false;
}
MessageBox.Show("Hello");
}
(just moved the MessageBox)
What about timer1.Stop()? I am not too familiar with this class, but looked it up quickly: Timer Class
try this:
int counter = 0;
private void timer1_Tick(object sender, EventArgs e) {
MessageBox.Show("Hello");
counter++;
if (counter == 10){
timer1.Stop();
timer1.Dispose();
timer1 = null;
}
}
It is also working for me. I placed the timer in the form, on the button click, I am calling timer1.start() and I put the following code in the tick event and its working.
int i = 0;
private void timer1_Tick(object sender, EventArgs e)
{
i++;
this.Text = i.ToString();
if (i == 10)
{
timer1.Enabled = false;
}
}
You need to call Stop.
int i = 0;
private void timer1_Tick(object sender, EventArgs e)
{
i++;
if (i == 10)
{
timer1.Stop();
}
}
I'm pretty sure the MessageBox is the culprit here. Maybe if you use a short execution interval for the timer handler then this could potentially cause your code to function undesirably, if executions are overlapping.
The problem would be, in this case, that the handler executes and displays the MessageBox which in turn halts execution of the current scope until the the prompt is acknowledged by the user, meanwhile the handler has started again, showing another prompt, and another, and so on. At this point, we have multiple MessageBoxes waiting for input, yet counter hasn't even been incremented once. When we click 'OK' on the prompt, counter increments as desired, but at this point has a value of 1, rather than a value representing the number of prompts shown. This means yet another prompt will be displayed if more time elapses, until the user clicks 'OK' on at least 10 prompts.
You could try inhibiting execution if the process is already under way in order to prevent concurrent runs:
private readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
int counter = 0;
private void timer1_Tick(object sender, EventArgs e)
{
if (Locker.TryEnterWriteLock(0))
{
try
{
MessageBox.Show("Hello");
Counter++;
if (Counter == 10)
{
Timer.Enabled = false;
}
}
catch { }
finally
{
Locker.ExitWriteLock();
}
}
}

Categories