ManipulationStarted fails to activate callback method - wpf

I have a WPF Canvas with .NET-4.5.
I added events (which autocreated methods for) MouseLeftButtonDown and MouseDown. Using MessageBox, I have confirmed these methods are called when a user clicks on the canvas, but I can't find a way to get the mouse position from MouseButtonEventArgs.
When I added events (and autocreated methods for) ManipulationStarted and ManipulationStarting those MessageBoxes don't show up.
private void CenterCanvas_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
MessageBox.Show("Doesn't show up"); // never shows up
}
private void CenterCanvas_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Shows up"); // shows up, but can't seem to get click position
}

In order to get the mouse position from a MouseEventArgs you would have to call the GetPosition method.
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
var pos = e.GetPosition((IInputElement)sender);
System.Diagnostics.Trace.TraceInformation("MouseDown at {0}", pos);
}
For getting manipulation events you need to set IsManipulationEnabled to true. You may want to take a look at the Touch and Manipulation section in the MSDN Input Overview.

Related

Handling a Click for all controls on a Form & getting mouse location

I am working on a windows form that is covered in panels representing a grid.
I'm trying to create an event handler that handles all mouse clicks regardless of which panel the click occurs on and then moves a PictureBox to the location of the panel.
I managed to find a topic that covered the event handler, but I am unable to get the location of the mouse click from the event handler. Below is the code I have so far (mostly pinched from another post):
private void Form1_Load(object sender, EventArgs e)
{
foreach (Control c in this.Controls)
{
c.MouseClick += new MouseEventHandler(myEvent_handler_click);
}
}
public void myEvent_handler_click(object sender, EventArgs e)
{
Point point = new Point(e.X, e.Y);
game.MoveToSquare(point);
}
The line of code Point point = new Point(e.X, e.Y); doesn't work because I can't refer to the X of e or the Y of e.
How can I get the location of the mouse at the time it is clicked?
Any help is appreciated. Feel free to ask me more questions if I wasn't clear enough!
The delegate for the event handler is defined like so:
public delegate void MouseEventHandler(object sender, MouseEventArgs e);
MouseEventArgs inherits from EventArgs, that's why your code is working. If you change the definition of your EventHandler, you should be able to access the coordinates:
public void myEvent_handler_click(object sender, MouseEventArgs e)
{
Point point = new Point(e.X, e.Y);
}
You can also simply access e.Location to get point:
Point point = e.Location;

Why does implementing WPF DragDrop behaviour stop ListBoxItems becoming selected on the first click?

I have been implementing basic drag and drop functionality using WPF and C# quite successfully for some time now. I have always had one problem after implementing it though... for some reason, the drag and drop functionality stops the ListBoxItems from becoming selected (on the first click).
If I click on a ListBoxItem but don't drag it, it doesn't get selected and the drag icon appears momentarily. On the next click I can then select any of the ListBoxItems and the drag icon does not appear. This cycle then repeats... first click won't select, second one will.
Below is a typical implementation of my drag and drop code, taken from the Micorsoft MCTS 70-511 'Training kit' book.
private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
object data = (ListBoxItem)(FrameworkElement)sender;
if (data != null) DragDrop.DoDragDrop(ListBox, data, DragDropEffects.Copy);
e.Handled = false;
}
private void ListBox_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(ListBoxItem))) e.Effects = DragDropEffects.Copy;
}
private void ListBox_Drop(object sender, DragEventArgs e)
{
object data = e.Data.GetData(typeof(ListBoxItem));
if (data != null) DoSomethingWith((DataType)((ListBoxItem)data).DataContext);
}
The drag and drop works fine, but the item selection doesn't... I presumed that by adding e.Handled = false in the ListBox_PreviewMouseLeftButtonDown handler, the ListBoxItem selection mechanism could handle the click event, but it never reaches that far.
I also tried handling the drag initiation in the MouseLeftButtonDown handler instaed of the PreviewMouseLeftButtonDown handler, but the ListBoxItem selection mechanism handles the click event and it never reached that drag drop handler.
There must be a way to initiate the drag drop operation and still have the ListBoxItem that was clicked on become selected, but I still haven't managed to find it... any clues anyone?
UPDATE >>>
Thanks to the MSDN article #icebat provided a link for, I've managed to get the drag and drop functionality working perfectly. It is now as follows:
private void SourceListBox_MouseMove(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
object data = ((ListBox)(FrameworkElement)sender).SelectedItem;
if (data != null)
DragDrop.DoDragDrop(SourceListBox, data, DragDropEffects.Copy);
}
}
private void TargetListBox_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(DragObject))) e.Effects = DragDropEffects.Copy;
}
private void TargetListBox_Drop(object sender, DragEventArgs e)
{
object data = e.Data.GetData(typeof(DragObject));
if (data != null) DoSomethingWith((DragObject)data);
}
Just use MouseMove event instead of MouseDown for drag and drop. You can find more information and some code in the Drag and Drop article on MSDN.

MouseMove event in WPF

