In the previous blog post about High-dots-per-inch (DPI) scaling improvements, we talk about how desktop applications can be blurry or sized incorrectly when run on high-DPI displays. This is especially noticeable when docking and undocking or when using remoting technologies such as Remote Desktop Protocol (RDP).

In the Windows 10 Anniversary Update we chipped away at this problem by introducing mixed-mode DPI scaling and other high-DPI-related APIs. These APIs made it less expensive for developers to update desktop applications to handle dynamic DPI situations (situations where desktop applications are expected to detect and respond to DPI changes at runtime). We’re still working on improving the high-DPI story for you and in this article we’ll go over some of the improvements coming in the Windows 10 Creators Update. Before we dive into that, here’s a quick recap of the issue:

The image above illustrates the types of issues you’ll see in Windows 10 when using multiple displays with different DPI values. In this case a low-DPI primary (“main”) display docked to a high-DPI external display. In this picture you can see:

Some applications (Word) render blurry on the high-DPI display

Some applications (PowerPoint and Skype for Business) are crisp but render at the wrong size

Desktop icons are sized incorrectly on the high-DPI display

Tooltips are sized incorrectly

The desktop watermark is sized incorrectly

Note that these are just a few of the types of issues and that all the items that are too small in this picture could easily be too large if the display topology was reversed (high-DPI primary and low-DPI external display). Spoiler alert: many (but not all) of these issues have been fixed in the Creators Update.

Developer Improvements in the Creators Update

The high-DPI improvements in the Creators Update fall in two categories:

Improvements for desktop application developers

Improvements for end users

Let’s talk about the developer-focused improvements first. For Microsoft to be successful in reducing the number of blurry or incorrectly sized desktop applications that end-users see, updating desktop applications to handle dynamic DPI scaling properly needs to be as easy as possible for you. We are approaching this is by incrementally adding automatic per-monitor DPI scaling to desktop UI frameworks. Here are some of the improvements in the Creators Update:

Per-monitor DPI awareness V2

The Anniversary Update introduced the concept of mixed-mode DPI scaling which let you have different DPI-awareness contexts (modes) for each top-level window within a process, and these contexts could be different than the process-wide default. This enabled you to ease in to the world of per-monitor scaling by focusing on the parts of the UI that matter the most while letting Windows handle bitmap stretching other top-level windows. In the Creators Update we added a new awareness context, (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) which we refer to as per-monitor version 2 (PMv2).

PMv2 is technically a DPI_AWARENESS_CONTEXT and not one of the process-wide DPI awareness modes defined in the PROCESS_DPI_AWARENESS enumeration. PMv2 is designed to provide per-monitor scaling functionality that is missing from the original implementation of per-monitor awareness. This context enables the following:

Child window DPI change notifications

When a top-level window or process is running in per-monitor (V1) mode, only the top-level window is notified if the DPI changes. If you want to pass this notification to child windows that have their own window procedures, it’s up to you to pass along this notification. With PMv2 all child HWNDs in an HWND tree are notified in a bottoms-up, then tops-down manner via two new messages:

WM_DPICHANGED_BEFOREPARENT (bottoms-up)

WM_DPICHANGED_AFTERPARENT (tops-down)

The WPARAM and LPARAM parameters are unused and zero for both of these messages. They are simply nudges to notify your child HWNDs that a DPI change is occurring and has occurred.

Scaling of non-client area

Prior to the Anniversary Update there was no way to have the Windows-drawn non-client area DPI scale (caption bar, system menus, top-level scroll bars, menu bars, etc.). This meant that if you created a per-monitor application you’d be left with incorrectly sized (too big or too small) non-client area after the DPI change without any recourse other than drawing all that stuff yourself. In the Anniversary Update we added an API that you could call to turn on non-client scaling, EnableNonClientDpiScaling but now with PMv2 you get this automatically.

Automatic DPI scaling for dialogs

Win32 dialogs (dialogs that are created from a dialog template via the CreateDialog* functions) did not DPI scale previous to the Creators Update. With PMv2 these dialogs will automatically DPI scale when the DPI changes. If any of your dialog layout is controlled by code you’ll need to make sure that your code doesn’t conflict with the automatic scaling that is being done by Windows. You can use the SetDialogControlDpiChangeBehavior and/or the SetDialogDpiChangeBehavior APIs in this case to tell Windows how you’d like it to handle DPI scaling of your controls or of the whole dialog.

Fine-grained control over dialog scaling

There are scenarios where you’ll want control over how Windows DPI scales dialogs or even children HWNDs of a dialog. When you want to opt a dialog or an HWND in a dialog out of automatic DPI scaling you can use SetDialogDpiChangeBehavior/SetDialogControlDpiChangeBehavior, respectively.

NOTE: SetDialogControlDpiChangeBehavior only affects first-level children of a PMv2 dialog. If you have a more complex dialog tree you’ll have to handle the HWND scaling of child windows yourself.

With these APIs you can opt a specific window in a dialog (or the entire dialog itself) out of DPI scaling functionality. When your dialog is DPI scaled by the system a new font is sent to all HWNDs in the dialog. You might, for example, want to opt out of having Windows send a DPI-scaled font to a specific HWND. You could use SetDialogControlDpiChangeBehavior in this case.

Use GetDialogDpiChangeBehavior and GetDialogControlDpiChangeBehavior to query the scaling behaviors applied to a dialog or to specific dialog HWNDs, respectively.

Windows Common Control improvements

When a DPI changed in per-monitor version 1 (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE) you could resize and reposition your HWNDs, but if any of these HWNDs were Windows common controls (pushbuttons, checkboxes, etc.) Windows would not redraw the bitmaps (which we refer to as “theme drawn parts” or “theme parts” because they’re drawn by UXTheme) for these buttons. This meant that the bitmaps were either too large or too small, depending on your display topology. There wasn’t really anything that you could do about this, short of drawing the bitmaps yourself.

PMv2 helps draw these bitmaps at the correct DPI. Below we’re showing how the bitmaps in common controls in per-monitor version 1 wouldn’t DPI scale properly and how they do DPI scale if they’re in a PMv2 context:

PMv1

Common Control theme parts rendering larger than expected when the window was moved from a high-DPI display (200% scaling) to a low-DPI display (100% scaling)

PMv2

Common control theme parts rendering at the correct size after the window was moved from a high-DPI display (200% scaling) to a low-DPI display (100% scaling)

Specifying DPI awareness fallback behavior

It is recommended that you specify the DPI awareness of your process in the application manifest. In the Anniversary Update we introduced a new DPI awareness tag, <dpiAwareness>. With this tag you can specify a fallback behavior for the process-wide default DPI awareness mode or context. This is useful in that you can specify different DPI awareness modes for when your application is run on different version of Windows. For example, the following manifest settings:

This will result in the following process-wide default on different versions of Windows:

Windows Version

Applied process-wide DPI awareness mode default

Default DPI awareness context for new windows

Vista

System

N/A

Windows 7

System

N/A

Windows 8

System

N/A

Windows 8.1

Per Monitor V1

N/A

Windows 10 (1507)

Per Monitor V1

N/A

November Update (1511)

Per Monitor V1

N/A

Anniversary Update (1607)

Per Monitor V1

Per Monitor V1

Creators Update (1703)

Per Monitor V1

Per Monitor V2

Programmatically setting the process-wide default context

SetProcessDpiAwarenessContext(…) lets you specify the default DPI awareness context for your process programmatically. SetProcessDpiAwareness wouldn’t accept a DPI awareness context so there was no way to specify PMv2 as your process-wide default awareness context programmatically.

End-user DPI-scaling improvements

In addition to the work that we’re doing to make it easier for you, as a developer, to update your desktop applications to be per-monitor DPI aware, we’re also working to make your life as a Windows user better where it comes to using Windows in mixed-DPI environments. Here are some of the improvements that are part of the Creators Update:

DPI-scaling overrides

There are times when a Windows desktop application is defined to run in a certain DPI-awareness mode, such as System DPI awareness, but for various reasons you’d need it to run in a different mode. One scenario for this is when you’re running desktop applications that don’t render well on a high-DPI display (this can happen if the developer hasn’t tested and fixed up their applications for the DPI scale factors seen on the latest hardware). In situations like this you might want to force the application to run as a DPI-unaware process. Although this would result in the application being blurry it would at least be sized correctly. There are situations where this can make an unusable application usable, albeit blurry. You can enable this functionality in the .exe properties:

There are three settings that you can specify:

Setting

Effect

Application

This forces the process to run in per-monitor DPI awareness mode. This setting was previously referred to as “Disable display scaling on high-DPI settings.”

This setting effectively tells Windows not to bitmap stretch UI from the exe in question when the DPI changes

System

This is Windows’ standard way of handling system-DPI aware processes. Windows will bitmap stretch the UI when the DPI changes

System (Enhanced)

GDI Scaling (see below)

