Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

DPI-awareness on Windows #284

Closed
nefarius opened this issue Jun 24, 2024 · 2 comments
Closed

DPI-awareness on Windows #284

nefarius opened this issue Jun 24, 2024 · 2 comments

Comments

@nefarius
Copy link

Ahoy there, long time user and lurker of this amazing project 馃榾

It appears that neither SFML nor ImGui ship with or document a "best practice" on how to deal with DPI-awareness on Windows, like reacting to users who are on like 150% or 200% but the ImGui app stays "tiny" in comparison instead of adjusting width, height, fonts etc.

Anybody knows how to achieve this most elegantly?

Thanks & cheers

@Alia5
Copy link
Contributor

Alia5 commented Jun 25, 2024

I'm not sure that this is the most elegant way, however,
you could...

// stolen from: https://building.enlyze.com/posts/writing-win32-apps-like-its-2020-part-3/
typedef HRESULT(WINAPI* PGetDpiForMonitor)(HMONITOR hmonitor, int dpiType, UINT* dpiX, UINT* dpiY);
WORD GetWindowDPI(HWND hWnd)
{
    // Try to get the DPI setting for the monitor where the given window is located.
    // This API is Windows 8.1+.
    HMODULE hShcore = LoadLibraryW(L"shcore");
    if (hShcore) {
        PGetDpiForMonitor pGetDpiForMonitor =
            reinterpret_cast<PGetDpiForMonitor>(GetProcAddress(hShcore, "GetDpiForMonitor"));
        if (pGetDpiForMonitor) {
            HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY);
            UINT uiDpiX;
            UINT uiDpiY;
            HRESULT hr = pGetDpiForMonitor(hMonitor, 0, &uiDpiX, &uiDpiY);
            if (SUCCEEDED(hr)) {
                return static_cast<WORD>(uiDpiX);
            }
        }
    }

    // We couldn't get the window's DPI above, so get the DPI of the primary monitor
    // using an API that is available in all Windows versions.
    HDC hScreenDC = GetDC(0);
    int iDpiX = GetDeviceCaps(hScreenDC, LOGPIXELSX);
    ReleaseDC(0, hScreenDC);

    return static_cast<WORD>(iDpiX);
}

Then adjust ImGUIs fontScale

    HWND hwnd = window_.getSystemHandle();
    auto dpi = GetWindowDPI(hwnd);
    ImGuiIO& io = ImGui::GetIO();
    io.FontGlobalScale = dpi / 96.f;
    ImGui::SFML::UpdateFontTexture();

@nefarius
Copy link
Author

I pretty much have solved this challenge, for those interested in the implementation details check out this PR.

Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants