Skip to content

Commit 5407126

Browse files
committed
Add DPI scaling utilities for Windows platform
Introduces dpi_utils_windows.cpp and dpi_utils_windows.h to provide DPI scale factor detection for Windows windows. Updates window_windows.cpp to use logical pixels (DIP) in GetContentBounds by dividing screen coordinates by the DPI scale factor, improving high-DPI support.
1 parent 3b693d4 commit 5407126

File tree

3 files changed

+90
-5
lines changed

3 files changed

+90
-5
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include <windows.h>
2+
3+
namespace nativeapi {
4+
5+
// Internal: per-monitor DPI via Shcore when available
6+
static double GetScaleFactorForMonitor(HMONITOR hmonitor) {
7+
if (!hmonitor) return 1.0;
8+
typedef HRESULT(WINAPI * GetDpiForMonitorFunc)(HMONITOR, int, UINT*, UINT*);
9+
static GetDpiForMonitorFunc pGetDpiForMonitor = nullptr;
10+
static bool resolved = false;
11+
if (!resolved) {
12+
HMODULE hShcore = LoadLibraryW(L"Shcore.dll");
13+
if (hShcore) {
14+
pGetDpiForMonitor = reinterpret_cast<GetDpiForMonitorFunc>(
15+
GetProcAddress(hShcore, "GetDpiForMonitor"));
16+
}
17+
resolved = true;
18+
}
19+
if (pGetDpiForMonitor) {
20+
UINT dpiX = 96, dpiY = 96;
21+
if (SUCCEEDED(pGetDpiForMonitor(hmonitor, 0 /* MDT_EFFECTIVE_DPI */, &dpiX, &dpiY))) {
22+
return static_cast<double>(dpiX) / 96.0;
23+
}
24+
}
25+
return 1.0;
26+
}
27+
28+
double GetScaleFactorForWindow(HWND hwnd) {
29+
if (hwnd) {
30+
// Prefer GetDpiForWindow if available
31+
typedef UINT(WINAPI * GetDpiForWindowFunc)(HWND);
32+
static GetDpiForWindowFunc pGetDpiForWindow = nullptr;
33+
static bool resolved_win = false;
34+
if (!resolved_win) {
35+
HMODULE hUser32 = LoadLibraryW(L"user32.dll");
36+
if (hUser32) {
37+
pGetDpiForWindow = reinterpret_cast<GetDpiForWindowFunc>(
38+
GetProcAddress(hUser32, "GetDpiForWindow"));
39+
}
40+
resolved_win = true;
41+
}
42+
if (pGetDpiForWindow) {
43+
UINT dpi = pGetDpiForWindow(hwnd);
44+
if (dpi > 0) {
45+
return static_cast<double>(dpi) / 96.0;
46+
}
47+
}
48+
49+
// Fallback: per-monitor DPI
50+
HMONITOR hmonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
51+
double monitor_scale = GetScaleFactorForMonitor(hmonitor);
52+
if (monitor_scale > 0.0) return monitor_scale;
53+
}
54+
55+
// Fallback: system DPI
56+
HDC hdc = GetDC(nullptr);
57+
if (hdc) {
58+
int dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
59+
ReleaseDC(nullptr, hdc);
60+
if (dpiX > 0) {
61+
return static_cast<double>(dpiX) / 96.0;
62+
}
63+
}
64+
return 1.0;
65+
}
66+
67+
} // namespace nativeapi
68+
69+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
#include <windows.h>
3+
4+
namespace nativeapi {
5+
6+
// Returns the DPI scale factor for the given window (1.0 at 96 DPI)
7+
double GetScaleFactorForWindow(HWND hwnd);
8+
9+
} // namespace nativeapi
10+
11+

src/platform/windows/window_windows.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "../../window.h"
44
#include "../../window_manager.h"
55
#include "string_utils_windows.h"
6+
#include "dpi_utils_windows.h"
67

78
namespace nativeapi {
89

@@ -258,16 +259,20 @@ Rectangle Window::GetContentBounds() const {
258259
RECT clientRect;
259260
GetClientRect(pimpl_->hwnd_, &clientRect);
260261

261-
// Convert client rect to screen coordinates
262+
// Convert client rect to screen coordinates (physical pixels)
262263
POINT topLeft = {clientRect.left, clientRect.top};
263264
POINT bottomRight = {clientRect.right, clientRect.bottom};
264265
ClientToScreen(pimpl_->hwnd_, &topLeft);
265266
ClientToScreen(pimpl_->hwnd_, &bottomRight);
266267

267-
bounds.x = topLeft.x;
268-
bounds.y = topLeft.y;
269-
bounds.width = bottomRight.x - topLeft.x;
270-
bounds.height = bottomRight.y - topLeft.y;
268+
double scale = GetScaleFactorForWindow(pimpl_->hwnd_);
269+
if (scale <= 0.0) scale = 1.0;
270+
271+
// Return logical pixels (DIP) by dividing by scale
272+
bounds.x = static_cast<double>(topLeft.x) / scale;
273+
bounds.y = static_cast<double>(topLeft.y) / scale;
274+
bounds.width = static_cast<double>(bottomRight.x - topLeft.x) / scale;
275+
bounds.height = static_cast<double>(bottomRight.y - topLeft.y) / scale;
271276
}
272277
return bounds;
273278
}

0 commit comments

Comments
 (0)