“System (enhanced)” DPI scaling

While we want to make it as easy as possible for you to update your applications to handle DPI scaling properly, we fully recognize that there are many applications that can never be updated, for various reasons. For this class of applications, we’re looking at ways that Windows can do a better job of automatically DPI scaling. In the Creators Update you’ll see the first version of this work.

There is new functionality in the Creators Update that results in text and primitives rendering crisply on high-DPI displays for GDI-based apps only. For applications that are GDI-based Windows can now DPI scale these on a per-monitor basis. This means that these applications will, magically, become per-monitor DPI aware. Now keep in mind that this solution is not a silver bullet. There are some limitations:

GDI+ content doesn’t DPI scale

DX content doesn’t DPI scale

Bitmap-based content won’t be crisp

It won’t be possible for end users to determine which apps will benefit from this feature without trying it out on an app-by-app basis.

Even with all of these limitations, when this GDI scaling works it’s quite impressive. So much so that we’ve turned it on by default for some in-box apps. The Microsoft Management Console (mmc.exe) will be GDI scaled, by default, in the Creators Update. This means that many in-box Windows snap ins, such as Device Manager, will benefit from this feature in the Creators Update. Here are some screenshots:

A DPI-unaware application running on a Surface Book High-DPI display (200% DPI scaling)

The same application being GDI scaled (“System (Enhanced)” DPI scaling)

Notice how the text is crisp in the GDI-scaled version of the application (on the right) although the bitmaps are blurry (because they’re being bitmap stretched from a low-DPI to high)

What’s more, this functionality can be turned on for non-Windows application in the exe properties via the “System (Enhanced)” compatibility setting under “Override high-DPI scaling behavior. Scaling performed by:” (under the compatibility tab of the properties for an exe. See the screenshot earlier in this post). Note that this option isn’t available for Microsoft applications that ship in-box with Windows.

Internet Explorer

Per-Monitor DPI awareness support was first introduced in Windows 8.1 but many in-box Windows applications did not properly adopt this DPI scaling model. One of the most notable offenders was Internet Explorer. In the Creators Update IE has been updated to dynamically DPI scale.

Before the Creators Update, if you moved Internet Explorer to a display with a different DPI or otherwise changed the DPI of the display that it was on (docking/undocking/settings change/RDP/etc.) the content of the web page you were viewing would DPI scale but the app frame would not. In the image below we’re showing Internet Explorer and Edge, side by side, while being run on a secondary display with 100% display scaling. In this scenario, the primary display was using a high-DPI scale factor and then the app windows were moved to the low-DPI secondary display. You’ll see that the Edge UI scaled down but the Internet Explorer frame still rendered at the scale factor of the primary display.

Notice:

The text in the navigation bar is huge

The navigation buttons are huge

The vertical scroll bar is huge

The minimize/maximize/close buttons are rendered at the correct size but are spaced out as if they were on the high-DPI display

Here is how things look in the Creators Update:

Desktop icons

One of the biggest complaints we’ve heard (and experienced ourselves) was that the desktop icons would not DPI scale if you were running in “extend” display mode with multiple displays containing different DPI/display scaling values. Updates in the Creators Update fix this issue. Here is what you’d see before the Creators Update:

And here is what you’ll see in the Creators Update:

Office sizing issues

Although this isn’t specifically tied to the Creators Update, Office 2016 with the latest updates no longer has issues with Skype for Business and PowerPoint being sized incorrectly in mixed-DPI configurations.

What we didn’t get to

Hopefully you’ll enjoy these improvements, both as a developer and as an end user. While we’ve done a ton of work and are hopefully moving the needle, so to speak, on how Windows handles dynamic DPI support there is still a lot of work ahead of us. Here are a few things that we still need to work on:

High-DPI developer documentation

As of writing this blog, the high-DPI documentation available on MSDN is horribly outdated. The guides for writing per-monitor DPI aware applications were written in the Windows 8.1 timeframe and haven’t seen any significant updates since then. Also, many Windows API have DPI sensitivities that are not documented. That is to say that some Windows API will behave differently if they’re being called from a system-DPI-aware context vs. a per-monitor DPI aware context. All of this will need to be cleaned up and well documented so that you’re not left guessing when trying to update your application. We’re working on it, so keep an eye out for some improvements here.

“Magic numbers”

