HeaderPane
Main
Hide

SftMask/DLL 7.0 - Masked Edit Control

Share Link
Print

Per-Monitor DPI and Scaling

SftMask/DLL 7.0 is fully Per-Monitor v2 DPI-aware. A masked edit control hosted on a Per-Monitor v2 aware top-level window will re-render automatically when its window moves to a monitor of a different DPI or when the system DPI changes. The control owns the metrics it controls; two flags let the caller opt in to automatic scaling of caller-supplied images and pixel dimensions.

Host setup

The host application must declare Per-Monitor v2 DPI awareness. This is the single most common reason SftMask/DLL 7.0 applications do not re-render correctly when moved between monitors of different DPI. Without a PMv2 declaration, Windows silently keeps the process in System-aware mode: the DPI is fixed for the process lifetime, SftMask does not observe DPI changes, SFTMASKN_DPI_CHANGED is never sent, and high-DPI monitors render at System-DPI sizes stretched by Windows. Visual Studio's default app.manifest does not declare PMv2 awareness - the developer must opt in explicitly.

Two approaches - pick one:

Application manifest (recommended)

Add a <dpiAwareness> / <dpiAware> element to the application manifest. Both elements are usually included for back-compatibility with older Windows 10 builds:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:windowsSettings>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

In a Visual Studio C++ project, set Project Properties -> Manifest Tool -> Input and Output -> Additional Manifest Files to the .manifest file above, or edit the auto-generated manifest directly.

Runtime API

Alternatively, call SetProcessDpiAwarenessContext at process startup, before any window is created:

SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);

Caveat: This call must run before the first window (including hidden startup dialogs or splash screens) is created. If a window has already been created, Windows rejects the call and the process remains in whichever mode the manifest specified.

Verifying the declaration worked

Quick check at runtime: GetDPI on the masked edit control returns the current monitor's DPI - 96 at 100%, 120 at 125%, 144 at 150%, 192 at 200%. If the returned value never changes as you drag the window between monitors with different scale factors, the host is not in PMv2 mode.

What the caller controls

Two independent flags let the caller choose whether caller-supplied pixel metrics and caller-supplied images scale with DPI. Both default to ASIS, preserving the behavior of applications written for earlier SftMask/DLL versions. Applications that want automatic scaling opt in by switching either flag to STRETCH.

FlagCoversASIS (default)STRETCH
SetImageScalingThe error images the control draws: ImageInvalid, ImageEmpty and ImageRequired.Images are drawn at their native pixel size. Images supplied at 96 DPI look physically smaller on a high-DPI monitor.Images are scaled by currentDPI / 96 at draw time.
SetPixelScalingCaller-supplied pixel dimensions on the SFTMASK_CONTROL structure (captionnWidth).Values are used verbatim in physical screen pixels.Values are interpreted as 96-DPI reference pixels. A value of 20 is 20 pixels at 100%, 30 pixels at 150%, 40 pixels at 200%. Storage and getters always return caller-reference units so serialized configurations stay portable.

Caller responsibilities on DPI change

When the control's monitor DPI changes, SftMask sends SFTMASKN_DPI_CHANGED to the parent window. The application should:

  • re-send WM_SETFONT with a font sized for the new DPI (SftMask does not own the application's font); with fAutoSize set, the control resizes itself to the new font automatically,
  • if SetImageScaling is STRETCH, no further action needed - the control scales the error images automatically,
  • if SetImageScaling is ASIS (default) and the caller wants crisp images, re-register the SFT_PICTURE error images at the new physical size,
  • if SetPixelScaling is STRETCH, no further action needed,
  • if SetPixelScaling is ASIS (default), re-apply caller-supplied pixel dimensions scaled for the new DPI if desired.

Platform note: Per-Monitor v2 DPI awareness requires Windows 10 version 1703 or later. On older platforms the host process runs in System-aware or Unaware mode and DPI is effectively fixed for the process lifetime - SftMask still renders correctly but does not send SFTMASKN_DPI_CHANGED.

See Also SetImageScaling | SetPixelScaling | GetDPI | Notifications


Last Updated 08/30/2026 - (email)
© 2026 Softel vdm, Inc.