Getting a mouse click through (spurious click)

I’m getting a ‘click through’ with the mouse. Here’s an example: I created a file menu system:
Screenshot 2023-06-22 133606
I click on ‘Save Scenario’ and it saves the file and reports:


But notice that I’m getting a ‘false click’ on the icon (the soldier with the binoculars) and that report is now selected (notice the arrow indicating this report is ‘active’).

I’m calling this in Update()

            // The active state from the last frame is now old
            lastMouseState = currentMouseState;
            currentMouseState = Mouse.GetState();

            ms = Mouse.GetState();

Do I need to do something else to ‘clear out’ the mouse click?

You’ll need something to indicate that the “click” event has been handled. Not sure how your code is structured but if it’s in the same method you might have something like this…

bool mouseClickHandled = false;

if (Mouse.GetState().LeftButton == ButtonState.Pressed && mouseClickHandled == false)
{
// code here
mouseClickHandled = true;
}

Okay, so there isn’t any MonoGame mouse handling that I’m doing wrong. I should just set another boolean?

I haven’t seen your mouse handling code in full, so I doubt it.

If you have multiple objects that could be clicked on that are stacked, you need to keep track of the Z order of items so that the click goes to the correct object and then make sure all other objects don’t handle the click too. You can do that with a variable as I described above. Where that variable is depends on how you structured your code.

Generally speaking if you check only the x,y position of the mouse when a click happens, any control that is below will do the same check so all of them will trigger.
There are many solutions for that, some are easy, some are more complex:
1- Easy level : Make sure that no other control is below the one you show on screen at a given time so no overlap will happen.
2- Complex level: If you cannot do #1, then you will need to keep track what control is on top so only that one will process the click and the others will ignore it, there are many ways to do this too, but if you overlap controls in windows and so on, you will need to keep track what is on top, a hierarchy list so you know what is on top, I think you may have some sort of this since you know what controls are going to be displayed and where, since you are using the very old style of menus for games, like in the Atari ST or Amiga era, you can use your drawing order as a guideline, if any control processed a click, then any other control should not process a click until the flag is reset in the next update cycle.

I would say, try to change your menu or layout, so you won’t have to keep track of the hierarchy, if it is only happening when saving the game. If you have overlapping windows then you will need to keep track of the hierarchy.

Also to add, there must be a heirachy for the drawing order. Perhaps you can reverse that heirachy for reading the correct click.

Having made a ui with scrollable listboxes inside panels which where inside other panels and multiple moveable popups which used a parent child relationship you do need to keep track off what panel is focused.

Deoending on how you design it you could make it so all other ui elements wont even respond to a click until you have removed the focus off your messagebox (clicked okay)

Another way to do it, only have an isFocused flag. When you move your mouse calculate which one is focused and input only effects the focused one.

This comes in handy when you have multiple panels open that can enter text. You only will do your text entry on the focused panel

I use system similar to JavaScript - event’s stop propagation.

Place some bool in the global scope:

public bool PropagateEvent { get; set; } = true;

Always at the start of update() method in global scope set it to true. Then if you want to block propagation, simple set it to false on some input action (like click):

if (mouse.LeftButton == ButtonState.Pressed) {
    // Do some action on click

    // Set propagation to false
    PropagateEvent = false;
}

Then on all events that you don’t want the propagation, simple check for that bool. So modify the function above to something like:

if (PropagateEvent && mouse.LeftButton == ButtonState.Pressed) {
    // Do some action on click

    // Set propagation to false
    PropagateEvent = false;
}

Making it this way, you are sure that nothing will trigger other events if you block event propagation. Just remember that the order is important. First function/statement that will block event propagation will block next ones from executing event. Example:

update() {
    PropagateEvent = true;

    // We pressed Left Mouse Button

    if (PropagateEvent && mouse.RightButton == ButtonState.Pressed) {
        // Nothing will happen, cause we pressed left button, not right
    }

    if (PropagateEvent && mouse.LeftButton == ButtonState.Pressed) {
        // This statement will be triggered
        // Do some logic on click
        // ...
        // Disable event propagation
        PropagateEvent = false;
    }

    if (PropagateEvent && mouse.LeftButton == ButtonState.Pressed) {
        // This won't execute, cause event propagation (PropagateEvent) is set to false
    }

    if (mouse.LeftButton == ButtonState.Pressed) {
        // This will execute, cause we don't check event propagation (PropagateEvent)
    }
}

The Code you posted about retrieving the mouse state has nothing to do with the matter. It only tells you the mouse state in each call of it. It’s on you how you handle that information.

As other stated, you may want some mechanic to determine if a mouse click has been consumed or not - and that depends on how you handle it in your game.

I assume you already determine correctly if a “click” happens and not just checking if a button is currently pressed

Okay, I got it! I don’t know why I thought that MonoGame would somehow ‘consume’ the click. But, yeah, I can easily deal with it via a boolean.