SftTree/DLL 7.5 - Tree Control
SftBox/OCX 5.0 - Combo Box Control
SftButton/OCX 3.0 - Button Control
SftMask/OCX 7.0 - Masked Edit Control
SftTabs/OCX 6.5 - Tab Control (VB6 only)
SftTree/OCX 7.5 - Tree Control
SftTree/DLL 7.5 - Tree Control
SftBox/OCX 5.0 - Combo Box Control
SftButton/OCX 3.0 - Button Control
SftMask/OCX 7.0 - Masked Edit Control
SftTabs/OCX 6.5 - Tab Control (VB6 only)
SftTree/OCX 7.5 - Tree Control
SftTree/NET 2.0 - Tree Control
SftTree/OCX 8.0 is fully Per-Monitor v2 DPI-aware. A tree control hosted on a Per-Monitor v2 aware top-level window re-renders 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; the caller owns the images and fonts it provides. Two opt-in properties let the caller hand those over to the control as well.
The host application must declare Per-Monitor v2 DPI awareness. This is the single most common reason high-DPI applications do not re-render correctly when moved between monitors of different DPI. Without a Per-Monitor v2 declaration, Windows keeps the process in System-aware mode: the DPI is fixed for the process lifetime, the control does not observe DPI changes, the DPIChanged event is never fired, and high-DPI monitors render at System-DPI sizes stretched by Windows.
Declare Per-Monitor v2 awareness in the host application's manifest, for example:
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
In a .NET project, this corresponds to selecting Per Monitor V2 for the application's DPI awareness. The DPI property returns the control's current monitor DPI (96 at 100%, 120 at 125%, 144 at 150%, 192 at 200%). If the returned value never changes as the window is dragged between monitors with different scale factors, the host is not in Per-Monitor v2 mode.
When the host is Per-Monitor v2 aware, the control scales these metrics itself on every DPI change without any caller involvement: row height and item height, grid-line thickness, scroll bar and scroll arrow metrics, the drag threshold, 3D frame widths, the column drop-down / filter button width, the resize handle between panes of a split tree, the built-in expand / collapse glyphs, and the splitter bar width.
Two independent opt-in properties let the caller choose whether caller-supplied images and pixel metrics also scale with DPI. Both default to back-compatible behavior (no automatic scaling), so existing applications keep working unchanged. Each uses SftTreeScalingConstants: scalingSftTreeAsIs (default) or scalingSftTreeStretch.
| Property | Covers | scalingSftTreeAsIs (default) | scalingSftTreeStretch |
|---|---|---|---|
| ImageScaling | Every image the control draws: cell, label, item, row-header, column-header and column-footer pictures; plus / minus bitmaps; user-supplied tree button bitmaps; and control-owned glyphs. | Images are drawn at their native pixel size. Bitmaps supplied at 96 DPI look physically smaller on a high-DPI monitor. | Images are scaled by current DPI / 96 using high-quality interpolation. |
| PixelScaling | Caller-supplied pixel dimensions: column widths, indentation, row header width, horizontal extent and offset, item heights and the splitter offset. | Values are used verbatim in physical screen pixels. A column width of 100 is 100 pixels on any monitor. | Values are interpreted as 96-DPI reference pixels (100 pixels at 100%, 150 at 150%, 200 at 200%). Stored values and getters always return caller-reference units, so serialized configurations stay portable across monitors of different DPI. |
When the control's monitor DPI changes, the DPIChanged event is fired. The application should re-send a font sized for the new DPI (the control does not own the application's font). If ImageScaling is scalingSftTreeStretch and PixelScaling is scalingSftTreeStretch, no further action is needed - the control scales existing images and stored pixel values automatically.
