0

Setup:

  • Windows 10 Pro v1903
  • 1st Display: 1920x1080 default DPI scaling
  • 2nd Display: 1920x1080, 50% DPI scaling.

I am having problems implementing some DPI changes for Windows. The suggested rect (lParam of WM_DPICHANGED) is returning values of a smaller window once it gets to the scaled screen.

If I create a 1280x720 Window on 1st Display, then move it to the second display the suggested size becomes 1922x1044. The width makes sense since the resolution scaled should be 1920x1080. So I'm guessing it's factoring in the pixels for the borders. However, the height it is returning on the suggested rect, it smaller than what the Window should be if it was scaled properly. Now that it has shrunk to the new height if I go back to the original display, the new suggested size becomes 1280x694, we lose the original Window size.

I have tried manually setting the Window position to factor in a self calculated scale, (width * scale, height * scale) but it does not work properly since it does not factor borders and title bars correctly in SetWindowPos as I'm guessing it's expecting you to include those calculated sizes.

I have also tried reducing the window size to 1280x690 and moving it to the display 2 then back to display 1 and the size returns to the original size. So it's definitely related to the resolution of the window and the target display. I have tried testing other applications with DPI Scaling with a 1280x720 window (such as Microsoft Office) and they resize the window going to Display 2 and returning to Display 1 the size is the correct 1280x720 upon return, it does not experiencing the shrinking.

Am I missing something? I am using SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)

Any help would be greatly appreciated.

1
  • Since I cannot reproduce this issue, could you please provide a Minimal, Reproducible sample here? Commented Apr 2, 2020 at 2:08

1 Answer 1

0

but it does not work properly since it does not factor borders and title bars correctly

You could try to use GetWindowRect to get the bounding rectangle of the window. And then scale the rectangle:

static float dpi;
BOOL InitInstance(...)
{
    dpi = GetDpiForWindow(hWnd);
    SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    switch (message)
    {
    case WM_DPICHANGED:
        {
            WORD newdpi = HIWORD(wParam); //The values of X-axis and the Y-axis are identical for Windows apps
            float scale = newdpi / dpi;
            dpi = newdpi;
            //RECT* rect = (RECT*)lParam;
            RECT old;
            GetWindowRect(hWnd, &old);
            SetWindowPos(hWnd,
                NULL,
                old.left,
                old.top,
                (old.right - old.left) * scale,
                (old.bottom - old.top) * scale,
                SWP_NOZORDER | SWP_NOACTIVATE);
            return 0;
        }
    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.