There are things in Windows that when scaling to higher DPI, don’t get it quite right. The reason for this is lurking “magic numbers” in the code that assumes that the world is always running at 96 DPI. While, in the past, some of these “magic numbers” didn’t result in significant problems, as DPI increases these issues become more and more noticeable. We’ll need to scrub Windows for as many of these as we can find. A couple of places that you can see “magic numbers” in use are 1) the width of a Windows button border and 2) the padding in non-client menu bars (such as can be seen in Notepad). In the case of the menu bar, as you run Notepad on higher and higher DPI values, the space between each menu item decreases.

Child-window DPI scaling

In the Windows 10 Anniversary Update we introduced mixed-mode DPI scaling (sub-process DPI scaling) that enabled you to have different DPI scaling modes within each top-level window in an application. We do not, however, support child-window DPI scaling. There are many interesting scenarios where this could come in handy, such as when you’re hosting external HWND content that could be running in a different DPI awareness mode. If you don’t have the ability to control the code that generates that hosted content it would be nice to have Windows DPI scale it for you. Unfortunately, this is not supported today.

MFC

Although we’ve added per-monitor DPI scaling support to Win32, WPF and WinForms, MFC does not natively support this functionality.

Display settings page & mouse input

When you have multiple displays with different DPI/Display Scaling values, the Display Settings Page will show you a representation of your display topology. The displays are represented in terms of their resolution, whereas it might be better if they were represented per their physical/real-world dimensions.

Furthermore, when you have two displays that are nearly the same physical size but with different display scaling values (one 4K and one 1080p display, for example) and move the mouse between the displays you can hit “dead zones” where the mouse cannot move. Here it would be more intuitive to have the mouse movement reflect the physical size/dimensions of the displays, not the resolutions of the displays.

Dragging Windows

When you drag an application window from one display to a display with a different DPI, you’ll see an oddly shaped representation of the window. Part of the window will render at the wrong DPI for the display that it’s on, until you move enough of it to the new display. At that point the window snaps to the new DPI and looks odd on the display that it came from. It would be nice to have a smoother transition here.

The need to log out and back in

Most of all, the fact that you have to log out and back into Windows to get most applications to render correctly after a DPI change is a huge pain-point. We do not currently have a solution for this beyond having applications updated to support per-monitor DPI awareness.

Conclusion

Again, hopefully you’ll enjoy these improvements. We still have a long way to go but we are working on improving Windows 10 high-DPI functionality and support. Do you have any other ideas of things that you’d like to see in this space? If so, please leave a comment below or reach out @WindowsUI.

Some great improvements, and I appreciate the transparency on what you’ve got left to work on.

I just wanted to bring attention to one area that wasn’t mentioned but still hasn’t been fixed in Edge, which, as I understand it, is a UWP app, so it should “just work”(tm), and that’s the primary scroll bar.

While the height of the buttons on the scrollbar and the little arrow button icons all adjust when moving edge between monitors with different DPI scaling values, the width of the scrollbar does not. The result is oddly wide vertical scrollbars in Edge if you move an Edge window from a HighDPI primary monitor (like the 200% Surface Book) to a standard external monitor (say a 100% DPI 1080p display). Strangely enough, Edge makes scrollbars inside a web page (ex: a textarea, or a a div with overflow:scroll) scale correctly. It’s just the primary scrollbar that seems half finished.

Thank you for being transparent about what progress has been made and especially what is still being worked on!

The examples and information provided are exactly what we need and I wish the other official Microsoft Blog posts (and social media accounts) would follow this example. Too often other departments refuse to even acknowledge what they would like to improve, let alone that they recognize what is an issue. “We have nothing to say on that” only serves to make them seem ignorant to their own products/users/developers.

Even just stating that “It would be nice to have a smoother transition here” is a great example of awareness within the team/company. Obviously priorities dictate what work actually happens or not but that recognition of an issue is enough and very welcome to see.

Hey you guys really did a lot in Creators Update! You made GDI-based-text rendered much better in vertical anti-AA. You fixed DPI issue for PowerPoint and so. You fixed the desktop icon issue. Windows 10 is full of hope for its faster iteration, and you guys really did a great job!

Improving DPI-scaling in Windows is paramount.
While improvements can never come soon enough, much has already been done since Windows 8.1, and the team’s commitment to ship improvements at each Windows release is greatly appreciated.

Thank you so much for your continued hard work, and especially for officially acknowledging the issues under “magic numbers” and “dragging windows”. I hope to see these issues resolved soon. GDI scaling is quite impressive!

A few other non-obvious examples of magic numbers would include the thickness of the text cursor, the width of shadows under windows/menus, the blur radius of the taskbar/start menu, and many other stroke widths throughout the system. (Office is a very big offender.)

