ThePhD / infoware

C++ Library for pulling system and hardware information, without hitting the command line.
Creative Commons Zero v1.0 Universal
410 stars 84 forks source link

Incorrect refresh-rate with multiple displays (Windows 10, 11) #61

Closed 0d2f1x closed 2 years ago

0d2f1x commented 2 years ago

The refresh rate of the displays is the same as the first.

for (int i = 0; i < iware::system::displays().size(); i++)
{
       std::cout << "Screen [" << i + 1 << "]: " << iware::system::displays()[i].width << "x" << iware::system::displays()[i].height << " (" << iware::system::displays()[i].refresh_rate << "Hz)" << std::endl;
}

image

nabijaczleweli commented 2 years ago

Build the following with c++ -std=c++17 a.cpp -lgdi32:

#include <windows.h>
#include <wingdi.h>
#include <cstdio>

int main() {
    EnumDisplayMonitors(
        nullptr, nullptr,
        [](auto, auto hdc, auto rect, auto userdata) {
            static const auto desktop_dc          = GetDC(nullptr);
            static const unsigned int desktop_dpi = GetDeviceCaps(desktop_dc, LOGPIXELSX);
            // https://blogs.msdn.microsoft.com/oldnewthing/20101013-00/?p=12543
            static const unsigned int desktop_bpp    = GetDeviceCaps(desktop_dc, BITSPIXEL) * GetDeviceCaps(desktop_dc, PLANES);
            static const double desktop_refresh_rate = GetDeviceCaps(desktop_dc, VREFRESH);
            std::printf("desktop: %u DPI,   %u BPP, %f Hz\n", desktop_dpi, desktop_bpp, desktop_refresh_rate);

            // https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx
            // Doesn't work, can't link to shcore
            //
            // unsigned int dpi_x;
            // unsigned int dpi_y;
            // GetDpiForMonitor(monitor /* arg #1 */, MDT_DEFAULT, &dpi_x, &dpi_y);

            // Sometimes returns 0 for some reason?
            // Fall back to the desktop's globals if so.
            const unsigned int monitor_dpi    = GetDeviceCaps(hdc, LOGPIXELSX);
            const unsigned int monitor_bpp    = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
            const double monitor_refresh_rate = GetDeviceCaps(hdc, VREFRESH);

            const unsigned int width  = std::abs(rect->right - rect->left);
            const unsigned int height = std::abs(rect->bottom - rect->top);

            std::printf("monitor: %u DPI,   %u BPP, %f Hz,  %ux%u\n", monitor_dpi, monitor_bpp, monitor_refresh_rate, width, height);

            return 1;
        },
        0);
}

What's the output?

0d2f1x commented 2 years ago

First display 144hz (1920x1080) Second display 75hz (1920x1080)

Output:

desktop: 96 DPI,        32 BPP, 144.000000 Hz
monitor: 0 DPI, 0 BPP,  0.000000 Hz,    1920x1080
desktop: 96 DPI,        32 BPP, 144.000000 Hz
monitor: 0 DPI, 0 BPP,  0.000000 Hz,    1920x1080