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
Related
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.
According to this question, the answer begins with "The MouseEnter/Leave events are too unreliable to do this." What exactly makes these events unreliable?
The mouse position is only polled every so often. It's very possible that one of those events - the mouse entering, or leaving, could occur between when the polls occur, and the events would not fire correctly.
This also makes a pretty concrete assumption that mouse movement will be continuous, rather than discrete - what if the user has a touch screen monitor? What if the mouse goes directly from inside the control to being way outside it, with no movement in between?
You missed the point entirely. These events are unreliable for the OP question, not in general.
The question was about seeing if the cursor is inside the forms client area. Having many controls the MouseEnter/Leave are unreliable because you will get these events even if you are inside the form's area.
Hallo,
I am trying to keep track of the mouse position and also its delta position. Is there any nicer way of doing this then implementing all the mouse events for all my forms in my window?
The problem with using the MouseMove event is that as soon as the mouse moves outside of the form it stops working properly. Implementing the mouseEnter, mouseLeave improves it somewhat, but it does still not feel perfect. Any ideas?
Regards,
You have to handle lower level windows events.
Check out this example: http://www.codeproject.com/KB/cs/globalhook.aspx
I was looking at a program my friend sent me that was written in Tcl/Tk. It has a rich-formatting multi-line text box with different colors and fonts, and for certain blocks of text the application window reacts to users hovering over different text elements. He says this is implemented by specifying a "OnMouseEnter" callback event when creating a new font. This seems like a cool and elegant approach, and I wanted to do something similar in a C# app I wrote. At the moment the three ways I can think to do this are: (a) work out the mapping from X-Y mouse coords to text (maybe there is an easy function for this?) (b) make each distinct text block a child control with its own callback functions (which is very ugly and would require me to do my own text wrapping) or (c) make it a webpage control and have javascript "call" C# via WebBrowser.Navigating. Any suggestions as to the best way to implement this kind of functionality would be welcome.
Most textbox control have X-Y coord to text block translation function calls. You can hook the entire mouse move event for the textbox and see what's beneath the mouse.
This might be ugly code but at least it would work.
In my 3d editor application, I want to be able to click on and move a scene's entities (meshes, lights, cameras, etc). To do that, I imagine that I need to get the current mouse position relative to my Direct3d view and somehow give it to my ViewModel. How would I go about doing that, considering that my app is built with the MVVM pattern?
Additional Info: The Direct3d renderer is from a C++ DLL and we're using an HwndHost to place it inside our WPF app. It has a WndProc which I imagine I could use to handle mouse messages there but I'd rather avoid it if at all possible.
Thanks!
The best solution I found is to use an attached behavior. In the control that serves as the placeholder to the HwndHost I set an attached property, like
b:MouseBehavior.LeftClick="{Binding DoSomeActionCommand}"
where MouseBehavior receives the control and sets mouse events on it.
It works well for me.
InputManager.Current.PrimaryMouseDevice is probably your best bet.
you can get the mouse position with
Mouse.Position( RelativeToObject ); // get the mouse pos relative to an object
Mouse.Position( null ); // get the mouse pos relative to the whole screen
if thats not good enough, you can use Win32 calls.