StrataFrame Forum

MouseMove event with mouse button pressed

http://forum.strataframe.net/Topic23910.aspx

By Greg McGuffey - 7/23/2009

I'm about to start drinking (Fresca of course) over this one.



I have a little sample app were I'm attempting to create a control from scratch (i.e. just inherits from System.Windows.Forms.Control) and do all the drawing myself. I currently have code that handles mouse down and if the left button is pushed, I redraw the control, then when the mouse moves up, I redraw again. So far so good...



Until you leave the left mouse button presses and move the mouse OFF the control. Like way off. Like off the form. Like into next week. When the mouse leaves the control, that control continues to get MouseMove event. No mouse events are fired for any other control until the mouse button is released. No mouse leave, not mouse enter on another control, just MouseMove off into the ether.



What I was kind of hoping for would be either:



1. At least the MouseLeave event would fire if the mouse left the control...jeesh.

2. Or the MouseUp would be raised, the MouseLeave on current control, then MouseEnter then MouseDown....something like that.



So, anyone know about this or how to handle it?
By Trent L. Taylor - 7/23/2009

Yup....a couple of things. First, when you are doing this, you will want to override the OnMouseLeave event...that will handle this. Handling the event will not get the job done at this level in most cases.



Second, if you inherit off of the SF StrataUserControlBase class, it will double buffer using a buffer context (totally 100% kills flicker) without actually using the not so reliable Doublebuffer.



It would look like this on the declaration:



public class MyClass : MicroFour.StrataFrame.UI.Windows.Forms.StrataUserControlBase




Next, override the OnPaintBackground and put a comment and remove the base call (unless you are going to support a transparent background). Reduces flicker as well. After this, override the OnStrataPaint event, it will hand off the buffered graphics object and from that point forward the rest is the same...but we will do all of the context buffering behind the scenes so you never have to worry about the flicker (which will happen eventually). Wink
By Greg McGuffey - 7/23/2009

wow, thanks. As I said this was a learning project, so I went way down the food chain. But I do have flickering. Pinch I'll likely attempt to do some stuff with plain .NET to fix it to learn about it, but I'll be checking out the StrataUserControlBase class for any real work!



However, I am overriding the OnMouseXXX methods. I "log" the event to a text box and when the mouse button is down, the only control to get any mouse events is the one were the MouseDown event occurred. Not only are none of the other controls raising any mouse events, but the mouse events keep going outside of the form!



I've attached a sample app to demonstrate this.
By Trent L. Taylor - 7/24/2009

OK, a couple of things that may make life easier. First, I misunderstood what you were trying to do (I think). Learning to program mouse logic is one of the more frustrating things that one has to do when creating a complex control. Now if there is just one action, then it isn't that big of a deal, but the more complex and more elements that you get, then the more structured it needs to be otherwise you will NEVER be able to debug a faulty mouse click.



In this example, the mouse should no longer be handled it not within a valid region:



if(this.ClientRectangle.Contains(e.Location))

{

this.WriteLog(string.Format("MouseMove ({0}) [{1},{2}]", e.Button, e.X, e.Y));

base.OnMouseMove(e);

}




By making sure that the mouse is within a valid region (in this case I just used the bounds of the control) then it should not do anything. Also, within a move, you might need to know if a mouse was down on a object previously. When you create a control like this that will have internal contents (i.e. a block in this case) you are going down the right path in that you do not want to use another object, but you DO want to create a collection that manages itself with the items. This way each item is responsible for "knowing" where it is making mouse logic easy when clicking.



I added a new control called TrentMouseControl (or something like that) that creates an internal collection to keep up with the items as discrete blocks that know their location. I just handled the OnMouseUp event to show a click event, but the same logic would be used for a MouseMove.
By Greg McGuffey - 7/24/2009

Thanks for the info and sample. I'm trying to grok it now.



However, I can't run it. I don't have SF 1.7.0. Ermm



I guess this means it is coming out soon! w00t
By Greg McGuffey - 7/24/2009

Oops...

Er...never mind. I did a rebuild and it runs now. Blush



Next Question

I had no idea programming the mouse would be such a pain in the...er...posterior. I see how you are checking if the mouse is in the client area and only then actually raising the event. However, no events get raised on any of the other controls. It looks like .NET won't redirect mouse events to any other control while the mouse button is being pressed. Is that right? Any way around that (if I'm understanding it correctly)?



Comments

There's lots of good stuff in there:



- using [ ... ] in regions so they aren't all scrunched up. BigGrin



- Overriding OnInsert/OnRemove/OnClear with collections. I tried to create a custom dictionary were I could add some logic when an item was added/removed etc. and couldn't figure how to do it. This is the way. Very cool. Cool



- Rendering improvements. OK, so maybe the StrataUserControl is a better way to go Wink You can really see how much better you control behaves from mine. Nice.



- Handling rendering of a collection of objects. I wasn't even going there, I just wanted a bunch of the same control to see how events were handled. However, this shows how to do that and it doesn't seem that bad to render. I don't think I would have gotten it before having done a single control, but this actually makes sense.



Thanks! I might be back with more questions! BigGrin