Y
Y
Yoshinon Eared2016-11-06 20:23:13
Programming
Yoshinon Eared, 2016-11-06 20:23:13

Mouse events and prohibition of method execution more than once?

Good day to all!
I am writing my own GUI interface for a toy.
class Button.
We have the following set of event delegates:

public event EventHandler MouseUpHandler;
public event EventHandler MouseDownHandler;
public event EventHandler MouseOutHandler;
public event EventHandler MouseInHandler;

Each event has its own method:
private void OnMouseIn() {...}
private void OnMouseOut() {...}
private void OnMouseUp() {...}
private void OnMouseDown() {...}

They run something like this:
private void OnMouseDown()
{
    EventHandler tempHandler = MouseDownHandler; // получаем делегат события
    if (tempHandler != null) // проверяем, не пустой ли делегат
    {
        tempHandler(this, EventArgs.Empty); // вызываем событие
    }
    _state = ButtonState.Click; // используется для определения правильных координат на спрайте текстуры кнопки во время ее рисования
}

Corresponding methods are present for other event delegates.
In the same class, there is a method Update()that calculates the logic of the code:
public void Update()
{
     /* Формируем данные о положении мыши и о зоне пересечения (на основе позиции и размеров кнопки) */
     MouseState mouseState = Mouse.GetState();
     Point mousePosition = new Point(mouseState.X, mouseState.Y); 

     Rectangle buttonRectangle = new Rectangle
     (
        (int) this.Position.X, (int) this.Position.Y,
        (int) this.Size.X, (int) this.Size.Y
     );

    if (buttonRectangle.Contains(mousePosition)) // проверяем на наличие пересечения курсора мыши и кнопки
    {
        if (mouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed) //ЛКМ - нажатие кнопки мыши
        {
             OnMouseDown();
        }
       if (_mousePrevState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed && mouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Released) // ЛКМ - отпускание кнопки мыши
       {
            OnMouseUp();
       }
    }  else // выход курсора за границы кнопки
    {
         OnMouseOut();
    }
    _mousePrevState = mouseState; // сохраняем предыдущее состояние (MouseUp может быть только после MouseDown)
}

In another place, an instance of the button is created: Properties, textures, etc. are set accordingly. All of this is functioning. Further, in the same "other place", a method is assigned to the delegate: With this, I think everything should be clear. The logic in brief - an object is created, a method is assigned to it in a special delegate, after which it is checked in the method whether there was an intersection of the button and the cursor, whether there was a click, etc. and based on this, the event we need is already called. The problem that exists now: the method is called not once, but many times in a row: if the mouse is not hovering over the button, the event is constantly called , when hovering - , when the button is pressed and lowered, the corresponding events are fired.
Button button = new Button(...);
button.MouseInHandler += Название_метода;
Update()
OnMouseOut()OnMouseIn()
All this leads to the fact that, for example, the output to the console of any text occurs many times, but no more than one is required.
I tried to solve the problem with additional fields:
private bool _isMouseUp;
private bool _isMouseDown;
private bool _isMouseIn;
private bool _isMouseOut;

With a change in the structure of the logic of event methods:
private void OnMouseIn()
{
    if (!_isMouseIn) // если событие не вызывалось 
    {
         EventHandler tempHandler = MouseInHandler;
         if (tempHandler != null)
         {
              tempHandler(this, EventArgs.Empty);
         }
         _isMouseIn = true; // определяем событие, как вызванное и не даем ему совершиться повторно
         _isMouseOut = false; // после In события можно допустить выполнение Out события
    }
    _state = ButtonState.Hover;
}
// примерно такой же код ниже, разве что теперь Out и In поменялись местами
private void OnMouseOut()
{
    if (!_isMouseOut)
    {
         EventHandler tempHandler = MouseOutHandler;
         if (tempHandler != null)
         {
              tempHandler(this, EventArgs.Empty);
         }
         _isMouseOut = true;
         _isMouseIn = false;
    }
    _state = ButtonState.Normal;
}

For MouseDownand MouseUpcorresponding changes.
And all this works, as long as the user behaves normally. However, if you try different situations, for example, hold down the LMB, then point at the button and release it, or hold the LMB over the button and release it in another place - all this leads to the fact that at some point this or that event, which should was to be called - not called, or vice versa, the event that should not be called is called.
I tried to describe my problem in as much detail as possible, but if there are any questions, ask, I will clarify if necessary.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
T
tex0, 2016-11-07
@tex0

Put a break in the place where you subscribe to the event
and see how many times this happens.
This is a common situation when, in one context, an event was subscribed, but they forgot to unsubscribe, and therefore the invocation list of the event is filled with unnecessary handlers.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question