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);
}
}
Related
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.
So i have a UI that when you right click on a button, it opens a screen with 3 other buttons on it. How do i get the event system to not override the last button clicked (being what i right clicked to open the screen) when i click down on the button that is opened. The only way i can think to do it is to store the button that was right clicked in another variable. I was wondering if there was a way to prevent the event system from overriding the last button pressed. So that my code will run off what was right clicked and not the button that was clicked.
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.
Within the application I am writing for testing/learning C#, I use the hidden/visible property to open and close windows.
It is a WPF application.
In the main window, I have a "close" button that triggers this method:
public void buttonQuit_Click(object sender, RoutedEventArgs e)
{
var message = exitmessage;
var title = exitTitle;
var result = MessageBox.Show(
message, // the message to show
title, // the title for the dialog box
MessageBoxButton.YesNo, // show two buttons: Yes and No
MessageBoxImage.Question); // show a question mark icon
// lets see what has been pressed
switch (result)
{
case System.Windows.MessageBoxResult.Yes: // Yes button pressed
CloseAllWindows();
break;
case System.Windows.MessageBoxResult.No: // No button pressed
break;
default: // Neither Yes nor No pressed (just in case)
MessageBox.Show("Oh noes! What did you press?!?!");
break;
}
}
This way I make sure that all windows get closed, including the hidden ones.
But now is the catch; when the user presses (in the main window) the top right red X in toolbar to close, only that main window gets closed, but in the background the hidden ones are still there.
So in fact it is 2 questions:
Is CloseAllWindows(); really sufficient to get the app 100% closed down?
How do I "catch" the event when the user presses that red X in the toolbar, and make this also trigger the right closing event?
You should be handling either the Closing or Closed event for your window(s). The former allows you to cancel the close, while the latter just allows you to perform necessary cleanup in response to the window being closed.
So, in this case, you should place the code from your buttonQuit_Click method into a handler method attached to the Closing event so that it gets triggered regardless of how the window is closed.
Then, your buttonQuit_Click method can simply call the window's Close method. That will close the window, in turn raising the Closing event, and running your code in the attached handler method.
As far as your other question, CloseAllWindows will do exactly what it says: it will close all of the windows that your application has opened. In most cases, that should be sufficient to close the application, but it might not be, especially if you've created non-background threads or depending on the ShutdownMode setting.
App.Current.Shutdown will work unconditionally.
You could use the Closing event of the window for that.
Some more info
http://msdn.microsoft.com/en-us/library/system.windows.window.closing.aspx
I am trying to use a C# WinForms combobox in the following manner:
a) regular use: if the "Down arrow" button is pressed, the dropdown area opens and the user selects the desired item - no problem there..
b) advanced use: if the user clicks into the editable are of the dropdown control, another dialog with advanced selection mechanisms opens.
Currently, I am calling the advanced dialog in the combobox's onclick event handler. However, now the regular use of the DropDownbox is not usable any more. The advanced dialog is opend even if you click only on the dropdown arrow.
I couldn't find another likely event that I could use, so I assume that I have to check in the eventhandler if the user clicked into the control's editable part or on the control's button. Any ideas how to do that effectivly?
Thanks for all hints.
There are two events of interest; DropDown and Click. Handle DropDown in the "normal" way. For Click, you might actually try handling MouseDown, which includes coordinates. Turn those coordinates (which are based on the cursor's position on the entire screen) into the position relative to the control, and if the mouse is currently on the arrow portion of the control, simply exit and allow the default behavior to happen. Otherwise, show the more advanced dropdown.
I did it (not so beautiful but it works)
void comboBox_Click(object sender, EventArgs e)
{
// Calculate cursor position
Point pointCursorLocal = this.PointToClient(Cursor.Position);
// Calculate rectangle of working area.
Rectangle rectangle = this.comboBox.Bounds;
rectangle.Size = new Size(rectangle.Size.Width - 10, rectangle.Height);
// Check them
if (rectangle.Contains(pointCursorLocal))
// CLICK ON WORKING AREA ...
}