5
votes

When per-monitor DPI changes (WM_DPICHANGED message), the built-in scrollbars of controls like list view, tree view, rich edit, listbox are not scaled (as expected).

Unscaled scrollbar

They need to be scaled programmatically.

Though I didn't find any API (neither in Win32, let only in WinForms) to set scrollbar size.

What API can I use to set scrollbar size (width)?

Or at least how I do get hold of the scrollbar handle? (I assume that internally the scrollbars are separate child controls) Once I have the handle, I assume I can use MoveWindow to resize it (Edit: my assumption was incorrect, as the answer by @Anders shows)


For a background, see High DPI Desktop Application Development on Windows.


There are couple seemingly duplicate questions, but none of them are actually relevant:

The answers there either change system-wide settings or work for DataGrid only (that have separate child scrollbar controls available in its interface).

2
What happens if you forward the WM_DPICHANGED to the child windows? What happens if you call SetWindowPos(SWP_FRAMECHANGED) on the child windows? I don't know if either is the right answer, but these would be the first things I would try... (I need to re-read the MSDN pages on DPI awareness.)andlabs
@andlabs Thanks for your comment. I've tried both (however implausible the first seems to be, as the documentation does not imply the message should ever be handled by controls). Neither have any effect unfortunately.Martin Prikryl

2 Answers

3
votes

Scrollbars are usually not separate windows. If a window uses the WS_HSCROLL/WS_VSCROLL styles then the scrollbars are implemented in the non-client area of the control itself.

Windows 10 Creators Update is going to introduce something called Per Monitor V2 DPI awareness. This includes child window notifications, "Windows Forms DPI scaling improvements" and "Improved theming behavior". It is also going to automatically scale the non-client area.

In the meantime you can try calling EnableNonClientDpiScaling in WM_NCCREATE (added in the Anniversary Update).

2
votes

As suggested by @Anders, the Per Monitor V2 DPI awareness in Windows 10 Creators Update resolves this.

Scaled control scrollbar

To enable Per Monitor V2 DPI awareness, while still supporting old Per Monitor DPI awareness on older Windows 10 builds and Windows 8.1 and DPI awareness on yet older versions of Windows, make your application manifest like this:

<assembly ...>
    <!-- ... --->
    <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <dpiAware>True/PM</dpiAware>
            <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
        </asmv3:windowsSettings>
    </asmv3:application>
</assembly>

References: