据我所知,如果计算机未使用默认的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?
答案 0 :(得分:27)
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;
}
答案 1 :(得分: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;
}