Редагувати

Поділитися через


WM_DPICHANGED message

Sent when the effective dots per inch (dpi) for a window has changed. The DPI is the scale factor for a window. There are multiple events that can cause the DPI to change. The following list indicates the possible causes for the change in DPI.

  • The window is moved to a new monitor that has a different DPI.
  • The DPI of the monitor hosting the window changes.

The current DPI for a window always equals the last DPI sent by WM_DPICHANGED. This is the scale factor that the window should be scaling to for threads that are aware of DPI changes.

#define WM_DPICHANGED       0x02E0

Parameters

wParam

The HIWORD of the wParam contains the Y-axis value of the new dpi of the window. The LOWORD of the wParam contains the X-axis value of the new DPI of the window. For example, 96, 120, 144, or 192. The values of the X-axis and the Y-axis are identical for Windows apps.

lParam

A pointer to a RECT structure that provides a suggested size and position of the current window scaled for the new DPI. The expectation is that apps will reposition and resize windows based on the suggestions provided by lParam when handling this message.

Return value

If an application processes this message, it should return zero.

Remarks

This message is only relevant for PROCESS_PER_MONITOR_DPI_AWARE applications or DPI_AWARENESS_PER_MONITOR_AWARE threads. It may be received on certain DPI changes if your top-level window or process is running as DPI unaware or system DPI aware, but in those situations it can be safely ignored. For more information about the different types of awareness, see PROCESS_DPI_AWARENESS and DPI_AWARENESS. Older versions of Windows required DPI awareness to be tied at the level of an application. Those apps use PROCESS_DPI_AWARENESS. Currently, DPI awareness is tied to threads and individual windows rather than the entire application. These apps use DPI_AWARENESS.

You only need to use either the X-axis or the Y-axis value when scaling your application since they are the same.

In order to handle this message correctly, you will need to resize and reposition your window based on the suggestions provided by lParam and using SetWindowPos. If you do not do this, your window will grow or shrink with respect to everything else on the new monitor. For example, if a user is using multiple monitors and drags your window from a 96 DPI monitor to a 192 DPI monitor, your window will appear to be half as large with respect to other items on the 192 DPI monitor.

The base value of DPI is defined as USER_DEFAULT_SCREEN_DPI which is set to 96. To determine the scaling factor for a monitor, take the DPI value and divide by USER_DEFAULT_SCREEN_DPI. The following table provides some sample DPI values and associated scaling factors.

DPI value Scaling percentage
96 100%
120 125%
144 150%
192 200%

The following example provides a sample DPI change handler.

    case WM_DPICHANGED:
    {
        g_dpi = HIWORD(wParam);
        UpdateDpiDependentFontsAndResources();

        RECT* const prcNewWindow = (RECT*)lParam;
        SetWindowPos(hWnd,
            NULL,
            prcNewWindow ->left,
            prcNewWindow ->top,
            prcNewWindow->right - prcNewWindow->left,
            prcNewWindow->bottom - prcNewWindow->top,
            SWP_NOZORDER | SWP_NOACTIVATE);
        break;
    }

The following code linearly scales a value from 100% (96 DPI) to an arbitrary DPI defined by g_dpi.

    INT iBorderWidth100 = 5;
    iBorderWidth = MulDiv(iBorderWidth100, g_dpi, USER_DEFAULT_SCREEN_DPI);

An alternative way to scale a value is to convert the DPI value into a scale factor and use that.

    INT iBorderWidth100 = 5;
    FLOAT fscale = (float) g_dpi / USER_DEFAULT_SCREEN_DPI;
    iBorderWidth = iBorderWidth100 * fscale;

Requirements

Requirement Value
Minimum supported client
Windows 8.1 [desktop apps only]
Minimum supported server
Windows Server 2012 R2 [desktop apps only]
Header
WinUser.h

See also

DPI_AWARENESS

PROCESS_DPI_AWARENESS