Getting text from an input field only works after focus changes - c#

I've created a Pause menu for a simple game i'm making. In that pause menu there is a field to enter your username. I'm attempting to check that a username has been entered before the user is allowed to close the pause menu. However both the input.text and input.TextComponent.text values are only changed to the typed username when focus is changed away from the input field.
My code is as follows:
public InputField input;
if ((string.IsNullOrEmpty (input.text)) || (input.text == "Enter Username")){
input.textComponent.color = Color.red;
input.text = "Enter Username";
} else {
input.textComponent.color = Color.black;
//hide pause menu and resume game
canvas.gameObject.SetActive (false);
Time.timeScale = 1;
}
This code only works when the user clicks away from the input field box before attempting to close the pause menu. How can I get the text entered as its entered?
I've tried adding GUI.focusControl("") and GUI.focusControl(null) before the if statement but this doesn't work either.
Edit :
I've confirmed that the second parameter of the if statement is working. The menu doesn't close if the entered text is "Enter Username", so i know im checking the text variable correctly. I just dont understand why the if statement returns true if you enter in anything else? I must be missing something

Both GUI.focusControl("") and GUI.focusControl(null) have nothing to do with the Unity's new UI system(uGUI). They are made to work with IMGUI.
If you want to focus on InputField you can use the code below:
public InputField input;
input.ActivateInputField();
input.Select();
To stop the focus
input.DeactivateInputField();
Do not try to poll InputField.text. That's not how use it. You do have two options in this case:
1.Subscribe to the InputField onEndEdit event.
When the player is done typing and clicks Enter/Return or away, this function will be called. You can then check/compare for the username there.
Check #3 from this post.
2.Add a Button that says "check" or "submit". When user is done typing, they will have to click that Button. Subscribe to the Buttons onClick event. When the Button is clicked you then check/compare for the username there. Check #2 from this post.
If you find another tricky way to do this, it will work but not on Android device. You will end up rewriting the code again.

Related

How to get the "Return" key from the Android TouchScreenKeyboard (Unity, C#)

I have an InputField component that once I press my physical keyboard key Return the text in the InputField is saved. I want the same thing to happen when pressing my Android TouchScreenKeyboard "OK" or "Done" (I also tested with keyCode.Enter and that does not work). Do you know a specific KeyCode for it? Or maybe another way to achieve this?
This is the code that works with my physical keyboard:
if(Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
{
doThis(); //Saving the input's text to a variable
}
I want the same result when pressing "OK" or "Done" in my Android's TouchKeyboard. When pressing the mentioned choices, the TouchKeyboard gets hidden but the data in the InputField doesn't submit. I have created an on-screen button that calls the function doThis() as a workaround, but I want to avoid this.
Subscribe to InputField's onEndEdit event, its quite reliable at firing whenever the user is done entering text, weather its pressing enter or just loosing focus of that window, it gets fired when the user is done typing, I believe it should solve your issue
this works fine for me (PC/Mobile), try it out
this.yourInput.onSubmit.AddListener(delegate {
if (this.yourInput.text.Length > 0)
//do something when enter or done (mobile)
});

onClick called without actually clicking the button

Developing in Monogame I have created some simple way to detect that a sprite has been clicked. This is how I check that the sprite was pressed. mouseOver means the mouse is intersecting the sprite.
var lastMouseState = mouseState;
mouseState = Mouse.GetState();
if (mouseOver && lastMouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton == ButtonState.Released)
onClick(this);
onclick is managed in another class. This class is called Menu
private void onClick(Button btn)
{
//Toggles the button.
if (btn.HasCheckBox)//Whether the button has a checkbox
{
btn.Checked = !btn.Checked;
}
if (btn.Destination == "inGame")
unPause();
else if (btn.Destination == "Quit")
Exit();
else
openMenu(btn.Destination);
}
A little explanation here: Each button has a property called destination, meaning where the button leads to, such as: inGame, Options, Quit, etc.
Now here is my problem:
When the game is paused, the menu is shown containing 3 buttons (continue, options, and quit).
When the menu is opened and a submenu is entered, then a button there is pressed, after that, the menu is closed and the mouse has not been moved, then when I reopen the menu and the mouse is on top of the Quit button, the game will close. Check the gif below for a much clearer explanation.
This only happens with Quit. When I try the same procedure with the other buttons, it does not work. {SEE EDIT 2}
A small demonstration:
http://media.giphy.com/media/AxVvk9FgO6TOd5roEo/giphy.gif
I try it first with the music button. close and reopen menu -- nothing happens.
I try it with the fullscreen button, click > close > reopen menu -- game quits.
Why is a button click registered at quit, but not at options?
Thanks for the help. Comment if additional information is needed.
EDIT
Apparently, it does not matter where the mouse is when entering the options menu. As long as a click is done (anywhere in the screen) and after the menuscreen is reopened the mouse is hovering over the button, the game will quit.
Strangely enough, I added a new button, under Quit which also leads to the options menu. After testing the same behaviors with the 2nd Option button. I could not reproduce the error. However, If I do the same with the 1st Option button while hovering the second one, it works same as with Quit -- it will instantly open the option screen as if it was clicked.
Updated Gif: http://media.giphy.com/media/AxVvk60pK8NBjmghDa/giphy.gif
EDIT 2
Narrowed the bug even further. When using foreach, the bug only appears when the index of the second button is greater than the first. Explanation: I was pressing 2nd button, button[1] and it was only working for button[2] and higher.
This is my update method:
if (isPaused)
{
foreach (var button in ButtonList)
{
if (MenuScreen == button.Parent)//Menuscreen is the current screen being displayed.
//button.parent is the parent screen that holds current button. such as: ingame, pause, etc.
{
button.Update();
}
}
}
Now I know the logic behind it, but not where it happens.
Sounds like you could have some unseen characters mucking up the works, maybe from a copy paste or something. If you added another similar button and it worked, that could be a possibility.
You could re-type it by hand manually or run it through something like jsbin to see if anything shows. (In jsbin it shows red periods for unseen characters.) Just an idea to try if all else fails you.
Apparently, the bug was happening because the buttons that were not visible were not being updated, which meant that their respective mouse positions were not updated -- which still doesn't explain why the index had to be greater.
Anyway, I added a conditional in the Update method of the button. In case this bool variable is true, update the clicks too. And if the buttons are not visible, or the variable is false, only the mouse states are being updated.
Solution:
if (isPaused)
{
foreach (var button in ButtonList)
{
if (MenuScreen == button.Parent)
{
button.Update(true);
}
else
button.Update(false);
}
}

Allow button click even if validation on another control fails

I have an interesting problem that I don't know how to solve. I wrote a form which does a password change. The form displays the current password too in a read-only TextBox (not for validation purposes; this isn't important in this case.) Each password TextBox has a button in it that when clicked, masks or unmasks the password (replacing the password characters with bullets and vice versa.) Here's an image of the whole thing:
Notice how the mask/unmask buttons are inside the text boxes, not outside of them. The buttons have been placed inside the text boxes with:
var button = new Button();
button.Width = 20;
button.Cursor = Cursors.Default;
button.FlatStyle = FlatStyle.Flat;
button.Image = SystemIcons.Shield.ToBitmap();
button.Dock = DockStyle.Right;
button.CausesValidation = false;
textBox.Controls.Add(button);
The last TextBox has validation enabled. Now the problem is, that the user is unable to click the passwork unmask button on the other text box, because the validation event fails. Thus, the user is unable to see the current password without entering a new one.
I need a way to have the password mask/unmask button be clickable even if validation is failing in the text box. I can't think of anything. Moving those buttons outside the text boxes is not an option.
The unmask buttons themselves, as well as the parents of the text boxes, all have CausesValidation set to false. Only the text boxes themselves have it set to true.
This is a .NET 2.0 C# project in Visual Studio 2010.
It's not easy to do it with the Validating event of the text box. The click event will not even reach the button when the text box loses focus. I'm thinking that you could either create your own TextBox (by extending TextBox or TextBoxBase) and hack the validation behavior there or override the form's DefWndProc and catch the mouse events + associated info (coordinates) there and still dispatch them (could get ugly) when validation fails.
One easy way out is to not rely on the Validating event anymore. Instead do the validation in the Leave event of the text box and if it fails just mark the text box as such. The user will still see there is a problem.
One more thing you need to take care of is the OK button of the dialog. You need to make sure the user won't be able to close the dialog if there are unvalidated controls on the form. Since you don't have validation support anymore, maybe you can use the Tag property to store a False (for example) when the data is not valid. On OK just iterate over all textboxes and check their tags.
The behavior for the end user will ultimately be the same, you just have to write a bit more code.
Well, I found a way where I can keep using the Validating event and still be able to click the buttons in the other text boxes. It turns out that the Button.MouseUp event is sent even if a button doesn't have focus.
So the solution is to handle both the MouseUp as well as the Click event and perform the password masking/unmasking depending on whether the text box that contains the button currently has keyboard focus or not:
button.MouseUp += (sender, e) =>
{
if (button.Parent.ContainsFocus || e.Button != MouseButtons.Left
|| !button.ClientRectangle.Contains(e.Location))
{
return;
}
textBox.UseSystemPasswordChar = !textBox.UseSystemPasswordChar;
};
button.Click += delegate
{
if (!button.Parent.ContainsFocus) {
return;
}
textBox.UseSystemPasswordChar = !textBox.UseSystemPasswordChar;
};
We do want to handle both events, because if we only handle MouseUp, then clicking the buttons with the keyboard (Tab to switch to the button, and Enter or Space to click it) would not work anymore.

confirm messagebox only with mouse

I wrote an application, where the user filled in a form with some text and pressed enter when a textbox is filled. After this some checks were done and a nominal MessageBos with an OK-Button appeared. Some useres didn't read the messagebox, typed in as there were in the next textbox, pressed the OK-Button and the warning/error-message disappeared without reading.
I know, I cannot to control, that the user really read the message, but I want, that the usere use the mouse for conforming. Is there a way, that the Ok-button doesn't have the focus when the messagebox is shown ? Or do I have to write my Own Messagebox with an extra field, that has the focus.
While protecting users from themselves is typically a no-win endeavor, I would suggest that to do what you want would require you to construct a form of your own in which you could capture the keyboard input and disallow the dismissal of the dialog when the Enter key is pressed.

want to stop user input by messagebox but bypassed by a Enter keydown

I'm coding a windows form application running on a barcode scanner.
The plantform is .Net2.0CF/C#.
What i want is whenever user input wrong, the app will pop a messagebox and block the next input(actually,a scan action) until user click the OK on the screen.
But normally the user will continuously scan the next stuff as they didn't find anything went wrong, this will insert a Enter keydown so the messagebox will be closed, in one word, the messagebox does not stop the user.
How can i code this? Below is a very simple code snippet
private void tb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode.ToString() == "Return")
{
if(!ValidateInput(tb.Text))
MessageBox.Show("Error");
}
}
You can create your own window (Form) that displays the error message, but does not react on the enter key.
It should contain a button which the user can click (as you wrote), however you need to make sure the button does not have focus when the window is displayed. (Because if it had focus, pressing the return key will "click" the button.)
A simple way for doing this is adding another control which has TabStop set to true (e.g. a textbox, another button) and which has a lower TabIndex property than the button.
Additionally, maybe you might want to do a
System.Media.SystemSounds.Beep.Play();
when showing the window to draw the user's attention to the window.

Categories

Resources