{"id":2236,"date":"2018-10-08T20:05:34","date_gmt":"2018-10-09T00:05:34","guid":{"rendered":"http:\/\/ninecrows.com\/career\/?p=2236"},"modified":"2018-10-08T13:50:32","modified_gmt":"2018-10-08T17:50:32","slug":"win32-multiple-monitors","status":"publish","type":"post","link":"https:\/\/ninecrows.com\/career\/2018\/10\/08\/win32-multiple-monitors\/","title":{"rendered":"Win32 Multiple Monitors"},"content":{"rendered":"\n<p>Spent some time over the weekend looking at APIs in windows that give access to the monitor configuration of the system that code is running on.<\/p>\n\n\n\n<p>I tend to run on systems with several monitors (usually as many as is practical). Ideally, I&#8217;d like to create tools that can use the available display real-estate in helpful ways.<\/p>\n\n\n\n<p>The main API involved is\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/Winuser\/nf-winuser-enumdisplaymonitors\">EnumDisplayMonitors<\/a> which will invoke your provided <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/winuser\/nc-winuser-monitorenumproc\">callback function<\/a> with the HMONITOR for each monitor that is recognized by the system. Calling\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/winuser\/nf-winuser-getmonitorinfow\">GetMonitorInfoW<\/a> can then provide some of the details of each display in a\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/winuser\/ns-winuser-tagmonitorinfoexa\">MONITORINFOEX<\/a> structure.<\/p>\n\n\n\n<p>One oddity in all of this is that a monitor with a scaling factor applied (my 4K monitor is set to 150% scale factor for usability reasons) returns the post-scaling size with a gap in the coordinate system that reflects the &#8216;missing&#8217; pixels. In my case the small monitor I use to keep an eye on the router is logically far to the right of the left hand edge of the big monitor.<\/p>\n\n\n\n<p>There is a supplementary API call <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/shellscalingapi\/nf-shellscalingapi-getscalefactorformonitor\">GetScaleFactorForMonitor<\/a> which returns a\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/shtypes\/ne-shtypes-device_scale_factor\">DEVICE_SCALE_FACTOR<\/a> indicating the current scale factor for a given monitor. This is a little bit strange on my system as the big monitor appears to be set for 150% scaling but the API call shows 140% scaling. The size numbers match what I&#8217;d expect for 150% so something must be a bit off here&#8230;<\/p>\n\n\n\n<p>Interesting API to look into\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/shellscalingapi\/nf-shellscalingapi-getdpiformonitor\">GetDpiForMonitor<\/a> and\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/shellscalingapi\/ne-shellscalingapi-monitor_dpi_type\">MONITOR_DPI_TYPE.<\/a><\/p>\n\n\n\n<p>Looks as if the <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/shellscalingapi\/nf-shellscalingapi-setprocessdpiawareness\">SetProcessDpiAwareness<\/a> API (with <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/shellscalingapi\/ne-shellscalingapi-process_dpi_awareness\">PROCESS_DPI_AWARENESS<\/a>\u00a0and <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/hidpi\/wm-dpichanged\">WM_DPICHANGED<\/a>) may have a part in all of this as well&#8230;deciding whether\u00a0the process gets presented DPI aware or virtualized display metrics.<\/p>\n\n\n\n<p>Curious translation in\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/physicalmonitorenumerationapi\/nf-physicalmonitorenumerationapi-getphysicalmonitorsfromhmonitor\">GetPhysicalMonitorsFromHMONITOR\u00a0<\/a> could use a bit of a look.<\/p>\n\n\n\n<p>I need to read more of the DPI aware and multi-monitor articles before I&#8217;m done here. I also want a better idea of how this functionality interacts with WPF user interfaces as I&#8217;m likely to build the upper layers that way.<\/p>\n\n\n\n<p>This certainly gets more complicated with display scaling and DPI calculations in the mix.<\/p>\n\n\n\n<p>Some more relevant articles (I haven&#8217;t read these all in detail yet):<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/hidpi\/high-dpi-desktop-application-development-on-windows\">High DPI Desktop Application Development on Windows<\/a><\/li><li><a href=\"https:\/\/blogs.windows.com\/buildingapps\/2017\/05\/19\/improving-high-dpi-experience-gdi-based-desktop-apps\/\">Improving the high-DPI experience in GDI based Desktop Apps<\/a><\/li><li><a href=\"http:\/\/www.drdobbs.com\/windows\/coding-for-high-dpi-displays-in-windows\/240168736\">Coding for High-DPI Displays in Windows<\/a><\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/hidpi\/declaring-managed-apps-dpi-aware\">Developing a Per-Monitor DPI-Aware WPF Application<\/a><\/li><li><a href=\"https:\/\/blogs.windows.com\/buildingapps\/2016\/10\/24\/high-dpi-scaling-improvements-for-desktop-applications-and-mixed-mode-dpi-scaling-in-the-windows-10-anniversary-update\/\">High DPI Scaling Improvements for Desktop Applications and \u201cMixed Mode\u201d DPI Scaling in the Windows 10 Anniversary Update (1607)<\/a><\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/winauto\/uiauto-screenscaling\">Understanding Screen Scaling Issues<\/a><\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/gdi\/multiple-display-monitors\">Multiple Display Monitors<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Spent some time over the weekend looking at APIs in windows that give access to the monitor configuration of the system that code is running on. I tend to run on systems with several monitors (usually as many as is practical). Ideally, I&#8217;d like to create tools that can use the available display real-estate in &hellip; <a href=\"https:\/\/ninecrows.com\/career\/2018\/10\/08\/win32-multiple-monitors\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Win32 Multiple Monitors<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[7,44],"tags":[],"class_list":["post-2236","post","type-post","status-publish","format-standard","hentry","category-topics","category-win32"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p7F2Qc-A4","jetpack-related-posts":[],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/posts\/2236"}],"collection":[{"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/comments?post=2236"}],"version-history":[{"count":6,"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/posts\/2236\/revisions"}],"predecessor-version":[{"id":2242,"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/posts\/2236\/revisions\/2242"}],"wp:attachment":[{"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/media?parent=2236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/categories?post=2236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ninecrows.com\/career\/wp-json\/wp\/v2\/tags?post=2236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}