I've been working on making a dozenal calculator, so far it's going well. I have a UI that allows me to click numerals in, but something strange happens when I use my numpad to input my numbers.
When I press any number on my numpad instead of clicking, I get doubles.
example:
If I click 2 on screen, I get "2"
If I press 2 on my numpad, I get "22"
Here's part of my UI code:
if(GUI.Button(new Rect(113, 186, 47, 30), numeral[2]))
AppendNumber(numeral[2]);
Here's part of my keyboard code:
if(Input.GetKeyDown("[2]"))
AppendNumber(numeral[2]);
Here's my append code:
void AppendNumber (string num)
{
if (opIsActive == false)
{
slotA = num;
} else {
slotB = num;
}
if (currentNumber != numeral[0])
{
currentNumber = currentNumber + num;
if (opIsActive == false)
{
slotA = currentNumber;
} else {
slotB = currentNumber;
}
} else {
currentNumber = num;
}
}
Any ways, for now my keyboard function is disabled. If anyone knows what the problem may be, I'd love to see.
Use GetAxis instead of GetKeyDown as pointed out by TaW. For some reason GetKeyDown provided double characters, eg. "22" instead of "2".
Related
Basically what I need is an idea how to shorten my code.
So what I have now is an IF series to get the keys that user presses:
if (Input.GetKeyDown(KeyCode.I))
{
AddToBuffer("I");
}
else if (Input.GetKeyDown(KeyCode.N))
{
AddToBuffer("N");
}
else if (Input.GetKeyDown(KeyCode.F))
{
AddToBuffer("F");
}
It works perfectly well, but what I want is to shorten it so it would be possible to save to buffer any key (better, as a string)
So that I would no more have to specify what key was pressed.
(Maybe something like TryParse etc.)
InputString contains a string all keys pressed down on the current frame. It is recommended to break the string down into characters as shown in the input string example in Unity documentation, as inputString can contain backspace '\b' and enter '\n' characters.
An example of listening for cheatcodes might look like this:
string cheatCode = "money";
int cheatIndex = 0;
void Update()
{
if(Input.anyKeyDown)
{
foreach (char c in Input.inputString)
{
if(c == cheatCode[cheatIndex])
{
//the next character was entered correctly
Debug.Log("The next character {0} was entered correctly", c);
//On the next key down, check the next character
cheatIndex++;
} else
{
//The character was not correctly entered, reset the cheat index back to the start of the code
Debug.Log("Cheat code invalid. {0} was not the next character", c);
cheatIndex = 0;
}
}
if(cheatIndex == cheatCode.Length)
{
Debug.Log("Cheat code was successfully entered")
}
}
}
I have not written this in Unity and tested it, so your mileage may vary.
You can use "any key": https://docs.unity3d.com/ScriptReference/Input-anyKey.html
if (Input.anyKey)
{
Debug.Log("A key or mouse click has been detected");
// get the pressed key:
String keycode = Event.current.keyCode.ToString();
}
I want to create a form that allows the user to set a certain amount of points in five different fields (NumericUpDown). When that amount of points reaches 0, the user can't add any more. (I still want the user to be able to remove points, though.)
Here is my code so far:
private void calculateValue() {
decimal tempValue = CMB_num_Aim.Value + CMB_num_Reflexes.Value +
CMB_num_Positioning.Value + CMB_num_Movement.Value + CMB_num_Teamwork.Value;
controlValue = currentValue - tempValue;
MyBox.CMB_tb_cv.Text = controlValue.ToString();
}
This Method (calculateValue) is calculates how many points the user have left (controlValue).
private void CMB_num_Aim_ValueChanged(object sender, EventArgs e) {
calculateValue();
if (controlValue < 0) {
//Prevent Default here
MessageBox.Show("You are out of points!");
}
}
This method (CMB_num_Aim_ValueChanged) fires when the value of the NumericUpDown control has changed. I have one of these for each field, each doing the same thing.
The method fires as expected, but I can't prevent it from happening - the user can apply more points than they have. How can I prevent the user from applying more points?
(I thought about making a mouseUp method, but I don't know if the user will use the mouse or if he will type in the value using the keyboard.)
Seems like you want to create a point distribution system between some skills - aim, movement, teamwork etc. You can do that easily by setting Maximum value of NumericUpDown control when you enter it. Subscribe all skill updown controls to the same event handler:
private void SkillNumericUpDown_Enter(object sender, EventArgs e)
{
var skill = (NumericUpDown)sender;
var availablePoints = 42;
var maxSkillPoints = 20; // usually you cannot assign all points to one skill
var unassignedPoints = availablePoints - SkillPointsAssigned;
skill.Maximum = Math.Min(maxSkillPoints, unassignedPoints + skill.Value);
if (unassignedPoints == 0)
{
MessageBox.Show("You are out of points!");
return;
}
if (skill.Value == maxSkillPoints)
{
MessageBox.Show("Skill maximized!");
return;
}
}
private decimal SkillPointsAssigned =>
CMB_num_Aim.Value +
CMB_num_Reflexes.Value +
CMB_num_Positioning.Value +
CMB_num_Movement.Value +
CMB_num_Teamwork.Value;
Benefit - you will not be able to input illegal value neither by arrows nor manually.
Replace
if (controlValue < 0) {
By
if (controlValue <= 0) {
I am creating a windows form that is a random number guessing game. I've made these before in C++ and never had an issue, however I have a big one here- I have no idea how to get the user back to input a number after the loop has began running. Here is my code:
private void btnGuess_Click(object sender, EventArgs e)
{
int guess = 0;
int count = 0;
int accumulator = 0; // accumulator
Random rand = new Random();
int number = rand.Next(1, 100);
txtAnswer.Focus();
while (guess != number)
{
guess = int.Parse(txtAnswer.Text);
if (guess < number)
{
MessageBox.Show("Too Low! Guess again!");
txtAnswer.Text = "";
txtAnswer.Focus();
count++;
accumulator++;
}
else if (guess > number)
{
MessageBox.Show("Too High! Try again!");
txtAnswer.Text = "";
txtAnswer.Focus();
count++;
accumulator++;
}
else
{
MessageBox.Show("Correct! you guessed the number in " + accumulator + " tries!");
break;
}
}
}
}
}
I just filled the while loop arguments with something for you guys, even though i know it won't work. Basically, I need to run the loop, get feedback (if the users guess was too high or low) then get the user to be able to input another number BEFORE the loop runs again. I don't know how to get that to happen with a text box control which is where the input will be. Any ideas?
You should not loop inside in the btnGuess_Click. Instead you need to store the state (the number, count, and the accumulator variables) in the scope of the form itself.
Initialize the random number when the form loads, or using some kind of start button.
Then inside the guess button handler, read the text box value and compare it to the number variable, such as what you are doing currently.
What you are building is more a console style application. So there is 1 main loop that is executing all the code.
In forms applications it is an event driven environment. So the user gets a form, presses a button, the form is evaluated and then the method handling ends.
So you have on a class level some variables for counts, in the constructor you add the initialization and the method for submit will be something like
private void btnGuess_Click(object sender, EventArgs e)
{
//Increment counters
//Check
//Show feedback
//Leave the button click code
}
For some more info, check this out:
https://msdn.microsoft.com/en-us/library/dd492132.aspx
I have a simple form that takes 9 decimal numbers from 9 textboxes and I put some validation so that the users can only enter decimal numbers and nothing else.
Now the challenge I'm having is how to set the cursor in the textbox that had no decimal number after showing the error message in the try-catch statement?
Here's my code:
private void btn_Aceptar_Click(object sender, EventArgs e)
{
POI GPI = new POI();
POI VIM = new POI();
POI ST = new POI();
try
{
GPI.POI_x = Convert.ToDecimal(txt_GPIx.Text);
GPI.POI_y = Convert.ToDecimal(txt_GPIy.Text);
GPI.POI_z = Convert.ToDecimal(txt_GPIz.Text);
VIM.POI_x = Convert.ToDecimal(txt_VIMx.Text);
VIM.POI_y = Convert.ToDecimal(txt_VIMy.Text);
VIM.POI_z = Convert.ToDecimal(txt_VIMz.Text);
ST.POI_x = Convert.ToDecimal(txt_STx.Text);
ST.POI_y = Convert.ToDecimal(txt_STy.Text);
ST.POI_z = Convert.ToDecimal(txt_STz.Text);
}
catch (Exception)
{
MessageBox.Show("Ingrese solamente nĂºmeros en las variables GPI/VIM/ST", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
//Set the cursor in the first textbox that had no decimals..
return;
}
Comisurales Comisurales = new Comisurales();
Comisurales.calculo_coord_comisurales(PC, AC, IHP, GPI, VIM, ST);
}
Let me add that I also have a function to ensure the user is only limited to enter decimals but I wasn't able to figure how to avoid the "." only or this for example: "1."
As an addition to my question, here's what gets validated every time the user press a key in the textbox:
private void ValidarDecimal(object sender, KeyPressEventArgs e)
{
// permitir 0-9, backspace, y decimal
if (((e.KeyChar < 48 || e.KeyChar > 57) && e.KeyChar != 8 && e.KeyChar != 46))
{
e.Handled = true;
return;
}
// chequear solamente un decimal
if (e.KeyChar == 46)
{
if ((sender as TextBox).Text.IndexOf(e.KeyChar) != -1)
e.Handled = true;
}
}
I guess I have 2 ways to resolve my issue. Number one would be find a way to ensure the user never ever enters something weird in the textbox (which I've done partially) and number 2 would be to use the try-catch with the current limitations I mentioned above and then point the user to the textbox that has issues, both are acceptable.
The Decimal class has a TryParse method that could be used to avoid all this logic driven by catching exceptions (a very expensive approach in terms of performance)
decimal value;
if(decimal.TryParse(txt_GPIx.Text, out value))
GPI.POI_x = value;
else
{
MessageBox.Show("Invalid decimal value");
txt_GPIx.Focus();
}
Of course this code needs to be repeated for every control in your list, but you could write a generic function like this one
private decimal GetValueAndValidate(Textbox txt, out bool isOK)
{
isOK = true;
decimal value = 0m;
if(!decimal.TryParse(txt.Text, out value))
{
MessageBox.Show("Invalid decimal value");
txt.Focus();
isOK = false;
}
return value;
}
and then use the following approach in your code inside the button click
bool isOK = true;
if(isOK) GPI.POI_x = GetValueAndValidate(txt_GPIx, out isOK);
if(isOK) GPI.POI_y = GetValueAndValidate(txt_GPIy, out isOK);
.... and so on for the other fields ....
For the second part of your question, finding a way to completely control the input logic is not easy. What happens for example if your user PASTE an invalid text in your textbox? There are very edge case situations that takes a lot of effort to code correctly. It is a lot more easy to leave freedom of typing to your user and apply a strict logic when you get that input.
I want to obligate the person who is using my program to enter only numbers in the text label in c#. How can i do that?
example :
number of equations : (he should only enter a number)
This code to obligate him to enter a number between 2 and 10 but i need a code for letters
if (int.Parse(txt1.Text) < 2 || int.Parse(txt1.Text) > 10)
{
l6.ForeColor = System.Drawing.Color.Red;
l6.Text = "Svp choisir un nombre entre 2 et 10 ... Soyez Logique!";
}
put this (or a variation of this, according to what you want to let the user to enter) in the textbox keypress event, so basically you will manage key presses in this textbox..
Add System.Media library to use the beep if the user enters wrong key, or remove it from the code...
if ((e.KeyChar >= '0') && (e.KeyChar <= '9') && (txt1.Text.Length < 10))
{
}
else if (e.KeyChar == 0x08)
{
//BACKSPACE CHAR
}
else if (txt1.SelectionLength > 0)
{
//IF TEXT SELECTED -> LET IT OVERRIDE
}
else
{
e.Handled = true;
SystemSounds.Beep.Play();
}
if (txt1.Text.Trim().Length > 0)
{
// Parse the value only once as it can be quite performance expensive.
Int32 value = Int32.Parse(txt1.Text)
if ((value >= 2) && (value <= 10))
{
l6.ForeColor = Color.Red;
l6.Text = "Svp choisir un nombre entre 2 et 10 ... Soyez Logique!";
// Clear the text...
txt1.Text = "";
}
else
{
// Your code here...
}
}
But, IMHO, TryParse is even better as it can handle bad string formats in a better way:
if (txt1.Text.Trim().Length > 0)
{
Int32 value;
if (!Int32.TryParse(txt1.Text, out value))
{
l6.ForeColor = Color.Red;
l6.Text = "Svp choisir un nombre entre 2 et 10 ... Soyez Logique!";
// Clear the text...
txt1.Text = "";
}
else
{
// Your code here...
}
}
What GUI do you use?
Using Winforms there are two ways that come to mind:
I recommend: Use a numericUpDown Control instead of a textBox. This way the user can only enter numbers and has nice Up/Down arrows to change the value. Plus you get handling of cursor keys.
Implement an Validating event handler.
Checking the various methods to insert text in a textbox to avoid non number chars is not an easy task and more often than not it fails somewhere. For example what about text pasted from the clipboard?, what about Backspace, Delete, Left, Right arrows keys?.
In my opinion it is better to follow a different approach.
Use the Validating event and let the user type or paste whatever he wants. At the validation event do you checks and advise the user or add a special errorProvider to signal the error:
private void l6_Validating(object sender, CancelEventArgs e)
{
int isNumber = 0;
if (l6.Text.Trim().Length > 0)
{
if (!int.TryParse(l6.Text, out isNumber))
{
e.Cancel = true;
errorProvider1.SetError(l6, "Svp choisir un nombre entre 2 et 10 ...";);
}
else
{
errorProvider1.SetError(l6, "");
}
}
}
}