I am working on an application that uses a PictureBox to display an image. When the picturebox has the focus I have implemented several shortcut keys to manipulate the image; scrolling, rotating, zooming, etc. The problem is, there is no indication to the user that the image HAS the focus. Looking over the properties of the PictureBox I cannot see any event linked to losing the focus.
I can check the keydown event to GIVE the focus to the box, and then change the border or background or whatever to indicate that the PictureBox has focus, but I cannot find a way to tell when the focus LEAVES the PictureBox. The only focus related Events seem to be "Validating" and Validated".
Is there something I am missing here?
Related
I am currently using MSCharts in one of my windows forms. One of the quirky things about MSCharts is that you cannot trigger a MouseWheel event in the chart unless the chart has focus. To combat this, most people are saying that one should add a MouseEnter event to the chart and then Focus() the chart to allow one's MouseWheel events to fire (see here: Enabling mouse wheel zooming in a Microsoft Chart Control).
Let's say that I pull up a completely different window (call it Window A) that just so happens to be partially in front of my chart (call it window is Window B). If I accidentally move the mouse over the chart in Window B for even 10 milliseconds, Window B will take focus and Window A will be placed behind it, which is incredibly frustrating.
I've explored different options.
Setting Window B's TopMost property to true. The problem with this is that the user has to either close the window or minimize it to hide it. If there are a lot of windows up, it seems to be just as frustrating as the initial issue.
Instead of giving the MouseEnter event the ability to Focus(), let the MouseClick or MouseHover event to Focus(). The problem with MouseClick is that the user will always have to click on the chart first to zoom, which isn't bad, but can be annoying. MouseHover is okay, but the time that the event considers to be a hover is really short.
In the end, I want it so that I can put my mouse over the chart and scroll in without having to do anything (mouse clicks, or anything else). In addition to this, I don't want the form that contains the chart to jack the focus back to it if I accidentally move my mouse over it for just a second.
EDIT:
It seems that according to #TaW, the chart doesn't need focus to trigger MouseWheel events in Window 10. This is not the case in Windows 7, unfortunately.
This may seem slightly hacky, but it works in this case:
This works through the use of the FindForm method. I never knew it was a thing until now. You can read more about it here: https://msdn.microsoft.com/en-us/library/system.windows.forms.control.findform(v=vs.110).aspx
myChart.MouseEnter+= delegate(object sender, EventArgs args) //add a mouse enter event to your chart
{
if (!chart.Focused) //if chart isn't focused
{
if (chart.FindForm().ContainsFocus) //check if the form the chart is in contains focus
chart.Focus(); //if the chart isn't focused, but the form is focused, focus on the chart
}
};
This will still give the chart focus when you move your mouse into it and it will not allow the form that contains the chart to jack the focus from the form you're in.
Screen of my user control
I have an user control (black rectangle) that contains some controls.
When the mouse is hover the user control, I want to show the two images in the red rectangle.
At the moment I have implemented the mouseEnter (show the images) and mouseLeave (hide the images) events from the user control.
The problem is that when the mouse is hover another control (a label for instance), the mouseLeave event from the user control is fired and the images disappear.
I could implement the mouse enter / mouse leave events for all the controls but it seems a waste of time, lots of code deduplication and a poor usage of memory.
I also thought about disable events for the other controls, but not sure how to do it and it seems to be more of a hack than anything. Il tried to disable the controls but the color changes and again, a dirty hack.
Maybe I can prevent the user control mouseLeave event to be fired if the mouse is hover one of its control ?
I'm sure there is a proper way to do it, but cannot figure it out.
If anyone thinks about a better title, I will change it.
Thank you for your help,
Regards
Thank you very much both of you.
You pointed me to the right direction.
I ended up to simply register the ControlUser.MouseEnter event to all controls by doing :
foreach (Control control in Controls)
{
control.MouseEnter += new EventHandler(this.MyUserControl_MouseEnter);
}
Simple and efficient, this is perfect.
I have a custom ZoomBox control based on ScrollableControl which controls its scrollbars through AutoscrollMinSize property.
I would like to be able to handle WM_MOUSEWHEEL events to adjust control's Zoom.
I made necessary steps to make sure that the control receives the mouse events even when it is not in focus, by filtering them on the parent form.
It seems though that the events only reach the OnMouseWheel method if the control does not have its scrollbars active. If it does, it appears that the mousewheel events are being redirected to the scrollbars which handle them (by scrolling).
I would like the scrollbars to be there but only be controlled in a "traditional way", i.e. by dragging the slider or clicking on arrows etc. and handle the wheel myself. Is it possible to achieve that?
Inherit from the ScrollableControl in question and override OnMouseWheel(). In that method don't call base.OnMouseWheel().
As far as I can tell there's no other way to stop ScrollableControl from scrolling if the scroll bars are present.
A side effect is that you will no longer get MouseWheel events. Fixing that is another question. Conceptually you want to call base.base.OnMouseWheel().
Currently in my application I am using the HScrollBar and VScrollBar for panning around in a large image. The part of the image that is shown is based on the scrollbar's Value property. However, when resizing the SplitContainer or resizing the form window the scrollbar's Value does not automatically update and it may render something off-screen.
At this point I noticed that if you clicked the scrollbar's arrow it magically fixes the scrollbar. I was wondering if there was any way to simulate clicking the scrollbar to do this in the Form_Resize and SplitContainer_Resize event handlers but I couldn't find anything.
Having to manually adjust the scrollbar's value in all resizing events is slow, ugly, and doesn't work well. I'd really like for the scrollbar to just automatically fix itself when the window resizes like it does when you click its arrow but I'm not sure how.
Try calling the scrollbar's Invalidate() method in the form's resize event handler:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invalidate.aspx
That should cause it to redraw correctly after the form is resized.
Use something like this:
HScrollBarObject.SetStyle(ControlStyles.ResizeRedraw, true);
I'm trying to create User Control which will work like a rich button.
It's supposed to have an effect on hover - I turn border on on MouseEnter and off again at MouseLeave.
BUT, when I hover over label in my control, it fires Control.MouseLeave.
Is there any way to prevent this?
First, focus Enter and Leave are different events than MouseEnter and MouseLeave. Focus deals with keyboard input. MouseEnter and MouseLeave deals with where the mouse is right now.
Entering a nested control fires MouseLeave on the parent control. You can capture the mouse by setting the control's Capture property to true, but you may find that doesn't behave like you'd expect.
You might look at my post here. I had the same issue with nested controls. I opted to create a .NET equivalent of a mouse hook by calling Application.AddMessageFilter.
Another option would be to remove the inner label control and draw the text manually it in the button's OnPaint.