In WPF when the MouseMove event is triggered, I want to check if the left mouse key is pressed, if it's pressed I want to do some calculation.
I have tried this:
private void Window_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Calculate();
}
}
But when I left-click and hold and move the mouse around the screen the Calculate() only gets called one time (i.e when the mouse starts moving), after that no matter where I move the mouse the method does not get called.
I want the Calculate() method to get called repeatedly while the mouse is moving and while the left mouse key is pressed.
A simple test for me shows this working:
private void MouseMoveEvent(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
_vm.MoveCount++;
}
}
A would suspect that your Calculate method is a synchronous method that's causing problems.
Try calling the method like below. This will start the calculate method in a new thread. Then the updating of the text box will happen in the original thread.
private void WindowMouseMoveEvent(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var worker = new BackgroundWorker();
worker.DoWork += Calculate;
worker.RunWorkerCompleted +=
(o, args) => myTextBox.Text = (string)args.Result;
worker.RunWorkerAsync();
}
}
private void Calculate(object sender, DoWorkEventArgs args)
{
//do work
args.Result = "my new value"
}
If you are working with element derived from Panel class, it fires mouse events only when it has Background property set.
I have verified it works. If I keep the mouse button down and move it over the window, the function gets called repeatedly as long as I move mouse over the window. May be your Calculate function takes a lot of time to execute and return back. So it is a long time before it gets called back again. In that case use multiple thread to called Calculate().
To test that this works I added a label to Window and put line label.Content = DateTime.Now.Ticks; instead of the calculate func here. It keeps updating the value.
If applicable, the CRectTracker::Track function will capture the mouse until the user releases the left mouse button.
http://msdn.microsoft.com/en-us/library/ttwy7427.aspx

What event can I change the caret in in a winforms maskedtextbox

Right now, I'm calling the win32 createcaret/showcaret in the keypress event of my masked textbox. That changes it fine. I want the caret to change when the box is entered, though, either by tab or by click.
Unfortunately the enter event or even the invalidate event aren't suitable places to change that caret. It doesn't change, maybe because they fire too early.
So anyway, how can I get the caret to change on textbox enter without handling it in the enter event?
You need to add DestroyCaret to your routine, too:
private void Form1_Load(object sender, EventArgs e)
{
textBox1.GotFocus += new EventHandler(textBox1_GotFocus);
textBox1.LostFocus += new EventHandler(textBox1_LostFocus);
}
private void textBox1_GotFocus(object sender, EventArgs e)
{
CreateCaret(textBox1.Handle, IntPtr.Zero, 6, textBox1.Height);
ShowCaret(textBox1.Handle);
}
private void textBox1_LostFocus(object sender, EventArgs e)
{
DestroyCaret();
}

WPF Mousedown => No MouseLeave Event

I'm building a Windows Presentation Foundation control with Microsoft Blend.
When I leave my control by pressing the left-mouse-button, the MouseLeave-Event is not raised. Why not?
This is intended behaviour: When you are doing mousedown on a control and leaving the control, the control STILL retains its "capture" on the mouse, meaning the control won't fire the MouseLeave-Event. The Mouse-Leave Event instead will be fired, once the Mousebutton is released outside of the control.
To avoid this, you can simple tell your control NOT to capture the mouse at all:
private void ControlMouseDown(System.Object sender, System.Windows.Forms.MouseEventArgs e)
{
Control control = (Control) sender;
control.Capture = false; //release capture.
}
Now the MouseLeave Event will be fired even when moving out while a button is pressed.
If you need the Capture INSIDE the Control, you need to put in more effort:
Start tracking the mouseposition manually, when the mousekey is pressed
Compare the position with the Top, Left and Size Attributes of the control in question.
Decide whether you need to stop the control capturing your mouse or not.
public partial class Form1 : Form
{
private Point point;
private Boolean myCapture = false;
public Form1()
{
InitializeComponent();
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
myCapture = true;
}
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (myCapture)
{
point = Cursor.Position;
if (!(point.X > button1.Left && point.X < button1.Left + button1.Size.Width && point.Y > button1.Top && point.Y < button1.Top + button1.Size.Height))
{
button1.Capture = false; //this will release the capture and trigger the MouseLeave event immediately.
myCapture = false;
}
}
}
private void button1_MouseLeave(object sender, EventArgs e)
{
MessageBox.Show("Mouse leaving");
}
}
of course you need to stop the own tracking ( myCapture=false;) on MouseUp. Forgot that one :)
When I don't get mouse events I expect I typically use Snoop to help me understand what is happening.
Here are a couple of links:
1- Snoop (a WPF utility)
2- CodePlex project for Snoop
And for completeness and historical reasons (not the bounty - it doesn't make sense having two duplicate questions - you should probably move it into one if not too late)...
I made a thorough solution using global mouse hook here (approach 2)
WPF: mouse leave event doesn't trigger with mouse down
And simplified its use - you can use it by binding to commands in your view-model - e.g.
my:Hooks.EnterCommand="{Binding EnterCommand}"
my:Hooks.LeaveCommand="{Binding LeaveCommand}"
my:Hooks.MouseMoveCommand="{Binding MoveCommand}"
...more details in there
Old question but I came across the same problem with a Button (MouseLeave does not fire while MouseDown because MouseDown Captures the Mouse...)
This is how I solved it anyway:
element.GotMouseCapture += element_MouseCaptured;
static void element_MouseCaptured(object sender, MouseEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
element.ReleaseMouseCapture();
}
Hope that helps someone looking for a quick fix :P

Resources