app.dhover×224 error×63all
// F08 — DPI / runtime rescale, Win32 implementation
// (../../../features/f08-dpi-scaling.md). Extends the scaffold
// (../scaffold/app.d) into a Per-Monitor-v2 DPI observatory:
//
//   * SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)
//     before any HWND exists (druntime's core.sys.windows predates the
//     Win10-1607 DPI API surface, so the contexts and the user32 entry points
//     are declared below and resolved with GetProcAddress — which also logs
//     which of them the host provides).
//   * Logs every DPI source: GetThreadDpiAwarenessContext,
//     GetWindowDpiAwarenessContext, GetDpiForWindow, GetDpiForSystem,
//     GetSystemDpiForProcess, plus the GetDeviceCaps(LOGPIXELSX) legacy value.
//   * Immutability proofs: a second SetProcessDpiAwarenessContext call (the
//     process awareness is write-once), and a WSI_LATE_AWARENESS=1 mode that
//     creates the window FIRST and only then calls the API — capturing the
//     documented ERROR_ACCESS_DENIED ordering rule. The late mode then probes
//     SetThreadDpiAwarenessContext sub-process granularity: the existing
//     window keeps its creation-time awareness, a second window created on
//     the PMv2 thread gets the new one.
//   * WM_DPICHANGED: logs old/new DPI and the suggested rect, honors it with
//     SetWindowPos, reallocates the DIB backbuffer on the resulting WM_SIZE,
//     and logs logical (96-DPI units) vs physical client size on every
//     resize. The frame renders 1-physical-px hairlines (border + center
//     crosshair) over the scaffold gradient so scaling artifacts are visible.
//
// WSI_AUTO_EXIT=1 bounds the run (default ~1.2 s; WSI_RUN_MS overrides — the
// findings doc uses a longer run while changing the compositor output scale
// under winewayland to hunt a live WM_DPICHANGED). Exit 0 in all modes.
//
// Only druntime's built-in core.sys.windows bindings — no third-party packages.
module 
(module) app
app
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.windows
windows
.
(module) core.sys.windows.windows

Windows API header module

Translated from MinGW API for MS-Windows 4.0

Source

core/sys/windows/windows.d

windows
;
import instrument;
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
// --------------------------------------------------------------------------- // The Win10 DPI-awareness surface (winuser.h, 1607+/1803+) — absent from // druntime's core.sys.windows. DPI_AWARENESS_CONTEXT values are pseudo // handles; the functions are user32 exports resolved at runtime so a missing // export is a logged finding, not a loader failure. alias
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
= HANDLE;
undefined identifier `HANDLE`
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
app.dpiCtx
dpiCtx
(int
(parameter) int n
n
) nothrow @nogc
{ return cast(
(unresolved type) DPI_AWARENESS_CONTEXT
DPI_AWARENESS_CONTEXT
) cast(ptrdiff_t) n;
} enum
(constant) int app.CTX_UNAWARE = -1
CTX_UNAWARE
= -1;
enum
(constant) int app.CTX_SYSTEM_AWARE = -2
CTX_SYSTEM_AWARE
= -2;
enum
(constant) int app.CTX_PER_MONITOR_AWARE = -3
CTX_PER_MONITOR_AWARE
= -3;
enum
(constant) int app.CTX_PER_MONITOR_AWARE_V2 = -4
CTX_PER_MONITOR_AWARE_V2
= -4;
enum
(constant) int app.CTX_UNAWARE_GDISCALED = -5
CTX_UNAWARE_GDISCALED
= -5;
enum
(constant) int app.WM_DPICHANGED = 736
WM_DPICHANGED
= 0x02E0;
enum
(constant) int app.WM_GETDPISCALEDSIZE = 740
WM_GETDPISCALEDSIZE
= 0x02E4;
struct
(struct) app.Api
Api
{ extern (Windows) nothrow @nogc: BOOL function(
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
)
(field) _error_ app.Api.SetProcessDpiAwarenessContext
SetProcessDpiAwarenessContext
;
undefined identifier `BOOL`
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
function()
(field) _error_ app.Api.GetThreadDpiAwarenessContext
GetThreadDpiAwarenessContext
;
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
function(
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
)
(field) _error_ app.Api.SetThreadDpiAwarenessContext
SetThreadDpiAwarenessContext
;
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
function(HWND)
(field) _error_ app.Api.GetWindowDpiAwarenessContext
GetWindowDpiAwarenessContext
;
undefined identifier `HWND`
BOOL function(
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
,
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
)
(field) _error_ app.Api.AreDpiAwarenessContextsEqual
AreDpiAwarenessContextsEqual
;
undefined identifier `BOOL`
UINT function(HWND)
(field) _error_ app.Api.GetDpiForWindow
GetDpiForWindow
;
undefined identifier `UINT`
undefined identifier `HWND`
UINT function()
(field) _error_ app.Api.GetDpiForSystem
GetDpiForSystem
;
undefined identifier `UINT`
UINT function(HANDLE)
(field) _error_ app.Api.GetSystemDpiForProcess
GetSystemDpiForProcess
;
undefined identifier `UINT`
undefined identifier `HANDLE`
} __gshared
(struct) app.Api
Api
_error_ app.api
api
;
void
void app.loadDpiApi() nothrow
loadDpiApi
() nothrow
{ HMODULE
(local variable) _error_ u32
u32
= GetModuleHandleW("user32"w.ptr);
undefined identifier `HMODULE`
undefined identifier `GetModuleHandleW`
static foreach (name; __traits(allMembers, Api)) { __traits(getMember, api, name) = cast(typeof(__traits(getMember, api, name))) GetProcAddress(u32, name.ptr); logEvent("api name=%s present=%d", name.ptr, __traits(getMember, api, name) !is null ? 1 : 0); } } // Render an awareness context as a stable name for the log (the raw value is // an opaque handle; equality must go through AreDpiAwarenessContextsEqual). const(char)*
app.ctxName
ctxName
(
(alias) app.DPI_AWARENESS_CONTEXT = _error_
DPI_AWARENESS_CONTEXT
(parameter) DPI_AWARENESS_CONTEXT ctx
ctx
) nothrow
{ if (api.
api.AreDpiAwarenessContextsEqual
AreDpiAwarenessContextsEqual
is null)
return "unknown"; if (api.
api.AreDpiAwarenessContextsEqual
AreDpiAwarenessContextsEqual
(ctx, dpiCtx(CTX_PER_MONITOR_AWARE_V2)))
return "per_monitor_aware_v2"; if (api.
api.AreDpiAwarenessContextsEqual
AreDpiAwarenessContextsEqual
(ctx, dpiCtx(CTX_PER_MONITOR_AWARE)))
return "per_monitor_aware"; if (api.
api.AreDpiAwarenessContextsEqual
AreDpiAwarenessContextsEqual
(ctx, dpiCtx(CTX_SYSTEM_AWARE)))
return "system_aware"; if (api.
api.AreDpiAwarenessContextsEqual
AreDpiAwarenessContextsEqual
(ctx, dpiCtx(CTX_UNAWARE_GDISCALED)))
return "unaware_gdiscaled"; if (api.
api.AreDpiAwarenessContextsEqual
AreDpiAwarenessContextsEqual
(ctx, dpiCtx(CTX_UNAWARE)))
return "unaware"; return "unrecognized"; } // One line with every DPI source the platform exposes, tagged by call site. void
app.logDpiSources
logDpiSources
(const(char)*
(parameter) const(char)* when
when
, HWND
(parameter) HWND hwnd
hwnd
) nothrow
undefined identifier `HWND`
{ const
_error_ winDpi
winDpi
= hwnd && api.
api.GetDpiForWindow
GetDpiForWindow
? api.
api.GetDpiForWindow
GetDpiForWindow
(hwnd) : 0;
const
_error_ sysDpi
sysDpi
= api.
api.GetDpiForSystem
GetDpiForSystem
? api.
api.GetDpiForSystem
GetDpiForSystem
() : 0;
const
_error_ procDpi
procDpi
= api.
api.GetSystemDpiForProcess
GetSystemDpiForProcess
? api.
api.GetSystemDpiForProcess
GetSystemDpiForProcess
(GetCurrentProcess()) : 0;
HDC
_error_ screen
screen
= GetDC(null);
const
_error_ caps
caps
= GetDeviceCaps(screen, LOGPIXELSX);
ReleaseDC(null, screen); logEvent("dpi_sources when=%s window=%u system=%u process=%u devcaps=%d thread_ctx=%s", when, winDpi, sysDpi, procDpi, caps, api.
api.GetThreadDpiAwarenessContext
GetThreadDpiAwarenessContext
? ctxName(api.
api.GetThreadDpiAwarenessContext
GetThreadDpiAwarenessContext
()) : "unknown".ptr);
} // --------------------------------------------------------------------------- // Demo state: scaffold DIB backbuffer + DPI bookkeeping. enum UINT_PTR
(constant) _error_ app.TIMER_ID = __error
TIMER_ID
= 1;
undefined identifier `UINT_PTR`
enum
(constant) int app.TICK_MS = 16
TICK_MS
= 16;
struct
(struct) app.Demo
Demo
{ HWND
(field) _error_ app.Demo.hwndMain
hwndMain
; // the second (granularity-probe) window must not quit us
undefined identifier `HWND`
HDC
(field) _error_ app.Demo.memDc
memDc
;
undefined identifier `HDC`
HBITMAP
(field) _error_ app.Demo.dib
dib
,
(field) _error_ app.Demo.stockBmp
stockBmp
;
undefined identifier `HBITMAP`
undefined identifier `HBITMAP`
uint*
(field) uint* app.Demo.pixels
pixels
;
int
(field) int app.Demo.width
width
,
(field) int app.Demo.height
height
; // physical client pixels (= DIB size)
uint
(field) uint app.Demo.dpi
dpi
= 96; // current per-window DPI; scale = dpi / 96
uint
(field) uint app.Demo.frame
frame
,
(field) uint app.Demo.ticks
ticks
;
uint
(field) uint app.Demo.runMs
runMs
= 1200; // auto-exit deadline (WSI_RUN_MS overrides)
uint
(field) uint app.Demo.nDpiChanged
nDpiChanged
;
bool
(field) bool app.Demo.autoExit
autoExit
,
(field) bool app.Demo.late
late
;
bool
(field) bool app.Demo.firstPaintDone
firstPaintDone
;
} __gshared
(struct) app.Demo
Demo
_error_ app.g
g
;
void
void app.createBackbuffer(int w, int h) nothrow
createBackbuffer
(int
(parameter) int w
w
, int
(parameter) int h
h
) nothrow
{ if (g.
(field) _error_ g.dib
dib
!is null)
{ SelectObject(g.
g.memDc
memDc
, g.
g.stockBmp
stockBmp
);
undefined identifier `SelectObject`
DeleteObject(g.
g.dib
dib
);
undefined identifier `DeleteObject`
g.
g.dib
dib
= null;
g.
g.pixels
pixels
= null;
g.
g.width
width
= g.
g.height
height
= 0;
} if (
(parameter) int w
w
<= 0 ||
(parameter) int h
h
<= 0)
return; BITMAPINFO
(local variable) _error_ bmi
bmi
;
undefined identifier `BITMAPINFO`
bmi.bmiHeader.biSize = BITMAPINFOHEADER.sizeof; bmi.bmiHeader.biWidth = w; bmi.bmiHeader.biHeight = -h; // top-down bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; void*
(local variable) void* bits
bits
;
g.
g.dib
dib
= CreateDIBSection(null, &bmi, DIB_RGB_COLORS, &bits, null, 0);
if (g.
(field) _error_ g.dib
dib
is null)
{ logEvent("error what=CreateDIBSection code=%lu", GetLastError());
undefined identifier `logEvent`
return; } g.
g.pixels
pixels
= cast(uint*) bits;
g.
g.width
width
= w;
g.
g.height
height
= h;
g.
g.stockBmp
stockBmp
= cast(HBITMAP) SelectObject(g.
g.memDc
memDc
, g.
g.dib
dib
);
logEvent("buffer_alloc size=%dx%d bytes=%d", w, h, w * h * 4);
undefined identifier `logEvent`
} // Scaffold gradient + 1-physical-px hairlines: a white border rectangle and a // center crosshair. At the correct buffer size they are razor-sharp; any // bitmap-stretch (the DPI-virtualization failure mode) blurs them visibly. void
void app.drawFrame() nothrow
drawFrame
() nothrow
{ if (g.
(field) _error_ g.pixels
pixels
is null)
return; const
(local variable) const(_error_) w
w
= g.
(field) _error_ g.width
width
,
(local variable) const(_error_) h
h
= g.
(field) _error_ g.height
height
;
const
(local variable) const(_error_) blue
blue
= (g.
(field) _error_ g.frame
frame
* 4) & 0xff;
foreach (
(parameter) y
y
; 0 .. h)
{ uint*
_error_ row
row
= g.
g.pixels
pixels
+ cast(size_t) y * w;
const
_error_ green
green
= h > 1 ? (y * 255) / (h - 1) : 0;
foreach (
(parameter) x
x
; 0 .. w)
{ const
_error_ red
red
= w > 1 ? (x * 255) / (w - 1) : 0;
row[x] = cast(uint)((red << 16) | (green << 8) | blue); } } foreach (
(parameter) x
x
; 0 .. w) // 1-px horizontal hairlines: border + center
{ g.
g.pixels
pixels
[x] = 0xffffff;
g.
g.pixels
pixels
[cast(size_t)(h - 1) * w + x] = 0xffffff;
g.
g.pixels
pixels
[cast(size_t)(h / 2) * w + x] = 0xffffff;
} foreach (
(parameter) y
y
; 0 .. h) // and vertical
{ g.
g.pixels
pixels
[cast(size_t) y * w] = 0xffffff;
g.
g.pixels
pixels
[cast(size_t) y * w + (w - 1)] = 0xffffff;
g.
g.pixels
pixels
[cast(size_t) y * w + (w / 2)] = 0xffffff;
} } // --------------------------------------------------------------------------- extern (Windows) LRESULT
app.wndProc
wndProc
(HWND
(parameter) HWND hwnd
hwnd
, UINT
(parameter) UINT msg
msg
, WPARAM wParam, LPARAM lParam) nothrow
undefined identifier `LRESULT`
undefined identifier `HWND`
undefined identifier `UINT`
undefined identifier `WPARAM`
undefined identifier `LPARAM`
{ switch (msg) { case WM_CREATE: if (g.
g.memDc
memDc
is null) // the probe window shares nothing
g.
g.memDc
memDc
= CreateCompatibleDC(null);
return 0; case WM_DPICHANGED: // wParam: new X DPI (low word) / Y DPI (high word); lParam: the // OS-suggested window rect at the new scale. Honoring it verbatim is // the documented contract — it keeps the window under the cursor and // at an equivalent logical size on the new monitor. ++g.
g.nDpiChanged
nDpiChanged
;
const
_error_ newDpi
newDpi
= cast(uint)(wParam & 0xffff);
const RECT*
_error_ r
r
= cast(RECT*) lParam;
logEvent("dpi_changed old=%u new=%u suggested=%dx%d+%d+%d", g.
g.dpi
dpi
, newDpi, r.right - r.left, r.bottom - r.top, r.left, r.top);
g.
g.dpi
dpi
= newDpi;
SetWindowPos(hwnd, null, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE); InvalidateRect(hwnd, null, FALSE); return 0; case WM_GETDPISCALEDSIZE: // PMv2-only negotiation hook before DPICHANGED logEvent("msg name=WM_GETDPISCALEDSIZE dpi=%u", cast(uint) wParam); goto default; // FALSE from DefWindowProc = default linear scaling case WM_SIZE: const
_error_ w
w
= cast(int)(lParam & 0xffff);
const
_error_ h
h
= cast(int)((lParam >> 16) & 0xffff);
// Under per-monitor awareness the client rect IS physical pixels; // the logical (DIP) size is derived: logical = physical * 96 / dpi. logEvent("resize size=%dx%d scale=%u.%02u logical=%dx%d", w, h, g.
g.dpi
dpi
/ 96, (g.
g.dpi
dpi
% 96) * 100 / 96,
w * 96 / g.
g.dpi
dpi
, h * 96 / g.
g.dpi
dpi
);
if (wParam == SIZE_MINIMIZED) return 0; if (w != g.
g.width
width
|| h != g.
g.height
height
)
createBackbuffer(w, h); return 0; case WM_PAINT: PAINTSTRUCT
_error_ ps
ps
;
HDC
_error_ hdc
hdc
= BeginPaint(hwnd, &ps);
++g.
g.frame
frame
;
drawFrame(); if (g.
g.pixels
pixels
!is null)
BitBlt(hdc, 0, 0, g.
g.width
width
, g.
g.height
height
, g.
g.memDc
memDc
, 0, 0, SRCCOPY);
if (!g.
g.firstPaintDone
firstPaintDone
)
{ g.
g.firstPaintDone
firstPaintDone
= true;
logEvent("first_pixel_presented size=%dx%d dpi=%u", g.
g.width
width
, g.
g.height
height
, g.
g.dpi
dpi
);
} EndPaint(hwnd, &ps); return 0; case WM_TIMER: if (wParam != TIMER_ID) return 0; ++g.
g.ticks
ticks
;
InvalidateRect(hwnd, null, FALSE); if (g.
g.autoExit
autoExit
&& g.
g.ticks
ticks
* TICK_MS >= g.
g.runMs
runMs
)
DestroyWindow(hwnd); return 0; case WM_CLOSE: logEvent("close_requested"); goto default; case WM_DESTROY: if (g.
g.hwndMain
hwndMain
!is null && hwnd !is g.
g.hwndMain
hwndMain
)
return 0; // the probe window: no teardown, no quit KillTimer(hwnd, TIMER_ID); createBackbuffer(0, 0); if (g.
g.memDc
memDc
!is null)
{ DeleteDC(g.
g.memDc
memDc
);
g.
g.memDc
memDc
= null;
} logEvent("summary dpichanged=%u final_dpi=%u", g.
g.nDpiChanged
nDpiChanged
, g.
g.dpi
dpi
);
PostQuitMessage(0); return 0; default: return DefWindowProcW(hwnd, msg, wParam, lParam); } } // --------------------------------------------------------------------------- bool
bool app.envFlag(const(wchar)* name) nothrow
envFlag
(const(wchar)*
(parameter) const(wchar)* name
name
) nothrow
{ WCHAR[16]
(local variable) _error_ buf
buf
;
undefined identifier `WCHAR`
const
(local variable) const(_error_) n
n
= GetEnvironmentVariableW(name, buf.ptr, buf.length);
undefined identifier `GetEnvironmentVariableW`
return n >= 1 && n < buf.length && buf[0] == '1'; } uint
uint app.envUint(const(wchar)* name, uint def) nothrow
envUint
(const(wchar)*
(parameter) const(wchar)* name
name
, uint
(parameter) uint def
def
) nothrow
{ WCHAR[16]
(local variable) _error_ buf
buf
;
undefined identifier `WCHAR`
const
(local variable) const(_error_) n
n
= GetEnvironmentVariableW(name, buf.ptr, buf.length);
undefined identifier `GetEnvironmentVariableW`
if (n < 1 || n >= buf.length) return
(parameter) uint def
def
;
uint
(local variable) uint v
v
;
foreach (
(parameter) i
i
; 0 .. n)
{ if (buf[i] < '0' || buf[i] > '9') return def; v = v * 10 + (buf[i] - '0'); } return
(local variable) uint v
v
;
} void
void app.setAwareness(const(char)* when, int ctx) nothrow
setAwareness
(const(char)*
(parameter) const(char)* when
when
, int
(parameter) int ctx
ctx
) nothrow
{ if (api.
(field) _error_ api.SetProcessDpiAwarenessContext
SetProcessDpiAwarenessContext
is null)
{ logEvent("awareness_set when=%s skipped=api_missing", when);
undefined identifier `logEvent`
return; } SetLastError(0);
undefined identifier `SetLastError`
const
(local variable) const(_error_) ok
ok
= api.SetProcessDpiAwarenessContext(dpiCtx(ctx));
logEvent("awareness_set when=%s ctx=%s ok=%d err=%lu",
undefined identifier `logEvent`
when, ctxName(dpiCtx(ctx)), ok ? 1 : 0, ok ? 0 : GetLastError()); } HWND
app.createDemoWindow
createDemoWindow
(HINSTANCE
(parameter) HINSTANCE hInst
hInst
, const(wchar)* cls, const(wchar)* title) nothrow
undefined identifier `HWND`
undefined identifier `HINSTANCE`
{ return CreateWindowExW(0, cls, title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 480, 320, null, null, hInst, null); } int
int D main()
main
()
{ instrumentInit("f08_dpi_win32");
undefined identifier `instrumentInit`
logEvent("init_start");
undefined identifier `logEvent`
g.
g.autoExit
autoExit
= envFlag("WSI_AUTO_EXIT"w.ptr);
g.
g.late
late
= envFlag("WSI_LATE_AWARENESS"w.ptr);
g.
g.runMs
runMs
= envUint("WSI_RUN_MS"w.ptr, 1200);
logEvent("mode auto_exit=%d late_awareness=%d run_ms=%u",
undefined identifier `logEvent`
g.
g.autoExit
autoExit
? 1 : 0, g.
g.late
late
? 1 : 0, g.
g.runMs
runMs
);
void app.loadDpiApi() nothrow
loadDpiApi
();
logDpiSources("before_awareness", null); if (!g.
(field) _error_ g.late
late
)
{ // The production ordering: declare PMv2 before ANY window exists.
void app.setAwareness(const(char)* when, int ctx) nothrow
setAwareness
("before_window",
(constant) int app.CTX_PER_MONITOR_AWARE_V2 = -4
CTX_PER_MONITOR_AWARE_V2
);
// Write-once proof: a second call must fail (ERROR_ACCESS_DENIED).
void app.setAwareness(const(char)* when, int ctx) nothrow
setAwareness
("second_call",
(constant) int app.CTX_SYSTEM_AWARE = -2
CTX_SYSTEM_AWARE
);
logDpiSources("after_awareness", null); } HINSTANCE
(local variable) _error_ hInst
hInst
= GetModuleHandleW(null);
undefined identifier `HINSTANCE`
undefined identifier `GetModuleHandleW`
auto
(local variable) wstring clsName
clsName
= "wsi-f08-class"w;
WNDCLASSEXW
(local variable) _error_ wc
wc
;
undefined identifier `WNDCLASSEXW`
wc.cbSize = WNDCLASSEXW.sizeof; wc.lpfnWndProc = &wndProc; wc.hInstance = hInst; wc.lpszClassName = clsName.ptr; wc.hCursor = LoadCursorW(null, IDC_ARROW); if (!RegisterClassExW(&wc))
undefined identifier `RegisterClassExW`
{ logEvent("error what=RegisterClassExW code=%lu", GetLastError());
undefined identifier `logEvent`
return 1; } HWND
(local variable) _error_ hwnd
hwnd
= createDemoWindow(hInst, clsName.ptr, "wsi-f08-dpi-scaling"w.ptr);
undefined identifier `HWND`
if (hwnd is null) { logEvent("error what=CreateWindowExW code=%lu", GetLastError());
undefined identifier `logEvent`
return 1; } logEvent("window_created");
undefined identifier `logEvent`
g.
g.hwndMain
hwndMain
= hwnd;
if (api.
(field) _error_ api.GetDpiForWindow
GetDpiForWindow
!is null)
g.
g.dpi
dpi
= api.
api.GetDpiForWindow
GetDpiForWindow
(hwnd);
if (api.
(field) _error_ api.GetWindowDpiAwarenessContext
GetWindowDpiAwarenessContext
!is null)
logEvent("window_ctx hwnd=main ctx=%s",
undefined identifier `logEvent`
ctxName(api.
api.GetWindowDpiAwarenessContext
GetWindowDpiAwarenessContext
(hwnd)));
logDpiSources("after_window", hwnd); if (g.
(field) _error_ g.late
late
)
{ // The ordering rule: setting process awareness AFTER a window exists // is documented to fail (the default awareness is locked in by then).
void app.setAwareness(const(char)* when, int ctx) nothrow
setAwareness
("after_window",
(constant) int app.CTX_PER_MONITOR_AWARE_V2 = -4
CTX_PER_MONITOR_AWARE_V2
);
logDpiSources("after_late_set", hwnd); // Sub-process granularity: thread-scoped awareness still works… if (api.
(field) _error_ api.SetThreadDpiAwarenessContext
SetThreadDpiAwarenessContext
!is null)
{ auto
(local variable) _error_ prev
prev
= api.SetThreadDpiAwarenessContext(dpiCtx(CTX_PER_MONITOR_AWARE_V2));
logEvent("thread_awareness_set ctx=per_monitor_aware_v2 prev=%s ok=%d",
undefined identifier `logEvent`
ctxName(prev), prev !is null ? 1 : 0); // …the existing window keeps its creation-time awareness, while a // window created NOW inherits the thread's new context. if (api.
(field) _error_ api.GetWindowDpiAwarenessContext
GetWindowDpiAwarenessContext
!is null)
logEvent("window_ctx hwnd=main ctx=%s note=unchanged_after_thread_set",
undefined identifier `logEvent`
ctxName(api.
api.GetWindowDpiAwarenessContext
GetWindowDpiAwarenessContext
(hwnd)));
HWND
(local variable) _error_ hwnd2
hwnd2
= createDemoWindow(hInst, clsName.ptr, "wsi-f08-second"w.ptr);
undefined identifier `HWND`
if (hwnd2 !is null && api.
(field) _error_ api.GetWindowDpiAwarenessContext
GetWindowDpiAwarenessContext
!is null)
{ logEvent("window_ctx hwnd=second ctx=%s dpi=%u",
undefined identifier `logEvent`
ctxName(api.
api.GetWindowDpiAwarenessContext
GetWindowDpiAwarenessContext
(hwnd2)),
api.
api.GetDpiForWindow
GetDpiForWindow
? api.
api.GetDpiForWindow
GetDpiForWindow
(hwnd2) : 0);
DestroyWindow(hwnd2);
undefined identifier `DestroyWindow`
} api.SetThreadDpiAwarenessContext(prev); } } ShowWindow(hwnd, SW_SHOW);
undefined identifier `ShowWindow`
UpdateWindow(hwnd);
undefined identifier `UpdateWindow`
SetTimer(hwnd, TIMER_ID, TICK_MS, null);
undefined identifier `SetTimer`
MSG
(local variable) _error_ msg
msg
;
undefined identifier `MSG`
while (GetMessageW(&msg, null, 0, 0) > 0)
undefined identifier `GetMessageW`
{ TranslateMessage(&msg);
undefined identifier `TranslateMessage`
DispatchMessageW(&msg);
undefined identifier `DispatchMessageW`
} logEvent("exit code=%d", cast(int) msg.wParam);
undefined identifier `logEvent`
return cast(int) msg.wParam; }