{"id":133,"date":"2011-01-07T20:25:09","date_gmt":"2011-01-07T09:25:09","guid":{"rendered":"http:\/\/blog.quppa.net\/2011\/01\/07\/pixel-measurements-in-wpf\/"},"modified":"2011-01-07T20:25:09","modified_gmt":"2011-01-07T09:25:09","slug":"pixel-measurements-in-wpf","status":"publish","type":"post","link":"https:\/\/www.quppa.net\/blog\/2011\/01\/07\/pixel-measurements-in-wpf\/","title":{"rendered":"Pixel Measurements in WPF"},"content":{"rendered":"<p>Part of the beauty of the Windows Presentation Foundation is that it is designed to be <a title=\"MSDN: WPF Graphics Rendering Overview\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms748373.aspx#visual_rendering_behavior\">resolution independent<\/a> \u2013 that is, a WPF application should scale perfectly no matter the system\u2019s DPI setting (excluding any bitmap graphics, which mightn\u2019t look as nice as the vector parts).<\/p>\n<p>Instead of measuring things in pixels, WPF uses Device Independent Units (DIUs). If you only ever use 96 DPI (100%), you won\u2019t notice the difference: at that setting, 1 pixel is the same as 1 DIU. Increase the system DPI, though, and this will no longer hold true. For example, at 120 DPI (125%), 1 DIU will be represented as 1.25 pixels. At 144 DPI (150%), 1 DIU = 1.5 pixels. At 192 DPI (200%), 1 DIU = 2 pixels.<\/p>\n<p>Notice that at 120 DPI and 144 DPI, the number of pixels in 1 DIU is not an integer. In cases like these \u2013 when edges fall in the middle of screen pixels \u2013 WPF <a title=\"MSDN: Pixel Snapping in WPF Applications\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa970908(v=VS.90).aspx\">uses anti-aliasing by default<\/a>. This can, however, result in lines that seem blurry (after all, that\u2019s what anti-aliasing does). If this behaviour is undesirable, one can use UIElement\u2019s <a title=\"MSDN: UIElement.SnapsToDevicePixels Property\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.uielement.snapstodevicepixels.aspx\">SnapsToDevicePixels property<\/a>.<\/p>\n<p>WPF\u2019s built-in handling of DPI scaling is great: in most cases, it should be transparent to both the programmer and user.<\/p>\n<p>Sometimes, though, one might want to measure lengths in pixels, not DIUs. For example, Keiki\u2019s custom window border for when the DWM (Aero) is disabled needs to be 1 pixel thick at any DPI (this is how the system\u2019s notification area applications look). So, how can we specify this?<\/p>\n<p>First, we need to get the system\u2019s DPI setting:<\/p>\n<pre class=\"lang:c# decode:true \">\/\/ get the handle of the window\nHwndSource windowhandlesource = PresentationSource.FromVisual(this) as HwndSource;\n\/\/ work out the current screen's DPI\nMatrix screenmatrix = windowhandlesource.CompositionTarget.TransformToDevice;\ndouble dpiX = screenmatrix.M11;\ndouble dpiY = screenmatrix.M22;<\/pre>\n<p>dpiX and dpiY will hold values like 1.0 (96 DPI), 1.25 (120 DPI), 1.5 (144 DPI) and 2.0 (192 DPI).<\/p>\n<p>To specify a pixel measurement, we simply divide the DIU measurement by the DPI factor (dpiX and dpiY should always be the same \u2013 at least in Windows 7 and earlier):<\/p>\n<pre class=\"lang:c# decode:true \">WindowBorder.Margin = new Thickness(3 \/ dpiX);<\/pre>\n<p>This will make the margin 3 pixels thick at any DPI. (For example, at 120 DPI, dpiX = 1.25. 3 \/ 1.25 = 2.4 DIUs. 2.4 DIUs will be converted by WPF to 3 pixels.)<\/p>\n<p>Fedir Nepyivoda has a neat solution to this problem: instead of manually converting DIU measurements, he created a PixelBorder control (inheriting from Border) that overrides MeasureOverride. Have a look <a title=\"WPF Snippets and Hacks: Border with exact 1 pixel width or height regardless of the screen DPI\" href=\"http:\/\/wpfhacks.blogspot.com\/2010\/09\/border-in-wpf-with-exact-1-pixel-height.html\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part of the beauty of the Windows Presentation Foundation is that it is designed to be resolution independent \u2013 that is, a WPF application should scale perfectly no matter the system\u2019s DPI setting (excluding any bitmap graphics, which mightn\u2019t look as nice as the vector parts). Instead of measuring things in pixels, WPF uses Device &hellip; <a href=\"https:\/\/www.quppa.net\/blog\/2011\/01\/07\/pixel-measurements-in-wpf\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Pixel Measurements in WPF&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[46,48,82,97,123,185],"class_list":["post-133","post","type-post","status-publish","format-standard","hentry","category-programming","tag-diu","tag-dpi","tag-measurement","tag-pixels","tag-scaling","tag-wpf"],"_links":{"self":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/posts\/133","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/comments?post=133"}],"version-history":[{"count":0,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/posts\/133\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/media?parent=133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/categories?post=133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/tags?post=133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}