3

I have the following issue:

I have window with two textboxes. When I click in a textbox and then click anywhere else (even outside the window), the mouse click position should be written into the textbox.

I found the MouseKeyHook library, in which a demo shows how the mouse position is updated in a windows form. But I did not manage to apply the code to my problem yet. I don't even know where I should write the code found in the demo.

What I came up with so far is the following:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace LineClicker
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void StarttextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            Mouse.Capture(StarttextBox);
            StarttextBox.Text = string.Format(" x {0} , y {1}", PointToScreen(Mouse.GetPosition(this)).X, PointToScreen(Mouse.GetPosition(this)).Y);
        }
    }
}

This is the code for one textBox. When I click in it, x and y coordinates are displayed. They are not absolute, I think this is due to the parameter this in the GetPosition method. What do I have to choose instead of this?

Another thing is that the position is not updated always. When I move the mouse to the lower right corner of my desktop and then activate the textbox by tabbing into it, the position doesn't get updated.

What are the steps to do here?

Bassie
  • 9,529
  • 8
  • 68
  • 159
David P
  • 317
  • 2
  • 3
  • 9
  • If you want to get the absolute position of the mouse, relative to the screen, and update it even when you are outside the WPF Window, then you will have to use a MouseHook (Uses Win32 API calls to get the position), and a Timer, that gets the position and displays it in your TextBlock. – Lupu Silviu Nov 03 '16 at 10:55

2 Answers2

3

I was able to achieve this result using Cursor.Position:

A Point that represents the cursor's position in screen coordinates.

Example

using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void textBox_GotFocus(object sender, RoutedEventArgs e)
        {
            var postion = System.Windows.Forms.Cursor.Position;
            textBox.Text = string.Format($"{postion.X}, {postion.Y}");
        }
    }
}

You can see from the the Microsoft reference source that Cursor.Position is defined as:

public static Point Position {
    get {
        NativeMethods.POINT p = new NativeMethods.POINT();
        UnsafeNativeMethods.GetCursorPos(p);
        return new Point(p.x, p.y);
    }
    set {
        IntSecurity.AdjustCursorPosition.Demand();
        UnsafeNativeMethods.SetCursorPos(value.X, value.Y);
    }
}

So just like in yan yankelevich's answer, it still uses SetCursorPos, but this way it is easier to call.

Apart from that it probably just depends on whether or not you are happy to include the reference to System.Windows.Forms.

Community
  • 1
  • 1
Bassie
  • 9,529
  • 8
  • 68
  • 159
  • When I try this, `System.Windows.Forms` is underlined in red and there is an error saying CS0234 C# The type or namespace name 'Forms' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?) – David P Nov 03 '16 at 12:59
  • @DavidP You will need to add `System.Windows.Forms` as a reference by going `Project` -> `Add Reference` and then select it from the list (It will be under Assmblies -> Framework) – Bassie Nov 03 '16 at 13:06
  • It worked, thank you! That solution looks easier than the one from yan yankalevich. Are there any advantages/disadvantages between your answer and his? – David P Nov 03 '16 at 21:28
  • 1
    This website is a miracle. – David P Nov 04 '16 at 09:58
2

First you will need to get the absolute mouse position (not relative to your window or your controls). To do this you need one of these options (from here : https://stackoverflow.com/a/4232281/4664754) :

  • By adding a reference to System.Windows.Forms in your project ( go in References in your solution explorer -> Right Click -> Add a Reference -> Assemblys-> Framework -> Tick the box near System.Windows.Forms). Then add this static funtcion in some class (let's call it MouseHelper.cs) :

    public static Point GetMousePositionWindowsForms()
    {
        System.Drawing.Point point = Control.MousePosition;
        return new Point(point.X, point.Y);
    }
    
  • By pasting this code in your MainWindow.xaml.cs:

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetCursorPos(ref Win32Point pt);
    
        [StructLayout(LayoutKind.Sequential)]
        internal struct Win32Point
        {
            public Int32 X;
            public Int32 Y;
        };
        public static Point GetMousePosition()
        {
            Win32Point w32Mouse = new Win32Point();
            GetCursorPos(ref w32Mouse);
            return new Point(w32Mouse.X, w32Mouse.Y);
        }
    

Whatever the way you choose you will need to call one of those functions in your OnFocusChanged this way :

 private void StarttextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            Mouse.Capture(StarttextBox);
            Point mouseCoord = MouseHelper.GetMousePositionWindowsForms();
            // Or if you choose the other way :
            //Point mouseCoord = GetMousePosition();
            StarttextBox.Text = string.Format(" x {0} , y {1}", mouseCoord.X, mouseCoord .Y);
        }

This way the coordinates should be correct. For your problem of coordinates not displaying at the right time, i think your focus solution is not what you are looking for.

You should try to implement something like this : https://stackoverflow.com/a/2064009/4664754 and change your textboxes values every time the TheMouseMoved event is called

Community
  • 1
  • 1
yan yankelevich
  • 885
  • 11
  • 25