How to position windows correctly at 120 DPI in WPF

If you want to place a window at a specific place in WPF, it will work pretty much as you expect—unless your DPI is 120 (the default is 96). Here’s a sample that shows how to put it where you want.

In this case, I want to put a window just under another control, aligned to its left side.

 

CalcWindow calc = new CalcWindow();
Point point = this.PointToScreen(
    new Point(0, this.ActualHeight));
 
PresentationSource source = 
    PresentationSource.FromVisual(control);
 
double dpiX = 
    96.0 * source.CompositionTarget.TransformToDevice.M11;
double dpiY = 
    96.0 * source.CompositionTarget.TransformToDevice.M22;
 
calc.Left = point.X * 96.0 / dpiX;
calc.Top = point.Y * 96.0 / dpiY;
 
calc.Show();

The crux of this is getting the current DPI. You could use P/Invoke to call native methods to get this, but the transformation matrix contains the same information as well.


Check out my latest book, the essential, in-depth guide to performance for all .NET developers:

Writing High-Performance.NET Code by Ben Watson. Available now as an eBook at:

2 thoughts on “How to position windows correctly at 120 DPI in WPF

  1. SpeziFish

    Great, exactly what I need. Thanks.
    But in my case it works even with out the dpi parameter:


    double dpiX = source.CompositionTarget.TransformToDevice.M11;
    double dpiY = source.CompositionTarget.TransformToDevice.M22;
    calc.Left = point.X / dpiX;
    calc.Top = point.Y / dpiY;

  2. Ivo Milanov

    Actually the PointToScreen converts a point measured in DIPs to a point measured in screen cordinates – e.g. PIXELS.

    This means that the DPI setting must be taken into account if screen resolution is different than 96 in the case of which one DIP == one PIXEL.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>