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.
Related
I have a UWP app in which I have several buttons. Once the app starts to run, I set the focus in my code to the first button using a code like this:
firstButton.Focus(FocusState.Programmatic);
After this point, what I am interested in is that once the user use the mouse wheel, the UWP app automatically scroll to second, third, fourth, ... button(exactly like when we use tab key on keyboard to move between buttons).
However, when I use mouse wheel, nothing happens in the app.
I should also say that in firstbutton xaml, I use pointerwheelchanged event listener to change the focus to second button. However, this event handler does not work with mouse wheel UNTIL I MOVE THE MOUSE CURSOR INSIDE THE AREA OF FIRST BUTTON. What I am interested in is that this scrolling using mouse wheel becomes automatic exactly like the tab key of keyboard.
Any suggestions?
Place the event on the container control (like the Grid). If it's a control that already processes the event, use the AddHandler method with handledEventsToo set to true.
I have written a custom Control, based on other code, which includes a call to SetStyle(ControlStyles.Selectable, false);
This prevents the following code from being called (which works if I remove the above line and click on the Control first to 'focus' it):
protected override void OnMouseWheel(MouseEventArgs e)
{
ScrollBar.Value = Math.Min(ScrollBar.Value - e.Delta, ScrollBar.Maximum - ScrollBar.LargeChange);
LayoutChanged();
}
My control does not need focus so Selectable=false is correct.
What do I need to do so that I can run this code whenever the mouse is over my control and the MouseWheel is moved regardless of where the focus is?
Thanks for the comments. A additional info:-
I am running Windows 7 but any solution must work on any OS.
The Control is inherited via Control/ControlBase/BaseControl/BaseStyleControl where the latter 3 are DevExpress controls.
The real focus should not be changed just because the cursor hovers over my control
There are no child controls other than a scrollbar (an inherited DevExpress one) which is normally invisible and shows itself when the mouse hovers over where it would be when visible.
The control does nothing but draw itself (imagine a number of bookshelves one under the other with book covers drawn on them - the number of shelves increases to accommodate all the books and the scrollbar allows all to be scrolled into view.
Since this is a use-anywhere Control, getting MouseWheel events from a Parent that knows about its requirements isn't a good idea.
Maybe there is a way of registering for a first-look (is that a MessagePreview?) to pinch MouseWheel events before normal processing happens.
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 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?
In Excel, middle mouse button click work as a toggle. That is, if you press it once, it will allow you to scroll in your chosen direction till the time you click it again.
However, in Infragistics Ultragrid, this scrolling functionality is available only while middle mouse button remains pressed. How can I make Infragistics Ultragrid middle mouse button click work as in excel?
Otherwise also, what is the way to do it in winforms?
It's not as complicated as you might think. Clicking either the mouse wheel or middle button (depending on the type of Mouse the user has) fires off a MouseWheel event which must be handled and processed like any other event.
You'll need to configure a small "scrolling state machine" for you application. By this, I mean that the user is either scrolling in, say, a NormalMode, where using scroll bars or flicking up/down on the mouse wheel produces the same effect (scrolling up/down). Or, the application is in a HoverScrollingMode which occurs whenever the user has clicked the middle button (or mouse wheel) and is moving the mouse north or south of the click point.
I can't give you a programming example without seeing how your application currently handles other types of mouse events, but your overall strategy is to handle these MouseWheel events, use them to switch your application state (into, say, HoverScrollingMode) and then programmatically move the viewport up/down depending on the current position of their mouse.
Hope this helps, and good luck!