I'm developing a textbased RPG . If you type something into the textbox (tUser), the method Input() gets called and processes your query. If it matches a certain condition, something else, e. g. exiting the game, will happen.
public void Input()
{
if (tUser.Text.ToLower() == "ende" || listening)
{
if (tUser.Text.ToLower() == "ende")
{
if (MessageBox.Show(playername +
", wollt Ihr wirklich das Spiel ohne Speichern verlassen?", "Beenden",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
Application.Exit();
}
}
else
{
input = tUser.Text;
if (accept == 1 && !input.Any(char.IsDigit))
{
tRPG.AppendText("\nBitte gebt nur eine Zahl ein!");
}
else
{
listening = false;
}
}
}
// Reset
input = "";
tUser.Clear();
}
Your query will be submitted if you press Enter. After the process is done, the TextBox is being cleared.
If you try the same or any other command (again), nothing's going to happen, until you delete an "invisible" character in the TextBox.
I have also tried tUser.ClearUndo().
What is this character and how can I avoid it?
Why not just set the text to an empty string instead of using clear?
tUser.Text = string.Empty;
Well I believe it has something to do with the fact that your key events still set the value of the textbox or something alike after the textbox has been cleared. Anyway, a quick fix is to just use tUser.trimStart(' ') or something alike.
For some reason, the textbox keeps a carriage return. Adding e.Handled = true to the method which calls Input() solves this issue.
private void tUser_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
e.Handled = true;
Input();
}
}
e.Handled prevents the enter message from being processed after this handler has finished (source).
Related
I am creating an application that has an entry. I am trying to restrict the entry to only allow for numeric input. I have already tried using Keyboard = "Numeric". For the iPad, however, the keyboard has more characters than just numbers. So I had to restrict what is entered. When I do this however, if the user types in a parenthesis, for example, it does stop the character from being entered. But then if the user presses undo, it crashes. I assume this is because the software keyboard is separate from the app, so it is looking for that parenthesis character, but it isn't there. Here is my code:
private void Entry_TextChanged(object sender, TextChangedEventArgs e)
{
Entry theEntry = (Entry)sender;
string entryText = theEntry.Text;
if(entryText != null && entryText.Length != 0)
{
char theMostRecentInput = entryText[entryText.Length - 1];
if(!Extension.IsNumeric(theMostRecentInput))
{
theEntry.TextChanged -= Entry_TextChanged;
theEntry.Text = e.OldTextValue;
theEntry.TextChanged += Entry_TextChanged;
}
}
}
Thanks for the help!
This issue will occur when Validation like special character, Max Limit, etc... for Input field are implemented.
By that time undo action will have extra character count than current input field text characters length in iOS ShouldChangeCharacters Delegate. This leads to app crash.
One of the solution is to return as false in such scenario instead of disabling undo buttons. Below solution worked for me.
public class ExtEntryRenderer : EntryRenderer
{
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (Control != null)
{
Control.ShouldChangeCharacters += (UITextField textField, NSRange range, string replacementString) =>
{
if (range.Location + range.Length > ((UITextField)textField).Text.Length)
return false;
return true;
};
}
}
}
I would do this in a Entry custom renderer that way you you can control the input via ShouldChangeCharacters and not have to kludge it by allowing the input and then having to remove the handler and change the text back to the old value...
Here is a quick example that allows numeric, It also automatically handles clipboard pasting non-numeric strings as those would be disallowed. I am using the NSCharacterSet.DecimalDigits character set as that would be internationalized by the OS, but you could allow/disallow any chars of your choosing.
You could also include haptic, visual or audio feedback on the disallowed/rejected entries...
[assembly: ExportRenderer(typeof(NumericEntry), typeof(NumericEntryRenderer))]
namespace Forms_PCL_Tester.iOS
{
public class NumericEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Entry> e)
{
base.OnElementChanged(e);
if (e.NewElement != e.OldElement)
if (Control != null)
{
Control.KeyboardType = UIKeyboardType.NumbersAndPunctuation;
Control.ShouldChangeCharacters += (UITextField textField, NSRange range, string replacementString) =>
{
foreach (var aChar in replacementString)
if (!NSCharacterSet.DecimalDigits.Contains(aChar))
return false;
return true;
};
}
}
}
}
The following code is being used as a generic event handler for 16 digit buttons on a hexadecimal calculator (0-9, A-F).
The following instructions define what I need to be accomplishing:
If the calculator is in display mode when a digit is pressed, that digit will replace the current content of the display and place the calculator in input mode. If the calculator is in input mode, there are three cases:
If the content of the display is "0", the digit on the button pressed will replace the content of the display.
Otherwise, if the content of the display contains fewer than eight characters (because we are dealing with 32-bit words), the digit on the button pressed will be appended to the content of the display.
Otherwise, the button press is ignored.
One button press on my calculator will update the display correctly. However, if I press another button, instead of appending the StringBuilder with the new character, it will instead display a double character for the last button pressed. Eg. One press of 'C' will display a 'C'. A press of 'C' then say '8' will display '88'. Where is my problem here?
public void ProcessClick(object sender, EventArgs e)
{
StringBuilder _button = new StringBuilder();
_button.Append(((Button)sender).Text);
if (mode)
{
uxDisplay.Text = _button.ToString();
mode = false;
}
else
{
if (uxDisplay.Text == "0")
{
uxDisplay.Text = _button.ToString();
}
else if (uxDisplay.Text.Length < 8)
{
uxDisplay.Text = _button.Append(((Button)sender).Text).ToString();
}
else
{
return;
}
}
}
You appear to be appending the value of sender.Text twice.
Here:
_button.Append(((Button)sender).Text);
and here:
uxDisplay.Text = _button.Append(((Button)sender).Text).ToString();
You are also creating a new StringBuilder on each call to Process so you aren't persisting the last value (apart from in the uxDisplay control)
How about something simple like:
...
else if (uxDisplay.Text.Length < 8)
{
uxDisplay.Text += ((Button)sender).Text;
}
You are only appending a small number of strings so you won't really gain all that much performance from using a StringBuilder (especially if you create a new one on each call! :P )
You are appending the pressed button text to your StringBuilder object directly after its creation, that's why you get twice the character.
You can go with something simple like this:
public void ProcessClick(object sender, EventArgs e)
{
if (mode)
{
uxDisplay.Text = _button.ToString();
mode = false;
}
else
{
if (uxDisplay.Text == "0")
{
uxDisplay.Text = _button.ToString();
}
else if (uxDisplay.Text.Length < 8)
{
uxDisplay.Text += ((Button)sender).Text;
}
else
{
return;
}
}
}
I am making a simple hangman style game in a C# form. I have it set as textBox1_TextChanged. Except everytime the user backspaces their guess letter it takes in blank space. How can I make it so after the message saying right/wrong it clears the space. I am getting annoyed at it telling the user they made a wrong guess after they backspace. This is my first post on this forum so sorry if the code text is weird. I just want the program to clear the text in the textBox after they guess.
UPDATE: Added suggested information. Now it does everything it is supposed to do. Except it pops up a windows saying " was found in the target word". This happens if guessLetter == null || guessLetter == correct || guessLetter == false.
private void textBox1_TextChanged(object sender, EventArgs e)
{
string guessLetter = textBox1.Text;
//textBox1.ReadOnly = true;
if (targetWord == null)
{
MessageBox.Show("Please start a new game.");
textBox1.Text = ("");
}
else
{
if (targetWord.Contains(guessLetter))
{
MessageBox.Show(guessLetter + " was found in the word");
}
else
{
MessageBox.Show(guessLetter + " was not found in the word");
incorrectGuessCtr++;
textBox3.Text = incorrectGuessCtr.ToString();
}
textBox1.Text = ("");
}
}
Don't only check if the targetWord is null, but also the guessLetter. You'd better use string.IsNullOrEmpty too, since it also checks if the string is empty:
if (!string.IsNullOrEmpty(targetWord) && !string.IsNullOrEmpty(guessLetter))
{
...
}
I guess you should also check if there is exactly one letter entered. That would mean this additional check:
if (guessLetter.Length == 1)
{
...
}
You will enter this event when you write code that changes Text property in textbox. I mean this.
textBox3.Text = incorrectGuessCtr.ToString();
Put something in function arguments or set some flags so that you can identify whether the event is called from user input or your clearing the text.
Just check how many times this function is called when user press backspace. You will get the idea.
I have a modeless UI that adds a userID to a list that allows or removes access to parts of a program. When I click the modify button everything works as it should. Suppose I close the dialog and realize "Wait, forgot to do X". When I reopen the dialog box, perform my work and click Modify, the value for adding the userID is still available to the program even though the textbox is blank.
It's happening somewhere in the following code.
public static void checkSame()
{
int count = 0;
bool test = false;
while (linesPerm.Length >= count && tbPermValue != "")
{
if (linesPerm.Length >= count)
{
test = linesPerm.Contains(tbPermValue);
count += (linesPerm.Length + 1);
if (test == true)
{
DialogResult dr = MessageBox.Show("The UserID " + tbPermValue +
" already exists in the Permissions column. "
+ Environment.NewLine + "Would you like to add the UserID" +
tbPermValue + " to the Permissions column anyway?",
"User Already Exists", MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
switch (dr)
{
case DialogResult.Yes:
break;
case DialogResult.No:
tbPermValue = "";
break;
}
}
}
else
{
MessageBox.Show("Do Nothing");
}
}
}
If the user selects No on the dialog box, the value of tbPermValue is not available to the program. If the user selects Yes then the value of tbPermValue persists even if the dialog box is closed and reopened. I have tried to clear the textbox value like so.
tbUserName.Text = "";
tbUserName.Clear();
and several other ways. tbUserName value is being cleared from the textbox, but not from the code above. I get the value of tbPermValue like this.
public static void addPerm(System.Windows.Forms.Form targetForm)
{
foreach (Control C in targetForm.Controls)
{
if (C.GetType() == typeof(TextBox))
{
if (C.Text != "")
{
tbPermValue = C.Text;
}
}
}
}
This is a modeless dialog box owned by it's parent.
Can anyone point me in a direction that would remove access to tbPermValue to the DialogResult portion of the first code box after the button is clicked. I can't lose it completely because tbPermValue is used in other code down the line.
EDIT: Ok. I just tested this and the value is being held in memory. I have a dialog Form1 that has a button that opens dialog StartHere. On StartHere there is a button that opens Permissions. StartHere owns Permissions so that when I close StartHere, Permissions and all other child forms of StartHere will close. These are all modeless dialogs. My variable tbPermValue is being held in memory way back to Form1. The value is not being disposed when I close the dialog StartHere. I'm going to go back and research Garbage Collection at the advice of Eric below. Thank you Eric. I'll delete the question or at least post a new better question once I find out the rules for this process. Thank You.
Edit 2: Here is the code you asked for γηράσκωδ'αείπολλάδιδασκόμε
private void bModify_Click(object sender, EventArgs e)
{
WidgetLogic.addPerm(this);
WidgetLogic.checkSame();
WidgetLogic.writePerm(this);
WidgetLogic.writeAdmin(this);
WidgetLogic.writeDetailer(this);
tbUserName.Clear();
}
As noted above I have tried numerous ways to clear tbUserName to no avail.
Don't use tbPermValue but instead use the textbox directly:
while (linesPerm.Length >= count && tbUserName.Text != "")
EDIT
Change the code in addPerm to this, and you are done :):
public static void addPerm(System.Windows.Forms.Form targetForm)
{
foreach (Control C in targetForm.Controls)
{
if (C.GetType() == typeof(TextBox))
{
tbPermValue = C.Text;
}
}
}
You don't need the switch (dr) in checkSame()
I see that you say you have tried setting the following in the "yes" part of your switch statement:
tbUserName.Text = "";
tbUserName.Clear();
But in your "no" part, you don't set tbUserName, but instead you set the variable tbPermValue. From what I can tell, you should also be setting
tbPermValue = "";
in your "yes" part as well to clear that variable, or even just move it out of the switch and have it do that before the dialog closes since you would be setting it in all of the possible switch cases anyways.
I am using a test card and this is the output after I swiped the card and it is ok
But when I'm trying to get the data of the swiped through prompting it to messagebox this will be the output
How can I fix this? I am expecting the output same as the first image, and it will also be the message of the messagebox
Here is my code:
private void CreditCardProcessor_Load(object sender, EventArgs e)
{
KeyPreview = true;
KeyPress += CreditCardProcessor_KeyPress;
}
private bool inputToLabel = true;
private void CreditCardProcessor_KeyPress(object sender, KeyPressEventArgs e)
{
if (inputToLabel)
{
label13.Text = label13.Text + e.KeyChar;
e.Handled = true;
}
else
{
e.Handled = false;
}
MessageBox.Show(label13.Text);
}
In short I want to run a function after swiping the card, and use its data to be use in my function. :)
You'll need to be more specific with your question. From the looks of things your card scanner is operating through the keyboard buffer. (Many card scanners operate this way) This means that every character of the strip is received as a character which is why you can capture this OnKeyPress.
If you're wondering why you're only seeing one character at a time it is exactly because you're raising a message box with each character received. If you want to know when you can call a function with the whole card info using that code what you'll need is something like:
private bool inputToLabel = true;
private StringBuilder cardData = new StringBuilder();
private void CreditCardProcessor_KeyPress(object sender, KeyPressEventArgs e)
{
if (!inputToLabel)
return;
if (e.KeyChar == '\r')
{
MessageBox.Show(cardData.ToString()); // Call your method here.
}
else
{
cardData.Append(e.KeyChar);
//label13.Text = label13.Text + e.KeyChar;
}
e.Handled = true;
}
Caveat: This is assuming that the card reader library is configured to terminate a card read with carriage return. (\r) You'll need to read up, or experiment with it for settings as to whether it can/does send a terminating character to know when the card read is complete. Failing that you can watch the output string for patterns. (I.e. when the captured string ends with "??") Though this is less optimal.