How to get mouse position related to desktop in WPF?

后端 未结 3 1669
我在风中等你
我在风中等你 2020-12-06 12:03

Problem

When you search for such question using google you get a lot of hits but all solutions assume you have at least one window.

But my question is just l

相关标签:
3条回答
  • 2020-12-06 12:44

    Getting the Screen Coordinates:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetCursorPos(out POINT lpPoint);
    
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;
    
        public POINT(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    }
    
    private void WritePoint(object sender, RoutedEventArgs e)
    {
        POINT p;
        if (GetCursorPos(out p))
        {
            System.Console.WriteLine(Convert.ToString(p.X) + ";" + Convert.ToString(p.Y));
        }
    }
    

    Converting Pixels to WPF Units:

    [DllImport("User32.dll")]
    static extern IntPtr GetDC(IntPtr hwnd);
    
    [DllImport("gdi32.dll")]
    static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
    
    [DllImport("user32.dll")]
    static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
    
    private Point ConvertPixelsToUnits(int x, int y)
    {
        // get the system DPI
        IntPtr dDC = GetDC(IntPtr.Zero); // Get desktop DC
        int dpi = GetDeviceCaps(dDC, 88);
        bool rv = ReleaseDC(IntPtr.Zero, dDC);
    
        // WPF's physical unit size is calculated by taking the 
        // "Device-Independant Unit Size" (always 1/96)
        // and scaling it by the system DPI
        double physicalUnitSize = (1d / 96d) * (double)dpi;
        Point wpfUnits = new Point(physicalUnitSize * (double)x,
            physicalUnitSize * (double)y);
    
        return wpfUnits;          
    }
    

    Putting both together:

    private void WriteMouseCoordinatesInWPFUnits()
    {
        POINT p;
        if (GetCursorPos(out p))
        {
            Point wpfPoint = ConvertPixelsToUnits(p.X, p.Y);
            System.Console.WriteLine(Convert.ToString(wpfPoint.X) + ";" + Convert.ToString(wpfPoint.Y));
        }
    }
    
    0 讨论(0)
  • 2020-12-06 12:47

    Two options:

    Use System.Windows.Forms.Control.MousePosition, or p/invoke

    [DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
    public static extern bool GetCursorPos([In, Out] NativeMethods.POINT pt);
    

    The first option already does the p/invoke for you. I'm not entirely sure it requires you have some UI splashed up, but I don't think so. Yes, its winforms and not wpf, but it really doesn't have anything to do with where its located at.

    If you want to skip any dependencies on system.windows.forms.dll then check out more information about the second on pinvoke.net.

    0 讨论(0)
  • 2020-12-06 12:53

    I stumbled over that thread while looking for a solution for the same problem. In the meantime, I found PointToScreen, which does not require any P/Invoke. The method is available on any Visual starting .NET 3.0 (and thus UIElement, Control, etc.) and an implementation would look like this:

    protected void OnMouseLeave(object Sender, MouseEventArgs e) {
        var relativePosition = e.GetPosition(this);
        var screenPosition = this.PointToScreen(relativePosition);
    }
    
    0 讨论(0)
提交回复
热议问题