There’s also a major issue when a DPI-unaware game tries to do borderless fullscreen and changes the resolution. Since it’s still being scaled by the compositor, it’s either too big or too small. Per-monitor-DPI compounds the problem because an application which wasn’t being scaled may be subject to scaling after the resolution change.

I think the best solution would be to make it so that if a DPI-unaware game changes the resolution, that monitor’s DPI is temporarily set to 96 until the old resolution is restored. Likewise, if a system-DPI-aware application changes the resolution, the monitor’s DPI should be set to the system DPI. In this way, from the perspective of the game, the desktop resolution will always match the resolution the game tried to set, and when it extends its window to that resolution, it will fill the screen correctly.

Can you guys shed some light on why this problem hasn’t been fixed completely? On my MacBook, I have had no issues at all. But on my Surface Pro 4, the issues are still there, although it is much improved on the Creators Update. I wonder if the Windows team could implement something similar to Mac OS to address this problem?

Great post, I love how DPI scaling is improving. Especially as I am using a Surface Book with 4K screen and 3 external (main) normal-resolution monitors.
But I just found a bug with the new IE display aware scaling: When opening a taskbar-pinned IE site, the app icon and the back and forward buttons are wrongly scaled, when moving to an other non-system-dpi screen…
Cheers, Philippe

But, I am having this exact issue now, too. I have my pc hooked up to my 4K TV, running at 3840 x 2160, and immediately after this update, the font scaling look absolutely awful. Like, unusably bad to the point that I want to roll it back..

Just to mention, I have found that in the following case, you get some strange behavior with the Win32 dialogs:
1. Set up an external monitor with a higher DPI setting, and set the external monitor to be ABOVE the primary monitor (so your mouse passes to the external monitor when you push it up over the upper edge of the primary monitor).
2. Open a Win32 dialog (in my case, Microsoft.Win32.OpenFileDialog) on the primary monitor.
3. Drag the dialog slowly back and forth between the two screens- the first time you pull it back to the primary monitor, the dialog has a seizure for about 5 seconds before resolving to an incoherent window.

I am on creators update on a dual GPU laptop (Intel 530 + Nvidia Quadro M1000M). Since the creator update, the type in MMC based apps are blurry. They didn’t use to be blurry before. The Nvidia app is set to not use it’s GPU for this app (which is the default setting: use the integrated graphics card unless specified otherwise).

When logged in via RDP (with Microsoft’s RD Client v8.1.30) from my iPad, only the context menu spacing is huge while the text is very small. So huge that I can’t get down to properties, there is a microscopic down arrow but it’s almost impossible to hit it enough times w/o missing to get all the way down to properties

