Reputation: 41
How do I run a Java app with Windows' high-DPI scaling?
I'm trying to run a Java app (JAR file) using JavaSE-1.8 (jre1.8.0_161). The app uses Swing.
On regular screen everything OK but not on a high-DPI display on Windows 10… it's not scaling the Java app; I am getting the right window size but with tiny little menus and icons with impossible-to-read text.
In forums the advice is to move to jre1.9 or more. I installed jre1.10 but in Eclipse I do not see it – it seems the version of Eclipse (Version: Neon.1 Release (4.6.1) I am using is not compatible with that version of Java.
Before moving to Eclipse Oxygen + jre1.10, I wanted to have confirmation it is the right fix to my issue.
Upvotes: 4
Views: 6061
Reputation: 31
This is because Java 7+ added a manifest that tells the OS it knows how to scale correctly when it does not, and is supposedly fixed in Java 9 (https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8080153).
You can confirm this using a zip utility to open javaw.exe as a zip file, and look at .rsrc/MANIFEST/1 (sometimes .rsrc/1033/MANIFEST/1). It should be an xml file with an true element.
If you have MS dev tools (mt.exe) then you can patch the manifest in javaw.exe xml manifest to use a Windows 10 new setting described here (https://blogs.windows.com/windowsdeveloper/2017/05/19/improving-high-dpi-experience-gdi-based-desktop-apps/).
c:\>mt -nologo -inputresource:javaw.exe -out:man.xml
Edit with text editor, replacing
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
with
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">
<gdiScaling>true</gdiScaling>
</asmv3:windowsSettings>
Note that the xml namespace is different.
c:\>mt -nologo -outputresource:javaw.exe;1 -manifest man.xml
c:\>mt -nologo -outputresource:java.exe;1 -manifest man.xml
You can also address this problem by right clicking on the javaw.exe, choosing Properties, compatibility tab, Change High DPI Settings, and choose System (Enhanced). If that solves the problem, then you can use the mt.exe tool as above to patch the exe files so that you can distribute to your thousands of users without them having to manually set the compatibility settings.
Upvotes: 3
Reputation: 387
Or else, you can use following java code to create registry through your application. You may have to open your applicaiton twice.
import com.sun.jna.platform.win32.WinReg;
if(!Advapi32Util.registryKeyExists(WinReg.HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"))
{
Advapi32Util.registryCreateKey(WinReg.HKEY_CURRENT_USER,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers");
}
if(!Advapi32Util.registryValueExists(WinReg.HKEY_CURRENT_USER,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers",
System.getProperty("user.dir") + "\\**application name**.exe"))
{
Advapi32Util.registrySetStringValue(WinReg.HKEY_CURRENT_USER,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers",System.getProperty("user.dir") + "\\**application name**.exe","~DPIUNAWARE");
}
Upvotes: 0