Advertisement Jump to content
Sign in to follow this  
satsujin

Custom mouse event for custom class

This topic is 1882 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have looked online for custom events and have been a little confused by the example code. Many of them seem to set to set the event as the changing of a variable. This is a one time event. But what if you want to check for an event that could be true at any time?

 

I have a custom texture class that has a boolean function isClicked that returns true if the the texture has been clicked onscreen. I am using this in XNA so I constantly check if this this function returns true or not. But is there any way to create an event handler that will run a function when this has been clicked without constantly polling the function. If I have multiple textures onscreen this could affect performance so I would like to know if I can have an event handler that will fire without always running the the isClicked function? I doubt this is possible but just wanted to test the waters.....

Share this post


Link to post
Share on other sites
Advertisement

One way to do it is by using virtual functions. For example, in my 3d engine, i have this base class

class CVortez3DEngine {
// LOT of stuff removed ...
public:
    virtual void OnMouseMove(int x, int y){}
};


Then, in the message proc. i just call the function normally, which does nothing for now...

	...
        // Mouse move messages
	case WM_MOUSEMOVE:
		pVortez3DEngine->OnMouseMove(LOWORD(lParam), HIWORD(lParam));
		break;
        ...

So, to use those virtual function as events, all i need to do is to override the method in a derived class

class CVortez3DEngineEx : public CVortez3DEngine {
...
public:
    	void OnMouseMove(int x, int y);
}

So, whenever i move the mouse, this function got called automatically, instead of the default one in CVortez3DEngine.

void CVortez3DEngineEx::OnMouseMove(int x, int y)
{
    // do stuff with x and y
}

I dunno if that's the best way to do it, but this work very well.

Edited by Vortez

Share this post


Link to post
Share on other sites

I suppose what you are looking for is a delegate. Just google C# delegates, its pretty much an event where you register one or multiple function pointers. Then, when the texture is clicked you fire that delegate, and the registered functions are being called. Thats a pretty common idiom used specifically for gui-stuff, as you mentioned polling isn't really that great an option here.

Share this post


Link to post
Share on other sites

Vortez thanks for sending me your SDK but you are attaching your MsgProc function to your lpfnWndProc parameter of your Window class. I am doing this in C# XNA so I don't know what the equivalent  for that would be in the XNA framework.

 

Juliean, you say when my texture is clicked the delegate would fire its attached function. But how would I know if the texture has been clicked without constantly polling a function to see if Mousedown has occurred within the bounds of the texture?

Share this post


Link to post
Share on other sites

Here are some excerpts of my code:  

public class MainMenu : Screen
{
        public override void LoadContent()
        {
            
            position = new Vector2(100, 150);
            start = new MyTexture("Textures/Start",position,this.gameController);
            start.ClickEvent += new EventHandler(this.MoveText);
   
        }
        
        public void MoveText(object sender, EventArgs e)
        {
            MyTexture t = (MyTexture)sender;
            Vector2 newpos = new Vector2(start.position.X + 50, start.position.Y - 50);
            t.Move(newpos);
        }
}

class MyTexture
    {
        public EventHandler ClickEvent;

        public void ClickHappened()
        {
            if (gc.inputController.Clicked())
            {
                if (bounds.Contains(gc.inputController.currMouseState.X, gc.inputController.currMouseState.Y))
                {
                        if (ClickEvent != null)
                            ClickEvent(this, null);
                }
            }
        }
}

What is dont understand is how to trigger ClickHappened without constantly polling it. If I have to always poll it then I wont need an event handler, I can just turn it into a bool function and call MoveText if it returns true;

Edited by satsujin

Share this post


Link to post
Share on other sites
What is dont understand is how to trigger ClickHappened without constantly polling it.

Use the C# Window events. And, instead of checking whether the controller has been clicked, and the mouse is inside the boundings, have an event handler that checks all UI widget elements and calls the correct function, like ClickHappened (I'd rather call it OnClickHappened, but thats just a matter of taste). Also, IMHO even if you where doing nothing but polling in the background, having a delegate event for handling the actual response for things like the texture being clicked is still better than applying polling at that level too. My GUI event handler works as kind of a hybrid, I set states in my input manager whenever an event happens, but then I query those states via polling whenever the event handler is being updated.

 

So some pseudo-code might look like this:

class EventHandler
{
	public OnMouseClick() // this gets assigned to the window mouse down event
	{
		foreach(MyTexture texture in textureList)
		{
			if(IsInside(texture, mouseCoordinates)) // helper function to check if the mouse is over some widget
			{
				texture.OnClicked();
				return; // assuming painters algorythm is used, we'd have to traverse the list backwards actually so that the only topmost widget that can recieve the event gets it
			}
		}
	}
}
Edited by Juliean

Share this post


Link to post
Share on other sites

This was just a test example. For my game, MyTexture would be extended into a GameEntity class and each one would be polled in the current Screen class's Update loop to see if it had been clicked. I don't get what you mean by using C# Window event. What I am doing is currently within an XNA framework so I don't know if it applies since I don't have access to a Window object.

 

Also, a disadvantage of using the += operator for assigning anew method is that I can't change it without using -= on the previous method and for that I need to know the method's name. This could probably be solved by using a delegate in MyTexture and simply assigning/changing a method name as needed.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!