Funny, right clicking start for that [awesome new context menu, it’s spaced normally

“The need to log out and back in
Most of all, the fact that you have to log out and back into Windows to get most applications to render correctly after a DPI change is a huge pain-point. We do not currently have a solution for this beyond having applications updated to support per-monitor DPI awareness.

Do you have any other ideas of things that you’d like to see in this space? If so, please leave a comment below or reach out @WindowsUI.”

This is the biggest issue we’re facing today, please try to remove the need to log out and back in!

I don’t know of a way to do that, easily, from a system-DPI-aware process. You could theoretically track the system DPI value (which doesn’t change during the lifetime of the process) and then create a new thread in per-monitor DPI aware thread context (see mixed-mode DPI scaling: 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/) and then query the display DPI of the primary display, but it will be difficult to determine which display is the primary display (it’s top left coordinates should be 0,0). “Display DPI” is the DPI of a display as reported to a per-monitor DPI-aware thread/process, and it can be different from the “system DPI” (the DPI that Windows used when the Windows session was first started). I haven’t tried this so I can’t confirm that it works, but this should theoretically tell you if the DPI of the primary display is different than the system DPI, which means that a DPI change has occurred and the user has not logged out.

I added the section below to my app.config file in my ClickOnce Win Form app. After publishing and clicking to install the app, I get the following error: Application cannot be started. Contact the application vendor. Here is part of the details from:
Following errors were detected during this operation.
* [06/20/2017 1:02:25 PM] System.Deployment.Application.DeploymentException (Activation)
– Activation failed due to a Windows Side-by-Side error. System Event Log may contain some more information about this failure.
– Source: System.Deployment

This occurs on all my ClickOnce apps. I don’t think it is recognizing this section. Any help would be appreciated.

Hi David, can you share, on OneDrive or similar location, your app.config file and ClickOnce manifest (this would be in your ‘publish’ folder under a path “Application Files\your_app_1_0_0_0\your_app.exe.manifest”?

Peter and WindowsUI team, great post. Thanks for bringing improvements to Creator’s and Fall updates!

Many of my customers prefer to disable Windows scaling and set one of their panels to a lower than native resolution (1/4 for example) to match the effective dpi of other screen and bypass all the weird artifacts when dragging windows between screens. In back to back testing with users, nobody could tell that the panel was at non-native resolution and they preferred the usability. Here is a demo video showing the issue and solution my customers prefer:

I was wondering if you look into telemetry to understand how often folks in the field are doing such manual tweaks? In particular, on which devices do folks tend to use non-native resolution in multi-monitor configuration? And what other neat tidbits of info can you glean from cosmos for those system to understand *why* customers are using their device this way? Are there any apps that are statistically more likely to be used in these instance? I see >80,000 downloads of the regkey hacks I put together for my customers which is a small sample, but big enough to know that I’m on to something…

Hi Michael, I’ve never coded this myself so I can’t say for sure it will work, nor do I have a sample to point you towards, but I think what you’re asking is how you can determine that the display scale factor has changed such that system-DPI-aware apps are blurry and would be crisp if the user signed out and signed back in. If this is the case, unfortunately there isn’t an API that will tell you this.

If this is the case, you’ll want to determine if your app is being DWM scaled on the primary display. That will only happen if the scale factor of the primary display is different than the “system” DPI. The “system” DPI is the DPI that was in use on the primary display at the point that the Windows session was first started (when the user logged in).

Theoretically, you could detect this by comparing the system-DPI that Windows provides to the value of the DPI of the primary display. If the two do not agree, then you can infer that the process and/or top-level window is being scaled by Windows.

Here are some more details:
1) This is only relevant to system-DPI aware processes
2) If the DPI of the primary display has changed, then system-DPI aware processes will be bitmap-stretched on the primary display
3) If you call GetDpiForSystem, Windows will give you the DPI from before the DPI of the primary display changed (assuming that the DPI changed while your process was running)
4) You can then get the DPI of the primary display via GetDpiForMonitor, with the monitor corresponding to point (0,0), which is the upper-left corner of the primary monitor.
5) You’ll need to call this API from a per-monitor thread context, so call SetThreadDpiAwarenessContext and switch the thread context to DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 before calling this API (be sure to restore the previous thread context to avoid problems).
6) Your app will only benefit from logging out and back in if it’s on the primary display. Logging out and back in doesn’t help apps that are on secondary displays (if the secondary display has a scale factor that is different than that of the primary).

PS: The problem is not only that things are blurry but having apps that rely on the accessibility layer of the UI.
When the logout is required the accessibility layer reports incorrect bounds back to our app.
Once the logout has been done the bounds are correct.

Could you please provide more details and repro steps? Accessibility/Narrator should still work when a system-DPI-aware process or top-level window is being bitmap stretched by the DWM. What is going on in your scenario? Are you using mixed mode (SetThreadDpiAwarenessContext) to have different top-level windows run in different DPI awareness contexts?

When using a fullscreen window (a WS_POPUP window the same size as a monitor) I don’t receive the WM_GETDPISCALEDSIZE message – is this intentional? Instead of being able to override the scaled size for a fullscreen window, I immediately receive WM_DPICHANGED with a scaled rect which is not what you want for a fullscreen window (as opposed for a windowed one, which should resize on DPI change). This leads to different behaviour than Windows 8.1, which doesn’t give a scaled rect but instead the original monitor-sized rect when receiving WM_DPICHANGED for a fullscreen window.

I have to override this behaviour by totally ignoring WM_GETDPISCALEDSIZE, and in WM_DPICHANGED checking if the window is fullscreen and calling SetWindowPos() with it’s current rect rather than the recommended one if it is.

“I have to override this behaviour by totally ignoring WM_GETDPISCALEDSIZE, and in WM_DPICHANGED checking if the window is fullscreen and calling SetWindowPos() with it’s current rect rather than the recommended one if it is.” – My mistake, I don’t have to call SetWindowPos() if I want to keep a fullscreen window the same size. The difference is that Windows 10 v1703 gives a scaled rect in it’s lParam for a fullscreen window whereas Windows 8.1 doesn’t, and you can’t override this behaviour with WM_GETDPISCALEDSIZE because it doesn’t get sent for fullscreen windows.