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
Related
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;
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.
I have three storyboards in a wpf application.
begin is single animation
progress is a repeating animation
end is a single animation too
All storyboards animating the same image, the "progress" storyboard is repeating (while a query in an another thread is running), the "begin" storyboard preceeds it, the "end" animation follows it.
I supposed that this is a simple problem: when the application starts, start the "begin" animation, then in an oncompleted event handler, starts the progress animation, etc.
But it doesnt work: the progress animation is starts, but it appears improperly (strange flashing).
I made a "button1" to analyse this, and i noticed then the same method in the button's onclick eventhandler is works (after the begin storyboard is ended, i pushed it, and the progress storyboard is started and appeared perfectly).
(The FillBehavior of the begin animation is "Stop": the button doesnt worked without this setting, but the eventhandler is remains wrong after setting it)
private void Window_Loaded(object sender, RoutedEventArgs e)
{
begin = (Storyboard)FindResource("startanimation");
progress = (Storyboard)FindResource("progressanimation");
end = (Storyboard)FindResource("stopanimation");
begin.Completed += new EventHandler(begin_Completed);
begin.Begin();
}
void begin_Completed(object sender, EventArgs e)
{
progress.Begin(); //not works
}
private void button1_Click(object sender, RoutedEventArgs e)
{
progress.Begin(); //works
}
Any idea?
Try this:
void begin_Completed(object sender, EventArgs e)
{
this.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
progress.Begin();
}
));
}
Eventually I am forced to make a secondary timer, and start the progress animation in the tick event.. Very ugly, but works.
Any other tips are still welcome.
I'm having problems getting the Silverlight Button Click event to immediately update a control's UI element and then continue doing some other process. For example, update the text of a control and then do some process. I've tried calling the UpdateLayout() method but that doesn't help.
Here is some sample code:
private void button1_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "Testing";
textBlock1.UpdateLayout();
UpdateLayout();
Thread.Sleep(2000);
textBlock1.Text = "Done";
}
In that sample, the textBlock1 control will never display the text "Testing".
It's because you've blocked the UI thread with your Sleep statement which means that the text block won't update until after it's completed, but by that time you've set the text to "Done".
This doesn't work. The UI will block when you do not exit the method. This is why in Silverlight you usually do everything asynchronously:
private void button1_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "Testing";
var myTask = /* ... */
myTask.Completed += new FancyDelegate(myTask_Completed);
}
private void myTask_Completed(object sender, RoutetEventArgs e)
{
textBlock1.Text = "Done.";
}
If your tasks do not have asynchronous functions, just wrap them. But be reminded, that when you want to change your textBlock1.Text property from another thread, you must invoke it with the Dispatcher.
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