Why some programs misbehave on different screens but some don't
Modern Windows applications should include a manifest, which is an XML document that's usually embedded in the main EXE file. Manifests declare several important things, including whether the program will ask to be UAC-elevated and, more relevantly, the level of DPI awareness. If a program understands how to redraw itself for different dots-per-inch settings, it is DPI aware.
This Old New Thing article mentions the three levels of DPI awareness available on Windows 8.1 and up: no awareness (in which case the system will scale the program up, producing blurriness), system DPI awareness, and per-monitor DPI awareness. The difference between those last two is that per-monitor-DPI-aware programs need to redraw themselves depending on which monitor they're on, since different monitors can have different DPIs. System-DPI-aware programs scale themselves for the highest-DPI monitor, then the system scales them down as appropriate.
I inspected the manifests of the programs you mentioned by searching with a hex editor for the string <dpiAware
. These are my results:
- Internet Explorer 11:
True/PM
(per-monitor aware)
- Microsoft Word 2016:
True
(system aware)
- Adobe Reader XI:
True/PM
Word, therefore, is partially handled by the system, which explains why it works as you expect. The other programs should handle themselves, but evidently they messed up. Per-monitor-DPI-aware programs receive information about a monitor change by the WM_DPICHANGED
window message, but these apparently don't do the right thing in response to that.
Further reading: Writing DPI-Aware Desktop and Win32 Applications
How to fix it
It's possible to use the compatibility infrastructure to force blurriness (i.e. make the programs not DPI aware at all), but it seems that you want to make these programs only partially DPI-aware (i.e. use the system level). The only I way I can think of to do that is to whack the EXE with a hex editor and change the manifest. I like XVI32, no affiliation.
Run your hex editor as administrator and open the program file you want to change. Search for <dpiAware
, then read a bit ahead until you find True/PM
(or a different capitalization of the same). It's probably followed immediately by the </dpiAware>
closing tag, so we'll write over it like so:
Old: True/PM</dpiAware>
New: True</dpiAware>
Make sure to overwrite the extra space (re>
) with spaces. You might have to fiddle the file permissions before you save. Once the file is changed, it will be only a system-DPI-aware program.
It appears that the build of Internet Explorer that comes with Windows 10 uses SetProcessDpiAwareness
rather than a manifest to set the DPI awareness. Therefore, we need to get a little more serious with the hex editing. Search for windowsSettings
, then move your cursor to immediately after the closing bracket of the previous application
tag. Overwrite with all of this:
<windowsSettings><dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware></windowsSettings></application><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><!--
Once you're done, it should look like this (I highlighted the new part in red and placed the blue cursor at the start of the changed portion):
That takes advantage of the extra spaces and comments in the default manifest to insert our new setting and move the compatibility
element forward a bit. When dpiAwareness
is set in the manifest, the SetProcessDpiAwareness
function will have no effect.
There is a chance that Windows Resource Protection will roll back the changes, so if the program is automatically reverted, you might need to set up a script to recopy the new version over it.
Caution! It's very important that you overwrite rather than insert or delete characters. Inserting or deleting will shift the rest of the executable data, breaking a lot of things. If you make a transcription error, do not press Backspace or Delete. Instead, move your cursor back and overwrite your error with the correct character(s). If you haven't used a hex editor before, you should make a back-up of the EXE file before modifying it.