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

.net WPF:在屏幕坐标和WPF坐标之间转换,.net,wpf,coordinates,.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.Sc

我知道,如果计算机未使用默认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;
}
但在其他DPI中,这两个步骤都不正确,可能会使窗口完全脱离屏幕

到目前为止,它看起来可以用于第一部分:

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;

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

如果将其放在窗口的代码中,这是否有效

protected override void OnContentRendered(System.EventArgs e)
{
    base.OnContentRendered(e);
    MoveToLowerRightCorner();
}

private void MoveToLowerRightCorner()
{
    var workingArea = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
    var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
    var corner = transform.Transform(new Point(workingArea.Right, workingArea.Bottom));
    this.Left = corner.X - this.ActualWidth;
    this.Top = corner.Y - this.ActualHeight;
}
  • WPF窗口在哪个屏幕上:

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

    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;
    }
    

  • 不确定是否支持多监视器,但您可以仅使用WPF(支持DPI)在主屏幕上正确定位窗口,而不使用SystemParameters类引用Windows窗体(不支持DPI)。相关属性会自动调整以适应不同的DPI设置。示例:window.Top=SystemParameters.FullPrimaryScreenHeight-(window.ActualHeight-SystemParameters.WindowCaptionHeight)//适用于Vista和Windows 7,不了解XP。添加了RealPixelsToWpf()辅助方法。无法解决我的问题。WPF报告我的屏幕是1936x1040,而Windows实际上是1920x1024。在我的例子中,Transform()是不可操作的。经过大量调查,解决方案是:WPF全屏窗口实际上比屏幕大。它们周围有一个虚拟边框,表示窗口的整个范围。所以这不是一个缩放问题,而是一个加/减边界区域大小的问题。我不知道一个通用的方法,但现在只看数值并进行校正。