OnMouseMove() event handler delegation - c#

I'm trying to write to a status bar the current mouse position and in order to that I took over OnMouseMove() event handler which is triggered when the mouse cursor enters my control. The problem is that in my control I have a WPF control which is has Dock.Fill Dockstyle, meaning, it fills the entire parent control.
When I run the applicaiton I see that nothing happens and the mouse position isn't updated, so I've noticed that the OnMouseMove() event of the WPF control is triggered and not the OnMouseMove() event of my control, which contains the relevant code for updating the mouse location coordinates.
I wanted to know if there's a way (other than implementing the code in the WPF OnMouseMove() event handler, of course) to bypass the WPF control event handler and use always my control's event handler.
I hope I was clear enough in my question, if not please let me know and I'll try to elaborate.
Thanks!

try the PreviewMouseMove-Version of OnMouseMove - this one should fire correct
and you need to have some kind of background (not null) or your controll won't see the mouse - so give it a transparent color or something)

Related

Sensitive border area between MouseEnter and MouseLeave events

I have a PictureBox control on my form for which I have written two events for MouseEnter and MouseLeave. On MouseEnter anther PictureBox enters the form and stands beside the original and with MouseLeave the second PictureBox goes way.
All works fine. Except when the cursor is on the original PictureBox’s border area the MouseEnter and MouseLeave events are repeatedly run. So the second image enters and leaves the form until the cursor is taken away. This makes a strange sight.
How can I avoid this situation?
The border area can be tricky, especially when you want to trigger something the might influence it even if it is only by a few pixels..
One classic situation is when you want to resize or move a control by clicking an dragging it at its border. Unless you use the internal calls and simply code mouseenter, -leave, -move, -down and -up you may well end up with e.g. moving the control away from the mouse and thereby triggering another leave event.
This often occurs only at one set of borders, like left&top or right&bottom.
You need to check you code for any such influences, like the new PictureBox pushing the old one away by a few pixels or a resize that makes it smaller; even one pixel can lead to the effect you see..
If the MouseEnter event is triggering a border to be drawn, or the size of the first PictureBox to change in any way, that can cause the effect you describe.
You could add a check against the mouse coordinates in MouseEnter to ensure that the mouse pointer gets far enough into the control's interior before the event fires. That would prevent an instant firing of the Leave event.

NotifyIcon MouseDown MouseEventArgs do not have location data

I have the following event handler for a NotifyIcon within a WPF application using Forms integration:
void MyNotifyIcon_MouseDown(Object sender, System.Windows.Forms.MouseEventArgs e)
{
ShowSettingsWindow();
}
However, e.Location = {X=0,Y=0} always. Is there a way to make this work?
Update
Oddly enough, people have voted to close this question and have downvoted it. However, its clearly not working and simple enough to create a new NotifyIcon inside of a WPF application's App.xaml.cs file and try it out for yourselves.
Update
As Hans pointed out, this is by design. It still doesn't answer the question of what possible workarounds are. Furthermore, this is a bad design, because:
This event occurs on a MouseDown, which means it should have some context of the mouse position when it was clicked in order for it to have occurred. The WmMouseDown handler for NotifyIcon does have the ref Message m property which other controls use to establish the correct position, however it seems to disregard this property and not use it in the event handler. I'd call this a major bug.
Since its post-mortem, getting the Cursor.Position inside of MouseDown will not give you the exact last location in which the MouseDown was raised after the tray icon is clicked. There is a small delay between you clicking it, and it raising the event in which you can further move the mouse. You can test this out yourself with an application that gets the mouse coordinates by quickly moving the mouse after clicking the tray and getting its location within the MouseDown handler. A workaround (which answers my question) would be to save the last location on every MouseMove using Cursor.Position instead and using this last location on MouseDown as the location that clicked the icon. All of which spells out a clear need for the mouse location of when the event actually occurred.
Apparently, I am the only one who cares about these inconsistencies in .NET while a lot of people seem to tolerate them or not understand their implications properly.
Its not ideal because the framework is designed to not send proper mouse event arguments as Hans pointed out, but one workaround is to save the last location on every MouseMove using Cursor.Position and using this last location on MouseDown as the location that contextually clicked the icon.
Have you considered setting a global mouse hook? It would bypass the typical WPF event model, and you would have to manually determine coordinates. This may involve additional API calls.
Details can be found in this post Global mouse event handler

Blocking sending events from child to parent

I have very short contact with the C# and WPF, although most of the stuff I could find over the Internet. However, I cannot find anything (or don't know how to request google to find it) about blocking sending events to the parent.
I've got an Image inside ScrollViewer. My point is to create zooming option for the image by using Ctrl + mouse wheel, but obviously the scrollbars of the ScrollViewer are moving while I am moving mouse wheel (the mouse wheel method is defined within the Image). Is there any possibility to block event sent from child to parent when Ctrl is down?
In your handler for the Image, you should set the event's Handled property to true when Ctrl is pressed. This will prevent the ScrollViewer from handling the mouse wheel event.
See http://msdn.microsoft.com/en-us/library/ms742806.aspx for more information, especially the section entitled "The Concept of Handled."

MouseEnter and MouseLeave Event not raising in user control

Here is the problem:
I have a simple c# form
I have a simple c# user control containing a picturebox and other button.
My form contains one instance of the user control.
I want that when the user do a mouseEnter in the picture box, the mouse cursor change and when the user do a mouseLeave of the picturebox, the mouse go back to normal.
What is happening now is that the events are not fired at all. I put break point into MouseOver, MouseEnter, MouseMove, MouseLeave, etc and none of thems fired. It's the first time I have this problem in C#.
I think it has something to do with the "routed event" but I can't figure it out. If there is another way to achieve what I'm doing, this will also be considered a solution. What is important is that at the end, the user control will be the master of the mouse cursor over his "territory".
Thanks in advance!
What events are you using? The UserController.MouseEnter and UserController.MouseLeave events or the PictureBox.MouseEnter and PictureBox.MouseLeave events?
You should use the latter as the PictureBox will handle the event if the mouse enters the user controller directly through the PictureBox.
As InBetween wrote, PictureBox.MouseXXX should be firing. You can trap those in your UserControl.
If you want the event to be fired on behalf of UserControl, just disable the PictureBox. Be aware though that the event would fire for any mouse position over the UserContrl, not only the PictureBox.

In WPF, how can I capture mouse on a Canvas and still find what controls the cursor is hovering over?

I have a custom Canvas control (inherited from Canvas) overlaid over a large area of User Controls. The idea is to draw paths between user controls (i.e. connector lines).
To capture mouse movement, I call Mouse.Capture(theCanvas) on MouseDown. This works beautifully, but the user controls under the canvas obviously no longer receive mouse events. Mouse.DirectlyOver always shows the canvas, so I can't really fake it by peeking at the current position and seeing which user control it's over.
So, I still need the Canvas for drawing paths, but how can I solve this one of the following ways:
Peek under the Canvas and see what the topmost control is right under it?
Get this MouseDown -> Track MouseMoves -> MouseUp workflow to work on the canvas without mouse captures?
Any other ideas welcome...
I'd agree that those are your two options. If you want to only forward some clicks to your usercontrols, then go with option 1, and hit test the controls under the canvas.
If you need your usercontrols to behave as though there is nothing covering them (textboxes, buttons etc), then i'd recommend using the PreviewMouseMove event on the user control's parent, as this can pick up and optionally "handle" events before the controls get at the event, but it won't block the event if you don't set handled to true

Categories

Resources