【问题标题】:WPF: Converting between screen coordinates and WPF coordinatesWPF:在屏幕坐标和 WPF 坐标之间转换
【发布时间】:2011-08-03 18:26:22
【问题描述】:

我了解,如果计算机未使用默认 DPI 设置,WPF 坐标与“真实”屏幕坐标(像素坐标)不同。在我的程序中,我想 (1) 找出 WPF 窗口在哪个监视器上,(2) 在同一监视器的左下角打开另一个窗口。我听说 WPF 没有 Screen 的等价物,所以我使用 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 中,这两个步骤都无法正常工作,并且可能会使窗口完全脱离屏幕。

到目前为止,我似乎可以在第一部分使用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;

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

【问题讨论】:

  • 不确定是否支持多显示器,但您可以仅使用 WPF(支持 DPI)将窗口正确定位在主屏幕上,而无需使用 Windows 窗体(不支持 DPI)系统参数类。相关属性会自动调整为不同的 DPI 设置。示例:window.Top = SystemParameters.FullPrimaryScreenHeight - (window.ActualHeight - SystemParameters.WindowCaptionHeight); //适用于Vista和Windows 7,不知道XP。

标签: .net wpf coordinates


【解决方案1】:
  1. WPF 窗口在哪个屏幕上:

    private static Screen GetScreen(Window window)
    {
       return Screen.FromHandle(new WindowInteropHelper(window).Handle);
    }
    
  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;
    }
    

【讨论】:

  • 添加了 RealPixelsToWpf() 辅助方法。
  • 不能解决我的问题。 WPF 将我的屏幕报告为 1936x1040,而 Windows 实际上将其显示为 1920x1024。就我而言,Transform() 是无操作的。
  • 经过大量调查,解决方案:WPF全屏窗口实际上比屏幕大。它们周围有一个虚拟边框,代表窗口的全部范围。所以这不是缩放问题,而是添加/减去边界区域大小的问题。我不知道一般的方法,但现在只是查看值并进行更正。
【解决方案2】:

如果您将它放在 Window 的代码隐藏中,这是否有效?

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多