WPF:在屏幕坐标和WPF坐标之间转换

Qwe*_*tie 11 .net wpf coordinates

据我所知,如果计算机没有使用默认的DPI设置,WPF坐标与"真实"屏幕坐标(像素坐标)不同.在我的程序中,我想(1)找出WPF窗口所在的监视器,以及(2)打开同一监视器左下角的另一个窗口.我听说WPF 没有相应的屏幕,所以我使用WinForms版本,如下所示,它在默认的96 DPI下工作正常:

public void ChooseInitialPosition(Window w) // w is some other window
{
    var scr = System.Windows.Forms.Screen.FromRectangle(
          new System.Drawing.Rectangle((int)w.Left, (int)w.Top, (int)w.Width, (int)w.Height))
          .WorkingArea;

    this.Left = scr.Right - Width;
    this.Top = scr.Bottom - Height;
}
Run Code Online (Sandbox Code Playgroud)

但在其他DPI中,这两个步骤都不正确,并且可能会使窗口完全脱离屏幕.

到目前为止,看起来我可以在第一部分使用Visual.PointToScreen:

var p1 = w.PointToScreen(new Point(0,0));
var p2 = w.PointToScreen(new Point(w.Width,w.Height));
var scr = System.Windows.Forms.Screen.FromRectangle(
    new System.Drawing.Rectangle((int)p1.X, (int)p1.Y, (int)(p2.X - p1.X), (int)(p2.Y - p1.Y))).WorkingArea;
Run Code Online (Sandbox Code Playgroud)

我不确定这是否正确,因为它可能无法正确解释边界.但第二部分更重要.如何将屏幕矩形"scr"转换为WPF空间,以便正确设置Left和Top?

Sko*_*ski 30

  1. WPF窗口在哪个屏幕上:

    private static Screen GetScreen(Window window)
    {
       return Screen.FromHandle(new WindowInteropHelper(window).Handle);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 打开同一屏幕左下角的另一个窗口:

    static Point RealPixelsToWpf(Window w, Point p)
    {
        var t = PresentationSource.FromVisual(w).CompositionTarget.TransformFromDevice;
        return t.Transform(p);
    }
    private static void SetPositionBottomLeftCorner(Window sourceWindow, Window targetWindow)
    {
        var workingArea = GetScreen(sourceWindow).WorkingArea;
        var corner = RealPixelsToWpf(sourceWindow, new Point(workingArea.Left, workingArea.Bottom));
        targetWindow.Left = corner.X;
        targetWindow.Top = corner.Y - targetWindow.ActualHeight;
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 添加了RealPixelsToWpf()辅助方法. (2认同)