简体   繁体   English

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

[英]WPF: Converting between screen coordinates and WPF coordinates

I understand that WPF coordinates are different from "real" screen coodinates (pixel coordinates) if the computer is not using the default DPI setting. 据我所知,如果计算机没有使用默认的DPI设置,WPF坐标与“真实”屏幕坐标(像素坐标)不同。 In my program I want to (1) figure out which monitor a WPF window is on and (2) open another window in the bottom-left corner of the same monitor. 在我的程序中,我想(1)找出WPF窗口所在的监视器,以及(2)打开同一监视器左下角的另一个窗口。 I heard there is no equivalent of Screen for WPF so I use the WinForms version, as follows, which works fine at the default 96 DPI: 我听说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;
}

But at other DPIs, both steps work incorrectly, and may put the window completely off-screen. 但在其他DPI中,这两个步骤都不正确,并且可能会使窗口完全脱离屏幕。

So far, it looks like I can use Visual.PointToScreen for the first part: 到目前为止,看起来我可以在第一部分使用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;

I'm not sure if this is quite right, as it may not account for the borders correctly. 我不确定这是否正确,因为它可能无法正确解释边界。 But the second part is more important. 但第二部分更重要。 How do I convert the screen rectangle "scr" into WPF space, in order to set Left and Top correctly? 如何将屏幕矩形“scr”转换为WPF空间,以便正确设置Left和Top?

  1. Which screen a WPF window is on: WPF窗口在哪个屏幕上:

     private static Screen GetScreen(Window window) { return Screen.FromHandle(new WindowInteropHelper(window).Handle); } 
  2. Open another window in the bottom-left corner of the same screen: 打开同一屏幕左下角的另一个窗口:

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

Does this work if you place it in the code-behind for your Window? 如果将它放在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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM