Net-Base Rivista

18.08.2026

VCL High-DPI: ridimensionare le icone in fase di esecuzione ed evitare l'effetto pixelato in TImageList

High-DPI nella VCL non è solo una casella di controllo, ma una catena composta da configurazione di ImageList, eventi di cambio DPI e rendering pulito. Questo contributo pratico mostra come scalare le icone a runtime, evitare artefatti e eseguire il debug in modo riproducibile delle trappole tipiche di TImageList.

18.08.2026

Dal tema della rivista alla pratica di progetto

Pagine di servizi e tecniche correlate all'articolo

Chi esegue applicazioni VCL su moderni Windows-Clients prima o poi si imbatte nello stesso sintomo: le icone a 125%/150%/200% appaiono come sfocate, sgranate o mostrano un bordo grigio. Proprio qui entra in gioco il tema VCL High-DPI Icons: non perché l’High-DPI sia una novità, ma perché i problemi emergono soprattutto nell’uso quotidiano — su Terminalserver, al cambio docking/undocking del notebook o non appena ogni monitor ha una DPI diversa.

La questione centrale quasi mai è che il PNG sia rotto, bensì la pipeline: da dove proviene l’icona (risorsa, file, SVG, font), in quale risoluzione viene fornita, come finisce nella TImageList e chi scala quando e come. Nella VCL confluiscono poi diversi concetti che vanno distinti: DPI-Awareness (se Windows scala l’app o l’app si scala da sola), Per-Monitor-DPI (ogni monitor può avere valori diversi) e ImageList-Strategie (mantenere più risoluzioni o rasterizzare a runtime).

In questo articolo non si discute di dibattiti sul design dell’interfaccia, ma si presenta un approccio pulito e operativo: scalare le icone a runtime in modo che non diventino un ammasso di pixel, che i canali alpha restino intatti e che i cambi di DPI avvengano senza sfarfallii o dimensioni immagine errate. Aggiungono valore le trappole note, suggerimenti per il debug e una valutazione onesta su quando l’investimento aggiuntivo è giustificato.

Perché si crea perdita di nitidezza: comprendere la catena di ridimensionamento nella VCL

Grafik zur Icon-Skalierung: Master-Icon wird in mehrere Zielgrf6dfen gerastert, doppelte Skalierung ffchrt zu Unsche4rfe
Un singolo ridimensionamento da una sorgente master è controllabile — passaggi di resampling doppi portano rapidamente a una perdita di nitidezza visibile.

La causa più frequente di icone sfocate è un unico down-/upscaling al momento sbagliato. Flusso classico nella VCL legacy:

  • L’applicazione fornisce le icone solo in 16×16 o 24×24.
  • Windows o la VCL le scala a 20×20 / 32×32 / 48×48.
  • Il motore di scaling utilizza un’interpolazione pensata per le foto, che sulle immagini pixel-art sfoca i bordi.
  • In aggiunta, la trasparenza (canale alpha) viene compressa in una logica di maschera o convertita più volte.

La situazione peggiora quando avvengono più passaggi di scala uno dopo l’altro: ad esempio quando la ImageList già fornisce un bitmap scalato e poi Windows — perché DPI-unaware o per impostazione di sistema — lo scala di nuovo. Risultato: doppio ammorbidimento.

Un secondo punto spesso sottovalutato nei progetti è il momento del ridimensionamento. Con Per-Monitor-DPI (PMv2, cioè Per-Monitor-DPI-Awareness v2) l’effettiva DPI può cambiare quando una finestra si sposta su un altro monitor o quando un client Remote Desktop adatta dinamicamente la DPI. Se in tali casi una TImageList o una cache non vengono ricostruite correttamente, le icone possono apparire improvvisamente nella dimensione sbagliata o con un raster non corretto.

TImageList sotto High-DPI: trappole tipiche nelle applicazioni reali

La TImageList è storicamente pensata per piccole bitmap, con misure fisse, indici e una logica di memorizzazione relativamente rigida. In scenari High-DPI questo porta a trappole pratiche:

1) Width/Height cablati

Molti form VCL impostano ImageList.Width/Height in fase di design e poi non ci tornano più. Con il 150% Windows però potrebbe voler ridimensionare, p. es., da 16×16 a 24×24. Se la lista resta a 16×16, l’immagine viene o tagliata (clipped) o ridimensionata altrove — entrambe soluzioni sgradevoli.

2) PNG-Alpha e logica delle maschere

A seconda della versione di Delphi e dei controlli VCL ci si ritrova rapidamente in una situazione mista: PNG con alpha internamente gestiti a volte come bitmap a 32 bit e a volte come Mask+Color. Appena converti più volte (PNG → Bitmap → ImageList → Draw) compaiono aloni grigi o bordi netti. L’effetto dipende spesso dallo sfondo: su una toolbar scura si nota più che su un pannello chiaro.

3) Cambio DPI a runtime: cache, handle, OwnerDraw

Alcuni controlli fanno cache della resa delle immagini o acquisiscono gli ImageList-Handles in un momento in cui la DPI non è ancora definitiva. Soprattutto in toolbar, TreeViews/ListViews e scenari OwnerDraw si osservano dopo i cambi DPI immagini con dimensioni errate o icone vuote, finché non avviene un repaint o un RecreateWnd.

4) Terminal server e Remote Desktop come banco di prova reale

Quando l’app è usata via RDP, i cambi DPI e i riconnessioni di sessione non sono esotici. Proprio lì una strategia non robusta per le ImageList si rivela problematica: l’utente vede, dopo il reconnect, icone sfocate o barre degli strumenti scalate in modo errato, anche se in locale tutto era a posto.

Approccio corretto: fornire più risoluzioni invece di un upscaling drastico

La decisione più importante è concettuale: vuoi ridimensionare le icone a runtime a partire da un’unica immagine base (p. es. 16×16 → 32×32), o fornisci più risoluzioni native e scegli quella appropriata in base alla DPI?

In pratica quasi sempre vince l’approccio delle più risoluzioni. L’upscaling è accettabile se la sorgente è vettoriale (SVG, font di icone) o se servono solo fattori moderati. Se ingrandisci molto a partire da una bitmap piccola perdi qualità dei bordi, e questo si vede subito sui display moderni.

Nell’ecosistema VCL oggi per questo approccio sono rilevanti due componenti:

  • TImageCollection: contenitore per immagini in più dimensioni/varianti.
  • TVirtualImageList: genera da queste, a runtime, una ImageList nella dimensione effettivamente necessaria e reagisce ai cambi DPI.

Non risolve automaticamente ogni problema, ma sposta la responsabilità al punto giusto: definisci le sorgenti immagine in modo pulito e la selezione/scala avviene in modo coerente.

Scalare le icone VCL High-DPI a runtime: quando ha senso (e quando no)

Ci sono motivi legittimi per scalare le icone a runtime:

  • Carichi icone dinamicamente (p. es. da una cartella di plugin, pacchetti di branding cliente, pacchetti di configurazione).
  • Vuoi una pipeline unificata per diverse sorgenti (ICO, PNG, SVG) e non vuoi includere tutte le varianti a build time.
  • Generi icone programmaticamente (badge di stato, overlay, simboli composti).

Non ha senso la scalatura a runtime se hai solo icone da toolbar classiche da un insieme fisso. In quel caso la soluzione più semplice da mantenere è: distribuire pulitamente più risoluzioni e lasciare che la VCL scelga.

Se implementi la scalatura a runtime, fallo con regole chiare:

  • Mai ridimensionare nuovamente un bitmap già scalato. Parti sempre da una fonte master (idealmente vettoriale o ad alta risoluzione).
  • Cache per dimensione di destinazione e DPI, altrimenti ridimensioni ad ogni paint — questo costa CPU e può causare scatti.
  • Mantenere l’alpha: minimizzare le conversioni, usare 32-bit RGBA, non rasterizzare lo sfondo.

Architettura pragmatica: pipeline delle icone come componente separato

Nelle applicazioni più grosse conviene non disperdere il tema ovunque, ma costruire una piccola pipeline. Non deve essere un framework — piuttosto un chiaro ambito di responsabilità:

  • Sorgente delle icone: da dove provengono gli asset master (risorse, file, database, API)?
  • Rasterizer/Scaler: come si genera la dimensione di destinazione dalla master (interpolazione, eventualmente rendering SVG)?
  • Cache: chiave (Icon-ID, pixel di destinazione, DPI, tema) e ciclo di vita (invalidare al cambio DPI, cambio tema, cambio pacchetto).
  • Consumer-Adapter: come arriva il risultato nelle strutture VCL (TImageList/TVirtualImageList, OwnerDraw, PaintBox)?

Vantaggio: puoi riprodurre e debugare i bug legati ai DPI in un punto solo, invece di cercare in 40 form dove viene ancora scalato.

Gestire correttamente il cambio di DPI: eventi, rebuild, repaint

Notebook mit zwei Monitoren unterschiedlicher DPI, Fensterwechsel zeigt unterschiedliche Icon-Grf6dfen in einer Desktop-App
Il DPI per monitor è il test della realtà: al cambio di monitor la pipeline delle icone deve rasterizzare di nuovo, non solo ridisegnare.

Sotto Windows il cambio DPI è un ciclo di vita a sé. Nella VCL, a seconda della versione e della DPI-awareness, ci sono vari eventi/meccanismi, ma il principio di base resta:

  • Se il DPI della finestra cambia, le risorse basate su immagini che devono essere pixel-accurate devono essere fornite nuovamente.
  • Se riempi dinamicamente ImageLists, un semplice Invalidate spesso non basta — ti serve un Rebuild delle immagini nella nuova dimensione di destinazione.

Un pattern pratico è: al cambio DPI (p.es. Form-Scale/cambio monitor) invalidi la cache delle icone per quel DPI e ricostruisci le ImageLists interessate. È importante non scalare negli eventi di paint, ma farlo in un blocco di aggiornamento controllato (Toolbar.BeginUpdate/EndUpdate, ListView-Redraw disattivato e poi riattivato). Così eviti sfarfallii e stati UI incompleti.

Perché TImageList diventa spesso sfocata: interpolazione, arrotondamento DPI, bordi

Quando capisci che il problema non è il solo DPI, ma interpolazione più arrotondamento, molti effetti si spiegano:

  • Arrotondamento DPI: 125% non è un raddoppio pulito. Da 16 px si passa a 20 px (16 * 1,25). Da 24 px si passa a 30 px. Sono numeri irregolari che complicano i bordi dei pixel.
  • Filtro di resampling: Bilinear/Bicubic ammorbidisce i bordi. Questo va bene per le foto, spesso non per le icone.
  • Effetti subpixel: Windows può, a seconda del percorso di rendering, usare o meno il subpixel-antialiasing. Per le icone vuoi bordi controllati — e possibilmente nessuna moltiplicazione degli stadi di filtro.

Se hai icone raster, in molti team è pratica comune fornire PNG separati per ciascuna dimensione target (16/20/24/32/40/48). Sembra molto, ma spesso richiede meno lavoro che passare anni a fare debug del tipo “perché su questo monitor sembra strano”.

Debugging: rendere riproducibile il pixel-mess invece di correggere a sensazione

Arbeitsplatz mit Debug-Notizen für Icon-Skalierung und Hintergrundtests zur Alpha-Kante
Buone routine di DPI-debug testano dimensioni, sfondi e tempi di rebuild — non solo il primo screenshot.

I bug High-DPI spesso sembrano casuali. Con qualche check diventano deterministici:

1) Loggare DPI e dimensioni ImageList a runtime

Registra all’avvio e al cambio DPI: CurrentPPI del form, Screen.PixelsPerInch (Attenzione: questo può essere il DPI di sistema), e ImageList.Width/Height delle liste interessate. Se dopo un cambio monitor vedi ancora 16 mentre ti aspetti 32, la causa è chiara: manca il rebuild o arriva troppo tardi.

2) Ingrandire visibilmente le icone

Un test rapido è impostare temporaneamente le icone della toolbar a 48 px. Una scalatura scadente salta subito all’occhio. Pipeline ben progettate restano nitide anche a 48 px perché rasterizzano da una sorgente adeguata.

3) Testare cambio tema e sfondo

I “halo” ai bordi sono spesso problemi di alpha/premultiply. Testa su chiaro/scuro e su superfici con gradienti. Se il bordo cambia aspetto a seconda dello sfondo, il trattamento della trasparenza non è corretto.

4) Remote Desktop / cambio monitor come script di test

Crea un breve script di test per la QA: avvia l’app sul monitor A (100%), sposta la finestra sul monitor B (150%), ritorna, poi riconnetti RDP. Se questo è stabile, molti problemi dei clienti sono già risolti.

Migrazione in applicazioni esistenti: passo dopo passo invece del Big Bang

Nelle applicazioni VCL cresciute nel tempo la logica delle icone spesso è distribuita: menu, barre strumenti, ActionLists, TreeViews, indicatori di stato. Un rifacimento in una sola soluzione comporta rischi. Si è dimostrato efficace un approccio graduale:

  • Inventario: Quali ImageList esistono? Quali controlli le utilizzano? Quali dimensioni sono previste?
  • Prioritizzare: Inizia dalle aree più visibili (toolbar principale, navigazione, menu contestuali).
  • Sorgente unificata: Centralizza le icone (ImageCollection o un loader dedicato) invece di caricare file singoli per ogni form.
  • Test cambio DPI: Dal primo modulo convertito esegui sistematicamente test di cambio DPI.

Importante: se gestisci in parallelo pipeline vecchie e nuove, documenta regole chiare. Altrimenti si crea una situazione mista in cui alcune icone risultano nitide e altre visibilmente sfocate.

Prestazioni e memoria: scalabilità a runtime senza effetti collaterali

La scalatura costa CPU e memoria. In un software aziendale questo raramente si nota a riposo, ma trascinando la finestra su un nuovo monitor o all’avvio con molte form può causare micro-interruzioni. Tre linee guida pratiche:

  • Limitare le dimensioni della cache: non conservare ogni livello intermedio per sempre. Se ti servono solo 100% e 150%, memorizza nella cache soltanto questi.
  • Lazy Build: rasterizzare le icone solo quando lo schermo ne ha effettivamente bisogno. Con menu estesi si risparmia tempo di avvio.
  • Batch-Rebuild: al cambio di DPI non attivare ogni control singolarmente. Un rebuild centrale evita ridimensionamenti ridondanti.

Se lavori con TVirtualImageList, gran parte di questo è già prevista come concetto, ma devi comunque fare attenzione a non sovrapporre ulteriori meccanismi di scalatura personalizzati.

Strategie di fallback: cosa fare se non sono disponibili tutte le dimensioni delle icone?

Nella realtà non hai sempre tutte le risorse in tutte le dimensioni. Serve quindi una strategia di fallback chiara per evitare risultati casuali:

  • Preferire il downscale: meglio ridurre da 64 px a 32 px che ingrandire da 16 px a 32 px.
  • Definisci i livelli: stabilisci quali dimensioni target supporti realmente (es. 16/20/24/32/40/48) e mappa correttamente le DPI su di essi.
  • Testare la trasparenza: con i fallback presta attenzione all’alpha — è proprio lì che si formano gli aloni.

Un errore tipico è prendere qualsiasi dimensione successiva disponibile. Così la percezione di nitidezza varia da icona a icona. Meglio avere un piano di mapping rigido e documentato.

Quando vale davvero la pena lo sforzo?

Ci sono tre indicatori chiari che giustificano una pipeline di icone High‑DPI ben strutturata:

  • I tuoi utenti lavorano con monitor misti (laptop + esterno) o usano molto RDP.
  • L’applicazione è duratura e viene mantenuta per anni — la percezione dell’interfaccia è parte dell’accettazione.
  • Hai comunque in programma interventi di modernizzazione (aumentare la DPI-awareness, sostituire control, rivedere il layout della toolbar).

Se invece l’app gira solo su un sistema chiosco fisso con risoluzione identica, si può mantenere il tema al minimo: fornire la dimensione icona adeguata, impostare correttamente la DPI-awareness e basta.

Conclusione: High‑DPI non è un dettaglio cosmetico, ma una decisione di rendering

Le icone sfocate nella VCL raramente sono un errore isolato; indicano una catena imprecisa tra sorgenti, scalatura e caching. La strada più robusta è fornire le icone in più risoluzioni e distribuirle in modo coerente tramite una pipeline centrale (ad es. ImageCollection/VirtualImageList o un proprio layer di icone). La scalatura a runtime ha senso quando hai sorgenti dinamiche o simboli composti, ma solo con una fonte master, cache basata su DPI e regole di rebuild chiare.

Se hai sintomi concreti (il cambio DPI danneggia le icone, aloni sui bordi, dimensioni errate dopo RDP), conviene isolare il problema e trattarlo come un piccolo componente di architettura, anziché accumulare workaround per ogni form. Se ti serve supporto nel debugging o in una modernizzazione graduale, trovi qui il punto di partenza appropriato: contatto a Net-Base Software GmbH.

Per questo tema sono importanti anche Timagelist High Dpi e Delphi Vcl Dpi-Awareness. Il contributo inquadra questi aspetti in modo chiaro e mostra su cosa occorre concentrarsi nella pratica quotidiana.

Discutere un progetto o un intervento di modernizzazione con Net-Base.

Passo successivo

Quando un tema diventa un progetto reale, architettura, sistemi esistenti e gestione operativa dovrebbero essere considerati insieme fin dalle fasi iniziali.

Non forniamo solo supporto per questioni isolate, ma anche quando da frammenti di codice sorgente, tematiche legacy o idee di portale deve nascere un progetto aziendale solido.

  • Stato attuale, stato obiettivo e rischi tecnici vengono valutati insieme.
  • REST, l'accesso ai dati, i portali e il rollout non vengono rinviati a fasi successive.
  • Vede in anticipo quale percorso è economicamente e operativamente sostenibile.

Condividi il post

Condividi direttamente questo articolo

LinkedIn, X, XING, Facebook, WhatsApp e e-mail sono immediatamente disponibili. Per Instagram prepariamo direttamente il link e un breve testo.

E-mail

Instagram si apre in una nuova scheda. Il link e il breve testo vengono copiati prima negli appunti.