3

Is there a way to detect an event of cursor movement outside of WPF window? I'm not trying to find out if the cursor moved outside of the window, I'm simply trying to continue being subscribed to the movement event even if the mouse moves outside of wpf window boundary. I've been able to find a lot of stuff that deals with movement within the window, but nothing outside of it (at least nothing that actually works). They were all essentially working only within the window even if the question was asking about the external movement.

Since I haven't been able to find a solution thus far, I've been using the following code I've conjured up. I'm not sure how efficient this code is. I figure, if the system is checking for mouse movement already, it would be inefficient to add a separate check. However, I've been unable to tap into the system portion, since I can't find any good reference on it.

NOTE: I am trying to figure out an existing way of doing this. My code works fine, but it's probably inefficient, because if there's already an event producing code within the system that I can subscribe to, this extra timer loop is additional resource being wasted. I'm not trying to detect if the mouse moved outside of boundaries, I'm simply trying to record coordinates no matter where the mouse moved on screen. So, if the mouse moved on the second monitor, far away from my app window, I would still want an event to fire off and notification to occur. My timer implementation reports coordinates all the time, but I want to make sure I'm not adding an extra layer on top of something that already does the job. This seems to be a major confusion based on those who commented and the answer I received.

public MainWindow()
{
    InitializeComponent();
    InitializeCursorMonitoring();
}

private void InitializeCursorMonitoring()
{
    var point = System.Windows.Forms.Cursor.Position;
    var timer = new System.Windows.Threading.DispatcherTimer();

    timer.Tick += delegate
    {
        if (point != System.Windows.Forms.Cursor.Position)
        {
            point = System.Windows.Forms.Cursor.Position;

            System.Diagnostics.Debug.WriteLine(String.Format("X:{0}  Y:{1}",
                                               System.Windows.Forms.Cursor.Position.X, 
                                               System.Windows.Forms.Cursor.Position.Y));
        }
    };

    timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
    timer.Start();
}
General Grievance
  • 4,555
  • 31
  • 31
  • 45
B.K.
  • 9,982
  • 10
  • 73
  • 105
  • 1
    Try with capturing the mouse.. – Sankarann Mar 04 '14 at 09:35
  • @Sankarann Could you elaborate? – B.K. Mar 04 '14 at 09:36
  • Take a look of it... http://stackoverflow.com/questions/942357/what-does-it-mean-to-capture-the-mouse-in-wpf – Victory Jessie Mar 04 '14 at 09:41
  • @VictoryJessie Have you actually tried it? I think it only works within the windows, not outside of them. So if I have multiple windows, I can set mouse capture on them in foreground or background, but it doesn't do any tracking outside of them. At least not from what I've been able to find or test. MSDN documentation is horrible for this topic and every example out there pertains to dragging. – B.K. Mar 04 '14 at 10:03
  • @Noobacode Search StackOverflow (or the web) for "C# global mouse hook". – Clemens Mar 04 '14 at 11:30

1 Answers1

0

As mentioned by others you need to capture the mouse. Here's a sample based on your code illustrating it:

private void InitializeCursorMonitoring()
{
    var point = Mouse.GetPosition(Application.Current.MainWindow);
    var timer = new System.Windows.Threading.DispatcherTimer();

    timer.Tick += delegate
    {
        Application.Current.MainWindow.CaptureMouse();
        if (point != Mouse.GetPosition(Application.Current.MainWindow))
        {
            point = Mouse.GetPosition(Application.Current.MainWindow);
            Console.WriteLine(String.Format("X:{0}  Y:{1}", point.X, point.Y));
        }
        Application.Current.MainWindow.ReleaseMouseCapture();
    };

    timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
    timer.Start();
}

Capturing the mouse before getting the position to get the position anywhere on the screen and releasing it after to resume normal mouse functionality.

Eirik
  • 4,135
  • 27
  • 29
  • Your code prevents any dragging of the window - not something I would want. What exactly does capturing the mouse do? You've failed to mention that. All you said, in essence, was "do as others say" and described what you wrote in your code without explaining it. My implementation already reports coordinates of the mouse movement, so how does your code assist me with anything? – B.K. Mar 04 '14 at 17:11
  • 1
    Some time ago, capturing the mouse sent the mouse messages (WM_MOUSEMOVE, WM_CLICK, WM_...) to your program's message queue instead of sending them to the other programs' queues. Apparently this behavior was changed though : `If the mouse cursor is over a window created by another thread, the system will direct mouse input to the specified window only if a mouse button is down`. Hence your observed issue with dragging, I suspect. – FredP Mar 06 '14 at 08:29