Win Api DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 - WM_GETDPISCALEDSIZE msg is not sent

75 Views Asked by At

I have created a simple Win Api application to learn about handling dpi changes:

#ifndef UNICODE
#define UNICODE
#endif 

#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);

    const wchar_t class_name[] = L"Sample Window Class";

    WNDCLASSEX wc{};
   
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = class_name;

    if (!RegisterClassEx(&wc))
    {
        return 0;
    }

    DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU |
        WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME | WS_MAXIMIZE;

    HWND hwnd = CreateWindowEx(
        0,                              
        class_name,                     
        L"Title",    
        style,            
        100, 100, 800, 600,
        NULL,      
        NULL,       
        hInstance,  
        NULL       
    );

    if (!hwnd)
    {
        return 0;
    }

    ShowWindow(hwnd, SW_SHOWMAXIMIZED);

    MSG msg{};

    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg); 
    }

    return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_GETDPISCALEDSIZE:
        {
            OutputDebugStringA("WM_GETDPISCALEDSIZE\n");
            return TRUE;
        }
        case WM_DPICHANGED:
        {
            OutputDebugStringA("WM_DPICHANGED\n");
            return 0;
        }
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

I use two monitors, both have the same resolution. The first monitor has a display scale set to 100%, the second to 150%. According the the documentation when I move a window between displays with different dpi I should receive WM_GETDPISCALEDSIZE message before WM_DPICHANGED message. Sometimes I only get WM_DPICHANGED message. Why? Is it a Windows bug or I don't understand something ? You can try to reproduce that issue. Just run the application and move a window holding title bar between screens with the different dpi.

0

There are 0 best solutions below