Net-Base Revija

18.08.2026

VCL High-DPI: skaliranje ikon med izvajanjem in preprečevanje pikselnega razmaza v TImageList

High-DPI v VCL ni zgolj polje za potrditev, temveč veriga postopkov: nastavitve ImageList, dogodki ob spremembi DPI in čisto upodabljanje. Ta praktični prispevek pokaže, kako med izvajanjem skalirati ikone, preprečiti artefakte in tipične pasti TImageList na reproducibilen način razhroščevati.

18.08.2026

Od teme v reviji do projektne prakse

Ustrezne strani storitev in tehnični opisi k prispevku

Kdor izvaja VCL-aplikacije na sodobnih Windows-klientih, prej ali slej naleti na isti simptom: ikone pri 125%/150%/200% delujejo zamegljene, raztrgane ali dobijo siv rob. Ravno tukaj postane vprašanje VCL High-DPI Icons praktično relevantno: ne zato, ker bi bilo High-DPI novo, ampak ker se težave ponavadi pokažejo šele v vsakdanjem delovanju — na terminalskih strežnikih, pri preklopu prenosnika v dock ali takrat, ko ima vsak monitor drugačen DPI.

Glavno vprašanje skoraj nikoli ni, da je PNG pokvarjen, temveč pipeline: od kod prihaja ikona (Ressource, Datei, SVG, Font), v kateri velikosti je na voljo, kako pristane v TImageList in kdo kdaj kako skalira. V VCL se nabere več pojmov, ki jih je treba ločiti: DPI-Awareness (ali Windows skalira aplikacijo ali aplikacija sama sebe), Per-Monitor-DPI (vsak monitor sme biti drugačen) in ImageList-Strategie (hraniti več Auflösungen ali rastarizirati ob izvajanju).

V tem prispevku ne gre za razprave o UI-dizajnu, temveč za čist, obratovalno zanesljiv pristop: skalirati ikone ob izvajanju, a tako, da ne postanejo pixelmatsch, da ostanejo Alpha-Kanäle intaktni in da zamenjave DPI delujejo brez utripanja ali napačnih Bildgrößen. Poleg tega so opisane pasti, nasveti za razhroščevanje in poštena Einschätzung, kdaj se dodatni napor splača.

Warum Pixelmatsch entsteht: Skalierungskette in der VCL verstehen

Grafika za skaliranje ikon: master-ikona se rasterizira v več ciljnih velikosti, dvojno skaliranje vodi v zamegljenost
Enkratna skalacija iz master-izvora je obvladljiva — dvojni Resampling-Schritte hitro povzročijo vidno zamegljenost.

Najpogostejši razlog za zamegljene ikone je enkratno Down-/Upscaling ob nepravem času. Klasičen potek v Legacy-VCL:

  • Aplikacija dobavlja ikone samo v 16×16 ali 24×24.
  • Windows ali VCL skalira na 20×20 / 32×32 / 48×48.
  • Skalator uporablja interpolacijo, ki je za fotografije sprejemljiva, za pikselno grafiko pa zamegli robove.
  • Poleg tega se prosojnost (Alpha) stisne v maskno logiko ali večkrat konvertira.

Še posebej nezgodno postane, ko se pojavi več skaliranj zapored: na primer, če ImageList že vrne skalirano bitmapo in Windows zaradi DPI-Unaware ali sistemskega DPI znova preslika. Rezultat: dvojno weichgezeichnet.

Druga, v projektih pogosto podcenjena točka je Skalierungs-Zeitpunkt. Pri Per-Monitor-DPI (bzw. PMv2, torej Per-Monitor-DPI-Awareness v2) se lahko efektivni DPI spremeni, ko okno zamenja monitor ali ko ga Remote-Desktop-Client dinamično prilagodi. Če nato TImageList ali predpomnilnik ni pravilno znova zgrajen, se nenadoma vidijo ikone v napačni Größe ali z napačnim Raster.

TImageList unter High-DPI: typische Fallen in echten Anwendungen

Die TImageList ist historisch für kleine Bitmaps gedacht, mit festen Maßen, Indizes und relativ starrer Speicherlogik. Unter High-DPI ergeben sich daraus praxisnahe Fallen:

1) Fest verdrahtete Width/Height

Viele VCL-Formulare setzen ImageList.Width/Height zur Designzeit und lassen es dabei. Bei 150% möchte Windows aber z. B. aus 16×16 eher 24×24 machen. Wenn die Liste auf 16×16 bleibt, wird entweder geclippt oder an anderer Stelle skaliert — beides unschön.

2) PNG-Alpha und Maskenlogik

Je nach Delphi-Version und VCL-Controls landet man schnell in einem Mischbetrieb: PNGs mit Alpha werden intern teils als 32-bit Bitmap gehalten, teils als Mask+Color. Sobald du mehrfach konvertierst (PNG → Bitmap → ImageList → Draw), entstehen graue Halos oder harte Kanten. Der Effekt ist häufig backgroundsensitiv: Auf dunkler Toolbar sieht es schlimmer aus als auf einem hellen Panel.

3) DPI-Wechsel zur Laufzeit: Caches, Handles, OwnerDraw

Einige Controls cachen die Bilddarstellung oder übernehmen ImageList-Handles zu einem Zeitpunkt, wo die DPI noch nicht final ist. Besonders bei Toolbars, TreeViews/ListViews und OwnerDraw-Szenarien sieht man nach DPI-Wechseln sporadisch falsche Bildgrößen oder blasse/leer erscheinende Icons, bis ein Repaint oder ein RecreateWnd passiert.

4) Terminalserver und Remote-Desktop als Realitätstest

Wenn die App über RDP genutzt wird, sind DPI-Wechsel und Session-Reconnects nicht exotisch. Genau dort fliegt dir eine unrobuste ImageList-Strategie um die Ohren: Der Benutzer sieht nach dem Reconnect verwaschene Icons oder falsch skalierte Symbolleisten, obwohl lokal alles ok war.

Sauberer Ansatz: Mehrere Auflösungen bereitstellen statt brutales Upscaling

Die wichtigste Entscheidung ist konzeptionell: Willst du Icons zur Laufzeit aus einer einzigen Basisgrafik hochskalieren (z. B. 16×16 → 32×32), oder stellst du mehrere native Auflösungen bereit und wählst je nach DPI die passende?

In der Praxis gewinnt fast immer „mehrere Auflösungen“. Upscaling kann man machen, wenn die Quelle vektorbasiert ist (SVG, Icon-Font) oder wenn du wirklich nur moderate Faktoren brauchst. Sobald du aus einem kleinen Rasterbild stark hochskalierst, verlierst du Kantenqualität, und das siehst du auf modernen Displays sofort.

In der VCL-Welt sind für diesen Ansatz heute zwei Bausteine relevant:

  • TImageCollection: Container für Bilder in mehreren Größen/Varianten.
  • TVirtualImageList: erzeugt daraus zur Laufzeit eine ImageList in der aktuell benötigten Größe und reagiert auf DPI-Änderungen.

Das nimmt dir nicht alle Probleme ab, aber es verschiebt das Problem an die richtige Stelle: Du definierst Bildquellen sauber, und die Skalierung/Selektion passiert konsistent.

VCL High-DPI Icons zur Laufzeit skalieren: Wann es sinnvoll ist (und wann nicht)

Es gibt legitime Gründe, Icons zur Laufzeit zu skalieren:

  • Du lädst Icons dynamisch (z. B. aus einem Plugin-Ordner, kundenspezifische Branding-Pakete, Konfigurationspakete).
  • Du willst eine einheitliche Pipeline für verschiedene Quellen (ICO, PNG, SVG) und möchtest nicht alle Varianten zur Build-Zeit binden.
  • Du erzeugst Icons programmgesteuert (Status-Badges, Overlays, zusammengesetzte Symbole).

Skaliranje v času izvajanja ni smiselno, če dejansko uporabljaš le klasične ikone orodne vrstice iz fiksnega nabora. Najmanj zahteven način za vzdrževanje je: dostaviti več ločljivosti in pustiti VCL, da izbere.

Če izvajaš skaliranje v času izvajanja, potem z jasnimi pravili:

  • Nikoli ponovno ne skaliraj že skalirane bitmapne slike. Vedno izhajaj iz master-izvora (idealno vektorsko ali visoke ločljivosti).
  • Predpomnilnik za vsako ciljno velikost in DPI, sicer boš pri vsakem Paintu ponovno skaliral — to porabi CPU in lahko povzroči trzanje.
  • Ohrani alfa-kanal: zmanjaj konverzije, uporabi 32-bitni RGBA, ozadij ne rasteriziraj.

Pragmatična arhitektura: cevovod ikon kot samostojna komponenta

V ve07jih aplikacijah se izpla0da temo ne razpr61iti po vsej kodi, temve0d zgraditi majhen cevovod. To ne rabi biti framework — prej jasna odgovornost:

  • Vir ikon: Od kod prihajajo izvorni asseti (viri, datoteke, baza podatkov, API)?
  • Rasterizer/Scaler: Kako se iz master-izvora ustvari ciljna velikost (interpolacija, po potrebi renderiranje SVG)?
  • Predpomnilnik: klju0d (Icon-ID, ciljni piksli, DPI, tema) in 7eivljenjski cikel (invalidirati ob menjavi DPI, menjavi teme, menjavi paketa).
  • Consumer-Adapter: Kako rezultat pride v VCL-strukture (TImageList/TVirtualImageList, OwnerDraw, PaintBox)?

Prednost: DPI-napake lahko reproducira61 in odpravi61 na enem mestu, namesto da v 40 Forms iščeš, kje se ponovno skalira.

DPI-Wechsel korrekt behandeln: Ereignisse, Rebuild, Repaint

Notebook mit zwei Monitoren unterschiedlicher DPI, Fensterwechsel zeigt unterschiedliche Icon-Grf6dfen in einer Desktop-App
Per-Monitor-DPI je preizkus resni0dnosti: ob menjavi monitorja mora cevovod ikon znova rasterizirati, ne le ponovno narisati.

V okviru Windows so menjave DPI lasten 7eivljenjski cikel. V VCL je glede na razli0dico in DPI-awareness ve0d dogodkov/mehanizmov, vendar osnovno na0delo ostaja:

  • 0ce se DPI okna spremeni, je treba slikovne vire, ki morajo biti pikselno natan0dni, znova pripraviti.
  • 0ce dinami0dno polni61 ImageLists, pogosto ne zadostuje zgolj Invalidate — potrebuje61 ponovno izgradnjo slik v novi ciljni velikosti.

Prakti0den vzorec je: ob spremembi DPI (npr. Form-Scale/menjava monitorja) invalidira61 predpomnilnik ikon za to DPI in znova izgradi61 prizadete ImageLists. Pomembno je, da ne skalira61 znotraj Paint-dogodkov, temve0d v kontroliranem bloku posodobitve (Toolbar.BeginUpdate/EndUpdate, ListView-Redraw aus, dann wieder an). Tako se izogne061 utripanju in delno dokon0danim UI-stanjem.

Warum TImageList so oft unscharf wird: Interpolation, DPI-Rundung, Kanten

Ko enkrat razume61, da te7eava ni v samem DPI, temve0d v interpolaciji in zaokro7evanju, se da veliko u0dinov razlo7eiti:

  • DPI-Rundung: 125% ni čista podvojitev. Iz 16 px postane 20 px (16 * 1,25). Iz 24 px postane 30 px. To so nerodne številke, ki otežujejo robove pikslov.
  • Resampling-Filter: Bilinear/Bicubic robove zmehča. To je za fotografije v redu, za ikone pa pogosto ne.
  • Subpixel-Effekte: Windows lahko glede na render-poti uporabi ali ne uporabi subpixel-antialiasinga. Pri ikonah želite nadzorovane robove in po možnosti brez večkratnih filtrov.

Če imate raster-ikone, je v mnogih ekipah uveljavljen postopek, da za vsako ciljno velikost zagotovite ločene PNG-je (16/20/24/32/40/48). Zveni kot veliko, a je pogosto manj dela kot leta razhroščevati „zakaj na tem monitorju to izgleda čudno“.

Debugging: Pixelmatsch reproduzierbar machen statt nach Bauchgefühl zu fixen

Arbeitsplatz mit Debug-Notizen für Icon-Skalierung und Hintergrundtests zur Alpha-Kante
Dobre DPI-debugging-routine testirajo velikosti, ozadja in časovne točke rebuildov — ne samo prvi posnetek zaslona.

High-DPI-bug-i pogosto delujejo naključno. Z nekaj preverjanji postanejo deterministični:

1) DPI und ImageList-Größen zur Laufzeit loggen

Zalogirajte ob zagonu in ob spremembi DPI: CurrentPPI formularja, Screen.PixelsPerInch (pozor: to je lahko sistemski DPI) ter ImageList.Width/Height prizadetih seznamov. Če po menjavi monitorja še vedno vidiš 16, čeprav pričakuješ 32, je vzrok jasen: rebuild manjka ali pride prepozno.

2) Icons sichtbar vergrößern

Hiter test je začasno nastaviti ikone orodne vrstice na 48 px. Slaba skalacija takoj izstopi. Dobri procesi ostanejo tudi pri 48 px ostri, ker rasterizirajo iz primernega izvora.

3) Theme- und Hintergrundwechsel testen

Halos ob robovih so pogosto problemi z alpha/premultiply. Testirajte na svetlem/temnem in na površinah z barvnimi prehodi. Če rob izgleda drugače glede na ozadje, obdelava prosojnosti ni pravilna.

4) Remote Desktop / Monitorwechsel als Testskript

Naredite kratek testni skript za QA: aplikacijo zaženite na monitorju A (100%), premaknite okno na monitor B (150%), nazaj, nato ponovno povežite RDP. Če je to stabilno, je veliko strankinih problemov že odpravljeno.

Migration in bestehenden Anwendungen: Schrittweise statt Big Bang

V zraslih Delphi-VCL-aplikacijah je logika ikon pogosto razpršena po mnogih mestih: meniji, orodne vrstice, ActionLists, TreeViews, statusne prikaze. Velika prenova naenkrat prinaša tveganje. Dokazano se je izkazal postopni pristop:

  • Inventur: Katere ImageLists obstajajo? Kateri kontrolniki jih uporabljajo? Katere velikosti se pričakujejo?
  • Priorisieren: Najprej najvidnejše površine (glavna orodna vrstica, navigacija, kontekstni meniji).
  • Einheitliche Quelle: Centralizirajte ikone (ImageCollection ali lasten loader), namesto da za vsak form nalagate posamezne datoteke.
  • DPI-Wechsel testen: Od prvega predelanega modula naprej dosledno izvajajte teste menjave DPI.

Pomembno: Če hkrati uporabljaš staro in novo pipeline, dokumentiraj jasna pravila. Sicer nastane mešana krajina, v kateri so nekateri ikoni ostri, drugi pa vidno zamegljeni.

Performance in pomnilnik: skaliranje v času izvajanja brez stranskih učinkov

Skaliranje stane CPU in pomnilnik. V poslovni programski opremi to redko izstopa v praznem teku, lahko pa se pojavi ob presleku okna na nov monitor ali pri zagonu z veliko formami, kjer lahko nastanejo zatiki. Tri praktična vodila:

  • Omeji velikost cache-a: Ne hraniti vsake vmesne stopnje za vedno. Če rabiš le 100 % in 150 %, keširaj le ti.
  • Lazy build: Ikone rasteriziraj šele, ko jih zaslon dejansko potrebuje. Pri velikih menijih to prihrani čas zagona.
  • Batch-rebuild: Pri DPI-spremembi ne sprožaj vsakega kontrola posebej. Centralni rebuild prepreči redundantno skaliranje.

Če delaš s TVirtualImageList, je veliko tega že vgrajenega kot koncept, vendar moraš vseeno paziti, da ne zgradiš še dodatnega lastnega skaliranja na vrhu.

Fallback-strategije: Kaj narediti, če niso na voljo vse velikosti ikon?

V praksi nimaš vedno vseh assetov v vseh velikostih. Potrebuješ jasen fallback-naslov, da se izogneš naključnim rezultatom:

  • Raje pomanjševanje (prefer downscale): Bolje zmanjšati iz 64 px na 32 px kot povečati iz 16 px na 32 px.
  • Opredeli stopnje: Določi, katere ciljne velikosti res podpreš (npr. 16/20/24/32/40/48) in nanje dosledno mapiraj DPI.
  • Testiraj transparentnost: Pri fallbackih posebno pozornost namenjaj alpha-kanalu — prav tam nastajajo halo-artefakti.

Tipična napaka je vzeti kar katerokoli naslednjo velikost. Posledica je, da se zaznana ostrina razlikuje glede na ikonico. Bolje je imeti na trdo določeno, dokumentirano mapirno strategijo.

Kdaj se vložek resnično izplača?

Obstajajo trije jasni indikaterji, da se splača vzpostaviti urejeno High‑DPI‑ikon pipeline:

  • Tvoji uporabniki delajo z mešanimi monitorji (prenosnik + zunanji) ali pogosto preko RDP.
  • Aplicacija je dolgotrajna in bo vzdrževana leta; dojemanje UI je del sprejemljivosti.
  • V načrtu imaš že modernizacijske ukrepe (povišanje DPI‑awareness, zamenjava kontrol, prenova postavitve orodne vrstice).

Če aplikacija teče le na fiksnem kiosku z enako ločljivostjo, je smiselno zadevo držati minimalno: dostavi ustrezno ikonsko velikost, pravilno nastavi DPI‑awareness in to je to.

Zaključek: High‑DPI ni kozmetična podrobnost, temveč odločitev pri renderiranju

Neostre ikone v VCL redko pomenijo izoliran problem; običajno kažejo na neurejeno verigo iz virov, skaliranja in keširanja. Najbolj robustno je zagotoviti ikone v več ločljivostih in jih dosledno servirati preko centralne pipeline (npr. ImageCollection/VirtualImageList ali lastne ikon‑plasti). Skaliranje v času izvajanja ima smisel, kadar imaš dinamične vire ali sestavljene simbole — vendar le ob pogoju master‑vira, DPI‑baziranega cache‑a in jasnih pravil za rebuild.

Če imaš konkretne simptome (DPI‑preklop uničuje ikone, halo ob robu, napačne velikosti po RDP), se izplača temo ciljno izolirati in obravnavati kot manjši arhitekturni gradnik, namesto da zlagamo delne rešitve po posameznih formah. Če pri tem potrebuješ podporo pri debugiranju ali postopni modernizaciji, najdeš primeren začetek tukaj: Kontakt zur Net-Base Software GmbH.

Za to temo sta pomembna tudi Timagelist High Dpi in Delphi Vcl Dpi-Awareness. Prispevek te vidike razumljivo umešča v kontekst in pokaže, na kaj je v vsakodnevnem delu treba biti pozoren.

Projekt ali načrt modernizacije z Net-Base obravnavajte.

naslednji korak

Ko iz teme nastane resničen projekt, je treba arhitekturo, obstoječe sisteme in obratovanje zgodaj obravnavati skupaj.

Ne podpiramo le pri posameznih vprašanjih, ampak tudi takrat, ko iz izrezkov izvorne kode, legacy-tem ali idej za portale nastane zanesljiv podjetniški projekt.

  • Obstoječe stanje, ciljno stanje in tehnična tveganja se ocenjujejo skupaj.
  • REST, dostop do podatkov, portali in Rollout ne bodo prestavljeni v kasnejše faze.
  • Že zgodaj vidite, katera pot je ekonomsko in operativno vzdržna.

Deli objavo

Deli ta prispevek neposredno

LinkedIn, X, XING, Facebook, WhatsApp in e-pošta so takoj na voljo. Za Instagram pripravljamo povezavo in kratek tekst.

E-pošta

Instagram se odpre v novem zavihku. Povezava in kratek opis se pred tem kopirata v odložišče.