Experimental Windows high DPI support on develop branch

We’ve just released experimental support for building DPI aware applications on Windows 8.1+ to the develop branch. This means that JUCE projects built with these changes will be per-monitor DPI aware and will dynamically scale with the DPI of the monitor that they are on, replacing the previous behaviour which was to always use the DPI of the main monitor and to defer to Windows to bitmap stretch the UI on other monitors (often resulting in blurry text, graphics etc.).

Alongside this, the VST and VST3 client and hosting code has been updated to support the Windows scaling APIs making it possible to build and host DPI aware VST and VST3 plug-ins on Windows (the AudioPluginHost example has been updated to showcase these changes).

Please give these changes a go and report back with any issues!


This sounds super important! About time we upgraded JUCE in a few projects too :slight_smile:

Eek! Just raised an issue with Projucer (build for Win32/Win7/Develop) - fails (Screenshot of Debug issue) attached ProjucerWontStart


I’m trying this now and I’m seeing some issues with the plugin size not being correct when the audio plugin host hosts my plugins in compatibility mode. Some pixels get cropped off at the bottom (I guess 10-16… about half the window bar height and my windows machine uses 200% scaling), but that issue might be caused by my code. Once I switch “enable dpi awareness” on, the plugin scale properly and have the correct size.

However, the dpi awareness setting doesn’t seem to be stored in the filtergraph… so on relaunch, everything is broken again - could it store the setting in the filtergraph? Ideally this setting would be per plugin class, not per instance … so maybe it should be enabled in the plugin list and not in the instance menu?

I had a look. The window jumps around quite erraticaly when dragging between monitors with different DPI settings.

I tried to patch this up in the Demo runner and these are my observations:

  • You need the WM_DPICHANGED handler. The given RECT keeps the window under the cursor and ensures it has the same logical client area size after the DPI change. Update scaleFactor and call the listeners here.

  • We receive a WM_WINDOWPOSCHANGING event before receiving WM_DPICHANGED, to report the user is dragging the window. During this event, the window is already on the monitor with the different DPI but the window still has the old DPI. Make sure the window still has the old size when returning from this message. Remove the code from handlePositionChanging and handlePositionChanged. WM_DPICHANGED comes immediately afterwards.

  • Removing a similar chunk from HWNDComponentPeer::setBounds will mostly fix this for non-native dialog boxes as well.

  • Also in handlePositionChanging: I think the rounding errors introduced by physicalToLogical and logicalToPhysical interfere with this mechanism. This rounding is very noticeable when dragging slowly as the window doesn’t really follow the cursor. Only modify wp if the constrainer actually changes the position.

Hope this helps.


Thanks, I’ll take a look at this.

Thanks for taking a look! Yes the native windows jumping when moving between monitors with different scale factors is solved by using the WM_DPICHANGED message, and this was the route I went down initially, but it gets tricky with non-native windows and can quite easily end up in infinite resizing loops or window sizes changing when moving between monitors due to the sizes not being in sync.

I’ll take another look at implementing the WM_DPICHANGED messages though and see if I can get it running with your suggestions. Thanks again!