C# WPF - MouseLeftUp Event doesn't appear to fire [duplicate] - c#

On System.Windows.UIElement there is a CaptureMouse() and a paired ReleaseMouseCapture() method. In this WPF DragDrop sample they call CaptureMouse on MouseDown and release it on MouseUp. The documentation in MSDN is about as useless as it comes - "CaptureMouse -> Captures the mouse."
In my head before trying it I assumed that it somehow locked the mouse inside the UIElement bounds, but that's clearly not the case when I try it. From experimenting, it seems to have something to do with responding to events when the mouse is outside of the UIElement, but not wanting to be a cargo cult programmer I don't want to just use it because the example does, I'd like an authoritative description of what it means.

From Capture and Uncapture the Mouse on MSDN:
When an object captures the mouse, all mouse related events are treated as if the object with mouse capture perform the event, even if the mouse pointer is over another object.
Only the capturing control receives the mouse events until released.
Capturing the mouse is useful for dragging because all the dragging code can exist in the one control, rather than being spread over multiple controls.

When it has captured the mouse, a control will receive mouse events even if the mouse pointer is no longer within its bounding area.
Typically, it's used for:
Drag and drop
Buttons (to handle Mouse Up when you put the mouse down on the button and move the mouse before you release the button)

The Silverlight 2 documentation for it has a more verbose description, I don't know why it isn't a part of the 3.5 documentation page too:
When an object has captured the mouse, that object receives mouse input whether or not the mouse pointer is within its bounding area. The mouse is typically only captured during simulated drag operations.
...
It works the same with WPF, and so the reason it is used with DragDrop, is that is how the
it knows to report back to the control being dragged from when the mouse may be outside of that control. If you comment out the MyCanvas.Capture() and the Capture(Null) (which clears it) then you can no longer drop.

Related

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."

How can i detect if the mouse is moving both within and out of the bounds of my window in WPF/C#?

I have a small video app that i would like to give vlc-like functionality. By that, I mean having a certain element disappear and appear on mouse move or mouse not moving. I have a rough concept of how to do this but I have no ideea how i coul detect if the mouse is moving or not. I thought about using the GetPosition function but that will just give me the mouse's position and won't let me know if the cursor is moving or not. I would like to use a timer to count down 2-3 seconds after the mouse has stopped moving and then either fade out the control or just make it collapse without further ado. I can't check the value of the position variable every milisecond. Is there some other way to do this ?
You can use a hook functionality so you will be notified when a mouse move, I use to use this free opensource library.
How to use it:
using Gma.UserActivityMonitor.GlobalEventProvider;
GlobalEventProvider _globalEventProvider1
= new Gma.UserActivityMonitor.GlobalEventProvider();
this.globalEventProvider1.MouseMove += HookMouseMove;//to listen to mouse move
Capture the mouse. Release the capture if the user actually clicks anywhere else. Then you can use the standard WPF mouse move event.
myElement.MouseMove += (my MouseMove handler)
Mouse.Capture(myElement);

Inject/simulate WPF routed mouse click events

I have some straight WPF 3.5 controls handling left mouse clicks that I need to use within a Surface app (SDK 1.0). The problem I am facing is that do not work by default. I am thinking of wrapping each control in a SurfaceContentControl and translating ContactTouchDown or ContactTapGesture events to corresponding MouseDown events.
The problem boils down to - how to "inject" or simulate arbitrary routed mouse events? I have tried InputManager.Current.ProcessInput() but didn't get very far. Any help is appreciated.
Try to use AutomationPeer classes. For example ButtonAutomationPeer is for Button. The code below initiates a click.
ButtonAutomationPeer peer = new ButtonAutomationPeer(button);
IInvokeProvider provider = (IInvokeProvider)peer.GetPattern(PatternInterface.Invoke);
provider.Invoke();
evpo's idea is an interesting one (though if you're working with custom controls, they rarely come with AutomationPeer classes).
You can't simply 'inject' mouse input by sending WM_MOUSE* events to your app... WPF would indeed process the message but when it goes to figure out the position of mouse for that event, it will query the actual mouse API instead of trying what you stick in the WM.
So really all you can do is tell windows to move the actual mouse cursor and act as though the button is being clicked/released. Some code you can use for that is in http://www.codeproject.com/KB/system/globalmousekeyboardlib.aspx
That said, while you can technically do this, it sucks... you've got an expensive multitouch device but are 1) showing a mouse cursor on it 2) limiting arbitrary parts of it to being used 'single touch' (and only one of those arbitrary parts at a time and 3) coming up with an arbitrary method of determining which finger you will treat as the mouse-controlling one

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

Mouse movement capture

I have an application wich open a modal form with the ShowDialog method.
Once this form is displayed I want to capture the mouse movement even if the cursor is outside the form.
How can I capture the mouse movement? I saw something with the Capture property but I cannot manage to make it work.
[edit]
I want to be notified if the mouse move outside the form.
The Capture property is the correct way, but there are some limitations.
Only the foreground window can capture the mouse
Mouse capturing can be disabled by other parts of the system
The Win32 API function SetCapture gets reset everytime a "mouse up" event occours. I assume that also applies for .NET.
See the remarks section of Capture property.
When the mouse is captured, you'll receive the usual events but with a wider mouse coordinate range (for example a negative X position, if the mouse is left of the capturing control)
Mouse capturing is fragile, because of it's global nature. Check if there are other ways to handle certain events. Perhaps the MouseLeave or MouseEnter events are enough in your case.
You can just use the static property Control.MousePosition.
You can read the position of the cursor, using the Cursor.Position property, see Cursor.Position

Categories

Resources