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. 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. 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:
public void ChooseInitialPosition(Windo开发者_JAVA百科w 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.
So far, it looks like I can use Visual.PointToScreen for the first part:
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?
Which screen a WPF window is on:
private static Screen GetScreen(Window window) { return Screen.FromHandle(new WindowInteropHelper(window).Handle); }
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?
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;
}
精彩评论