Dev-Picayune

picayune: of little value or importance

C# and Mouse Events

I had hoped to get onto more important tasks tonight. Instead I wasted hours of my time because of quirks in the way that C# or .NET handles mouse and other events. I only thought I was leaving those things behind me with Clarion.

Again, this all goes back to the fact that I am trying to essentially simulate a button without using a button (since buttons can become a selected or default control which is what we DON’T want on a toolbar) and because I want to be able to change the size of the image easily (scaling it up and down with mouse overs).

My original plan that seemed to be working so perfectly was to change the border of the PictureBox control on a MouseDown event to a type Fixed3D or FixedSingle to show that the control was being clicked on. This worked wonderfully, even allowing me to correctly detect the MouseLeave event if it occurred before the mouse up (so I could act accordingly). Unfortunately, there is slight flaw or some sort such that if you clicked on where the outer edge of the frame was going to appear, it would never notice the MouseUp or MouseLeave events and you end up with a stuck icon until you pass over it again with the mouse. I thought about not worrying about this slight defect… but I knew that it would bother me if I never fixed it or found a way around. 3 to 4 hours later I have a solution of sorts.

What didn’t work was making a panel first and then placing the picturebox in the panel. I could then effect changes on the panel’s border by referring to the picturebox’s .parent property. The effect was similar but then I lost my MouseLeave event until after getting the MouseUp event (as it turns out… if you don’t change the border on the MouseDown, it will always fire events out of order like this — holding the MouseLeave until after the MouseUp no matter what). The other problem was that then I had twice the controls to keep track of and deal with and there were some odd sizing issues where the panels would grow or overlap… a real mess. So I scrapped that. I also tried changing the client rectangle area property as I was changing the border to possibly avoid the side-effect but that didn’t work either — still would get stuck. I also tried dozens of other bizarre little tweaks trying to figure out a magic combination that would work around it.

What I have decided on for now is actually a little better for skinning. The PictureBox object supports both an Image property and a BackgroundImage property.

The flow, now is MouseEnter — we enlarge the icon to the full size of the PictureBox just like always. On a MouseDown we shrink down to a centered image but we also set the background image on the icon to a specified background (for my testing I created a shaded box the size of the PictureBox). This gives the effect that we a clicking on the button with a nice border around the icon (and it can look like anything we want since it will be an image file). On a MouseUp I just return back to normal (no background) and an enlarged Icon again (assuming we are still over the PictureBox).

Since I am no longer changing border styles, I fail to get a MouseLeave if the user clicks and holds and then moves the mouse off the control. This means I now have to capture all the MouseMove events. If I detect that the user is leaving the bounds of the control with the button down I call my MouseLeave event with my current parameters. Then I also detect a MouseMove coming back into the control with the button down — calling the MouseDown code again. It isn’t 100% right yet but it has way fewer side-effects than anything else so far.

No comments yet. Be the first.

Leave a reply

For spam filtering purposes, please copy the number 3986 to the field below: