Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you scale the title bar on a DPI aware win application?

I am making my app dpi-aware per monitor by setting <dpiAware>True/PM</dpiAware> in the manifest file. I can verify with process explorer that this is indeed working or by calling GetProcessDpiAwareness.

This is all working fine and I can scale anything in the client area fine in my code. However, my only problem is that if I drag my app from a system-dpi monitor to a non-system dpi monitor, the title bar and any system menu would either become too big or too small. This isn't the case for most built-in apps (e.g. calc, edge browser, etc..) so there must be away to scale it properly. Does anyone how the devs at MS did this?

The screenshot below should explain my problem better. Also notice, that the padding between the close, min, and max button is different when it's scaled (96dpi).

Screenshot

Sample app I'm attaching a very simple app that is per-monitor dpi aware.

like image 455
Dealdiane Avatar asked Aug 03 '15 07:08

Dealdiane


People also ask

How do I fix apps that look small on high DPI and high resolution displays?

Select Display > Change the size of text, apps, and other items, and then adjust the slider for each monitor. Right-click the application, select Properties, select the Compatibility tab, and then select the Disable display scaling on high DPI settings check box.

How do I fix DPI scaling issues for Visual Studio 2019?

There are three options to resolve the display problem: Restart Visual Studio as a DPI-unaware process. Add a registry entry. Set your display scaling setting to 100%

What is high DPI override scaling?

DPI-scaling overrides 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.


1 Answers

The Windows 10 Anniversary Update (v1607) has added a new API you must call to enable DPI scaling of the non-client areas: EnableNonClientDpiScaling. This function should be called, when WM_NCCREATE is received. The message is sent to the window's procedure callback during window creation.

Example:

case WM_NCCREATE:
{
    if (!EnableNonClientDpiScaling(hWnd))
    {
        // Error handling
        return FALSE;
    }

    return DefWindowProcW(...);
}

If the application's DPI-awareness context is DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, then calling EnableNonClientDpiScaling should be omitted, as it won't have any effect, although the function will still return successfully.

From the documentation:

Non-client scaling for top-level windows is not enabled by default. You must call this API to enable it for each individual top-level window for which you wish to have the non-client area scale automatically. Once you do, there is no way to disable it. Enabling non-client scaling means that all the areas drawn by the system for the window will automatically scale in response to DPI changes on the window. That includes areas like the caption bar, the scrollbars, and the menu bar. You want to call EnableNonClientDpiScaling when you want the operating system to be responsible for rendering these areas automatically at the correct size based on the API of the monitor.

See this blog post for additional information about DPI scaling changes in Windows 10 AU.

like image 92
josh3736 Avatar answered Sep 17 '22 11:09

josh3736