Good day to all!
I write my own GUI-interface for the toy.
Class Button .
There is the following set of delegate events:
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; // ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π΄Π»Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΡΡ
ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°Ρ Π½Π° ΡΠΏΡΠ°ΠΉΡΠ΅ ΡΠ΅ΠΊΡΡΡΡΡ ΠΊΠ½ΠΎΠΏΠΊΠΈ Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π΅Π΅ ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ } Appropriate methods are present for other delegate events. In the same class, there is the Update() method, which 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:
Button button = new Button(...); Respectively properties, textures, etc. are set. It all works. Further, in the same "other place", the delegate is assigned a method:
button.MouseInHandler += ΠΠ°Π·Π²Π°Π½ΠΈΠ΅_ΠΌΠ΅ΡΠΎΠ΄Π°; With this, I think everything should be clear. The logic is briefly - an object is created, a method is assigned to it in a special delegate, after which the Update() method checks if the button and cursor intersection, clicked, etc. and based on this, the event we need is already triggered.
The problem that exists now: the method is called not once, but many times in a row.
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 using additional fields:
private bool _isMouseUp; private bool _isMouseDown; private bool _isMouseIn; private bool _isMouseOut; With a change in the logic structure 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 MouseDown and MouseUp corresponding changes.
And it all works, as long as the user behaves normally. However, if you try different situations, for example, hold the paint button, then move the button and release, or hold the paint button over the button and release it in another place - all this leads to the fact that at some point an event that should it was to be called - not called, or vice versa, that event is raised, which should not be called.
I tried to describe my problem in as much detail as possible, but if there are any questions, ask, clarify if necessary.
Debug.WriteLine("ΠΡΠ»ΠΎ ΡΠΎΠ±ΡΡΠΈΠ΅ Π½Π°ΠΆΠ°ΡΠΈΡ Π½Π° Π»Π΅Π².ΠΊΠ»Π°Π²ΠΈΡΡ"), etc.? It seems that somewhere along with a subscription to an event there is a need to unsubscribe from it, although I am not sure. - BulsonRoutedEventevents and there you can stop further downward or upstream calls of events in the event handler. It looks like you need to implement something like this. - Bulson