Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is 1920 device-independent units not 1920 pixel with 96 DPI?

My Windows settings are set to have a DPI of 96. However when I create the following Window it will be a little smaller then my screen (which is set to the resolution 1920*1080):

<Window x:Class="WPF_Sandbox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_Sandbox"
        mc:Ignorable="d"
        Title="MainWindow"
        Width="1920">
</Window>

According to this msdn blog post:

1 device independent pixel = 1/96 inch.
1 physical pixel = 1/DPI (dependent on the system DPI)

Default system settings usually choose a DPI of 96 so these two types of pixels come out to be the same size.

However this does not seem to be the case since my Window is clearly less then 1920 pixel wide.
If I maximize the Window and inspect its ActualWidth it appears to be 1936.

Why is this the case?

like image 740
Tim Pohlmann Avatar asked Mar 23 '16 15:03

Tim Pohlmann


1 Answers

The question is more along the lines of:

Why does Window.ActualWidth report a width that does not appear to be the 'real' width of the Window?

The answer is that what looks like the full width of the window isn't exactly the full width.

When you set the Width, query the ActualWidth, or even use GetWindowRect to get the "no-lies what does windows think my width is", you're setting or getting the width of the Window including invisible parts.

Those invisible parts, especially on Windows 10, includes a little bit of extra space for making it easy for users to resize the window even if they're a little bit off of the border:

resize off of the window

(note that my mouse is not on the border but rather a bit off to the right)

This means that when you maximize your window, your width is still "padded" with that invisible space, and thus your window size will be bigger than your screen size.

How can you retrieve the width of the extra space? GetSystemMetrics with SM_CXSIZEFRAME and SM_CXPADDEDBORDER is your friend here (example includes code from pinvoke.net):

int extraBorderStuff = GetSystemMetrics(SystemMetric.SM_CXSIZEFRAME)
                       + GetSystemMetrics(SystemMetric.SM_CXPADDEDBORDER);
double realWidthForSure = ActualWidth - borderSize * 2;

If you then maximize your window, you should notice that realWidthForSure should equal your 1920px that you'd expect.

like image 171
zastrowm Avatar answered Oct 17 '22 17:10

zastrowm