I'm sure I've read that there is a way of getting co-ordinates on TouchDown in a WPF app and finding out what UI elements are 'underneath' this touch. Can anyone help?
You have to do a hit test against the visual tree.
Here is an example with mouse click (but touch is more or less the same thing in this respect):
// Respond to the left mouse button down event by initiating the hit test.
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Retrieve the coordinate of the mouse position.
Point pt = e.GetPosition((UIElement)sender);
// Perform the hit test against a given portion of the visual object tree.
HitTestResult result = VisualTreeHelper.HitTest(myCanvas, pt);
if (result != null)
{
// Perform action on hit visual object.
}
}
Other overload of HitTest can give you multiple hit visuals.
Let your UI elements extend UIElement class like this:
class MyUIElement : UIElement
{
protected override void OnManipulationStarting(System.Windows.Input.ManipulationStartingEventArgs e)
{
base.OnManipulationStarting(e);
UIElement involvedUIElement = e.Source as UIElement;
// to cancel the touch manipulaiton:
e.Cancel();
}
}
involvedUIElement should hold the UI elements that raised the touch event, if you need to cancel the manipulation for specific elements you just need to call e.Cancel();
I hope this will help!
Related
I have basically two controls involved in a drag/drop operation. I do this for the start control:
private void controlA_MouseMove(object sender, MouseEventsArgs e)
{
if(e.LeftButton == MouseButtonState.Pressed)
{
//set DataObject...datao
DragDrop.DoDragDrop(controlB, datao, DragDropEffects.Copy | DragDropEffects.Copy;
}
}
The user moves off of controlA, onto controlB and continues dragging to some point on controlB. I've tried the following in several events with no luck to establish a different cursor from the default arrow with the little box under it:
Mouse.OverrideCursor = Cursors.Hand;
and
Mouse.SetCursor(Cursors.Hand);
In these events for controlB, which is where the drop happens:
DragOver
DragEnter
GiveFeedback
How do I get rid of the default arrow with the little box under it while dragging over controlB?
Set ControlB.Cursor = Cursors.Whatever; inside your ControB_MouseEnter() event handler.
You may want to limit it under an if(e.LeftButton == MouseButtonState.Pressed) condition.
Tested MouseEnter while MouseLeftButton is Pressed:
I think that must be only a little problem, but I can't get a clear thought on that. Someone an idea?
I have some borders on a canvas (filled with images) and i want to click the border (i do this with the OnMouseLeftButtonDown) where the border gets red (so the user knows for sure which object he had clicked) and then, after 1 or 2 seconds, when the mousebutton is still pushed down, a drag'n'drop should start.
At first I had the borders inside buttons, but the clickevent seems to conflict with the dragevent. So I got rid of the buttons and did everything inside the borders directly, which works well also. But how can I start the drag after the mousebuttondown and stop it when the mousebuttonup happens before the time runs out.
Someone an idea for a clean solution?
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_source = sender as Border;
Mouse.Capture(_source);
}
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_source = null;
Mouse.Capture(null);
}
and in event OnMouseMove you can modify border margins depends on mouse position but after checking if _source is type of Border.
var position = e.GetPosition(Canvas);
EDIT:
For that time you can add property Stopwatch _watch, and inside OnMouseLeftButtonDown event handler you can do it:
_watch = Stopwatch.StartNew();
in OnMouseLeftButtonUp:
_watch.Stop();
and in OnMouseMove before your code:
while (_watch.ElapsedMilliseconds < 2000 && _watch.IsRunning)
{
Thread.Sleep(100);
}
For the record: I'm new to Silverlight and XAML.
I'm trying to simply display the mouse coordinates relative in my canvas (or any other element).
After reading a lot on the subject, unfortunantly I havn't figured this our yet.
My Silverlight 5 project uses MVVM with Caliburn micro.
How can this be done?
Would Appreciate help on implementing this.
Thanks,
Guy.
You need to be a little more specific with what control you're trying to get this with, but have you tried wiring something up to the MouseMove event? Like MouseMove="Handle_MouseMove"
public void Handle_MouseMove(object sender, MouseEventArgs args)
{
mouseVerticalPosition = args.GetPosition(null).Y;
mouseHorizontalPosition = args.GetPosition(null).X;
}
Is that what you're looking for?
If you want this to happen on the entire canvas, you can instead wire it up to PointerMoved
See MouseEventArgs. This can get you the X and Y position and it can be used with the MouseUp, MouseDown, and MouseMove events.
To complete tnw Answer : You have to start mouse capture on object : MyElement.CaptureMouse()
In the handler method, you can use GetPosition on MouseEventArgs with an UIElement in parameter for relative coordinates...
public void Handle_MouseMove(object e, MouseEventArgs f)
{
var point = f.GetPosition(MyElement);
}
you have to catch the mouse click event and there are some event handlers you can use it to capture the position.
private void CadLayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
double point1 = e.GetPosition(bitmapCadView.UIElement).X;
double point2 = e.GetPosition(bitmapCadView.UIElement).Y;
}
I have this code:
Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this,
OnMouseDownOutsideCapture);
And it fully captures when a mouse click happens outside my WPF Popup (so I can close it).
private void OnMouseDownOutsideCapture(object sender, MouseButtonEventArgs e)
{
if (Mouse.Captured is ComboBox) return;
if (IsOpen)
IsOpen = false;
ReleaseMouseCapture();
}
But I need some way to know if the focus is moved outside my popup via the keyboard. More specifically by an shortcut (ie Alt + T).
Right now, my popup does not close when the user moves focus off it that way. Any ideas?
This is how I did it:
Add this to the constructor:
EventManager.RegisterClassHandler(typeof(UIElement),
Keyboard.PreviewGotKeyboardFocusEvent,
(KeyboardFocusChangedEventHandler)OnPreviewAnyControlGotKeyboardFocus);
Then add this event handler:
/// <summary>
/// When focus is lost, make sure that we close the popup if needed.
/// </summary>
private void OnPreviewAnyControlGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
// If we are not open then we are done. No need to go further
if (!IsOpen) return;
// See if our new control is on a popup
var popupParent = VLTreeWalker.FindParentControl<Popup>((DependencyObject)e.NewFocus);
// If the new control is not the same popup in our current instance then we want to close.
if ((popupParent == null) || (this.popup != popupParent))
{
popupParent.IsOpen = false;
}
}
VLTreeWalker is a custom class that walks up the visual tree looking for a match to the passed in generic type and then (if it does not find a matching item, will walk up the logical tree.) Sadly, I can't easily post the source for that here.
this.popup is the instance that you are comparing against (that you want to know if it should close).
You could add a KeyDown event and check if alt+tab were pressed.
I registered Hotkey: Ctrl + Space. Hotkey message is sent to:
private void Hotkey_press()
{
... // I want to show tooltip "Hello" at current mouse location.
}
Is there any way to show this tooltip even the mouse doesnt point to any control and it is outside my Window.Form1?
Edit: That ToolTip can show even the form lost focus or hide
You want something like
ToolTip tt = new ToolTip();
IWin32Window win = this;
tt.Show("String", win, mousePosition);
Where the MousePosition can be obtained from the MouseEventArgs via
private SomeMouseEventHandler(object sender, MouseEventArgs e)
{
System.Drawing.Point mousePosition = e.Location;
...
}
or using
System.Drawing.Point mousePosition = Cursor.Position;
also, you may want to set a longer duration for which the ToolTip is displayed, well just use the overloads available for the Show method, tt.Show("String", win, mousePosition, 5000); will display the tool tip for 5 seconds.
I hope this helps.
Tooltip tip = new ToolTip();
tip.ShowAlways = true;
tip.Show("My tooltip",this,Cursor.Position.X,Cursor.Position.Y);
http://msdn.microsoft.com/en-us/library/system.windows.forms.tooltip.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.tooltip.showalways.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.cursor.aspx
As this answer suggests, there is no managed way to accomplish this. If you want to show a tool tip control when your program is not in focus then the "right" way to do it is to PInvoke Win32 and use CreateWindowEx. The answer linked above given by gideon shows some pointers on how to do it, but nonetheless it is very complicated.
If you don't mind using thrid party libraries, AutoIt provides a way to create tool tips easily without having to deal with Win32 yourself.
Here is a very simple example demonstrating use:
//make sure AutoItX3.dll is referenced in your project
using AutoItX3Lib;
private AutoItX3 myAutoIt = new AutoItX3();
private async void ShowToolTipAtMouse(string message)
{
//default position is bottom right of mouse pointer,
//but you can set the x and y positions yourself
myAutoIt.ToolTip(message);
//call the function again with an empty argument to close
await Task.Delay(1000);
myAutoIt.ToolTip(String.Empty);
}
This will work as long as your program is running; doesn't matter if it is in/out of focus or even hidden. Downside is you don't get the regular fade out animation (it just vanishes). Also, if you need multiple tool tips at once you need to have multiple AutoItX3 objects.
You need Show/Hide it in the mouse events, also converting mouse location from Screen coordinate to your control coordinate. the little problem is if you put tooltip exactly on mous pointer location toolTip will catch mouseEnter event and unintended mouseLeave event on your control will be triggered so my solution was adding a little offset to final location.
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Point p = pictureBox3.PointToClient(Cursor.Position);
p.X += 5;
p.Y += 5;
toolTip1.Show("My tooltip" ,
pictureBox1, p);
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
toolTip1.ShowAlways = false;
Text = ("Leave");
}
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
toolTip1.ShowAlways = true;
Text=("Enter");
}
It is a shame Winforms does not have a position property for tooltips.
The easiest thing I found is to add your own mouse-over and mouse-leave handlers and then use the Show() function to set the location (x and y), in pixels, relative to the upper left corner of the second argument of the Show() function.
The second argument can be any control, but probably makes most sense to use the control containing the tooltip itself (this), the parent the control, or a child control inside the control.
You can use a Point instead of two arguments (x and y) for the position, but remember Show() will take the point's x coordinate and y coordinate and add them to the x and y coordinates of the upper left corner of the control you chose as the second argument.
private void UserControl1_MouseHover(object sender, EventArgs e)
{
toolTip1.Show("this text is so new", this, 10, 10);
}
private void UserControl1_MouseLeave(object sender, EventArgs e)
{
toolTip1.Hide(this);
}