Obtain desktop dimensions while DPI scaling is enabled

Good day!

I am looking for a way to get physical desktop (primary monitor) resolution using Windows API.
So far I tried several approaches:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <windows.h>

std::pair<int, int> GetDesktopDimensions1() {
    int screenWidth  = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
    return { screenWidth, screenHeight };
}

std::pair<int, int> GetDesktopDimensions2() {
    HDC hdc = GetDC(nullptr);
    int screenWidth  = GetDeviceCaps(hdc, HORZRES);
    int screenHeight = GetDeviceCaps(hdc, VERTRES);
    ReleaseDC(nullptr, hdc);
    return { screenWidth, screenHeight };
}

std::pair<int, int> GetDesktopDimensions3() {
    RECT desktopRect;
    HWND hwndDesktop = GetDesktopWindow();
    GetWindowRect(hwndDesktop, &desktopRect);
    int screenWidth  = desktopRect.right  - desktopRect.left;
    int screenHeight = desktopRect.bottom - desktopRect.top;
    return { screenWidth, screenHeight };
}


The problem is they all return scaled dimensions. For example on 4k monitor with 200% Windows UI scale they all return 1920 x 1080. While I want 3840 x 2160.

I am also aware of "Properties" > "Compatibility" tab > "Override high DPI scaling behavior" which will change that behavior for particular app. But I want to know physical desktop dimensions regardless of this setting set or not by the user.

There are some methods in some game engines that do just that easily, but at some point I need to know these dimensions before I init some game engines stuff.
Last edited on
Apparently, "the best option here (simple and backward compatible) is to use EnumDisplaySettings with ENUM_CURRENT_SETTINGS."
https://stackoverflow.com/a/41337181

I have not tried this myself.
https://stackoverflow.com/questions/70976583/get-real-screen-resolution-using-win32-api

DPI scaling makes getting the actual screen size a PITA the usual way with WinAPI functions.
Thank you for answers!

@Canado, that worked for me!
At least for my single-monitor config on Win 10.
The code:
1
2
3
4
5
6
7
8
9
10
#include <windows.h>
...
pair<int, int> GetPhysicalDesktopDimensions() {
    DEVMODE devMode;
    devMode.dmSize = sizeof(DEVMODE);
    EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &devMode);
    int screenWidth  = devMode.dmPelsWidth;
    int screenHeight = devMode.dmPelsHeight;
    return { screenWidth, screenHeight };
}


@George P
Maybe for several monitors I will need something like that...
But have not tried it, because of PITA part. Sorry (:

The solution is enough for me, so, [solved].
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <utility>
#include <iostream>

#include <windows.h>

#pragma comment (lib, "user32.lib")

std::pair<int, int> GetPhysicalDesktopDimensions() {
	if (DEVMODE devMode { .dmSize = sizeof(DEVMODE) }; EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &devMode))
		return { devMode.dmPelsWidth, devMode.dmPelsHeight };

	return {};
}


int main() {
	const auto [width, height] { GetPhysicalDesktopDimensions() };

	std::cout << width << '\t' << height << '\n';
}

Last edited on
I am also aware of "Properties" > "Compatibility" tab > "Override high DPI scaling behavior" which will change that behavior for particular app. But I want to know physical desktop dimensions regardless of this setting set or not by the user.

Maybe you want to have a look at:
https://learn.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process
Topic archived. No new replies allowed.