Net-Base Magasin

18.08.2026

VCL High-DPI: Skalere ikonar ved køyretid og unngå pikselutvasking i TImageList

High-DPI i VCL er ikkje berre ein avkryssingsboks, men ei kjede av ImageList-oppsett, DPI-skjiftehendingar og reint rendering. Denne praksisartikkelen viser korleis du skalerer ikoner i køyretid, unngår artefaktar og feilsøkjer typiske TImageList-fellar på ein reproduserbar måte.

18.08.2026

Frå magasinetema til prosjektpraksis

Passande teneste- og tekniske sider til innlegget

Den som køyrer VCL-applikasjonar på moderne Windows-klientar, snublar tidleg eller seinare over same symptom: ikon verkar ved 125%/150%/200% som om dei er uskarpe, flisa eller får ein grå kant. Nett her blir temaet VCL High-DPI-ikoner praktisk: ikkje fordi High-DPI er nytt, men fordi problema oftast viser seg først i kvardagen — på terminalserverar, ved docking- og undocking av bærbar eller så snart ulike DPI per skjerm kjem inn i biletet.

Kjernen er nesten aldri at ein PNG er øydelagd, men pipelinen: kvar kjem ikonet frå (ressurs, fil, SVG, font), i kva oppløysing blir det levert, korleis endar det i TImageList og kven skalerer når på kva måte. I VCL kjem dessutan fleire omgrep saman som må skiljast: DPI-Awareness (om Windows skalerer appen eller appen skalerer seg sjølv), Per-Monitor-DPI (kvar skjerm kan vere ulik) og ImageList-strategi (ha fleire oppløysingar tilgjengelege eller rasterisere ved køyring).

I dette innlegget handlar det medvite ikkje om UI-design-debattar, men om ein rein, driftssikker tilnærming: skalere ikon ved køyring, men slik at dei ikkje blir pikselmos, at alpha-kanalar held seg intakte og at DPI-bytte fungerer utan flimring eller feil bileteoppløysingar. I tillegg kjem fallgruver, feilsøkingspeik og ei ærleg vurdering av når ekstra innsats lønner seg.

Kvifor pikselmjøl oppstår: forstå skaleringskjedja i VCL

Grafik zur Icon-Skalierung: Master-Icon wird in mehrere Zielgrf6dfen gerastert, doppelte Skalierung ffchrt zu Unsche4rfe
Ei enkel skalering frå ein master-kjelde er kontrollerbar — dobbel resampling fører raskt til synleg uskarpheit.

Den vanlegaste årsaka til uskarpe ikon er ei ein gongs ned-/oppskalering til feil tidspunkt. Klassisk flyt i legacy-VCL:

  • Applikasjonen leverer ikon berre i 16×16 eller 24×24.
  • Windows eller VCL skalerer til 20×20 / 32×32 / 48×48.
  • Skaleringa brukar ein interpolasjon som er grei for foto, men som viskar ut kantane i pixelgrafikk.
  • I tillegg blir transparens (Alpha) pressa inn i ei maskelogikk eller konvertert fleire gonger.

Særleg uheldig blir det når fleire skaleringar skjer etter kvarandre: til dømes når ImageList allereie leverer eit skalert bitmap, og Windows på grunn av DPI-unaware eller system-DPI skalerer over att. Resultat: dobbel utglatting.

Eit anna, ofte undervurdert punkt i prosjekt er skaleringstidspunktet. Ved Per-Monitor-DPI (altså PMv2, altså Per-Monitor-DPI-Awareness v2) kan den effektive DPI endre seg når eit vindauge flyttar til ein annan skjerm eller når ein Remote-Desktop-klient justerer DPI dynamisk. Dersom ei TImageList eller ein cache ikkje blir bygd opp på nytt korrekt, ser ein plutseleg ikon i feil storleik eller med feil raster.

TImageList under High-DPI: typische Fallen in echten Anwendungen

TImageList er historisk meint for små bitmapar, med faste dimensjonar, indeksar og relativt stiv lagringslogikk. Under High-DPI oppstår det praktiske fallgruver:

1) Fastkopla Width/Height

Mange VCL-skjema set ImageList.Width/Height i design-tid og let det liggje. Ved 150% vil Windows t.d. heller gjere 16×16 om til 24×24. Dersom lista blir verande på 16×16, blir bileta anten klipte eller skalerte andre stader — begge delar er uheldige.

2) PNG-alpha og maske-logikk

Avhengig av Delphi-versjon og VCL-kontroller endar ein fort i eit hybridoppsett: PNG-ar med alpha blir internt til dels halde som 32-bit bitmap, til dels som Mask+Color. Så snart du konverterer fleire gonger (PNG -> Bitmap -> ImageList -> Draw), oppstår grå halos eller harde kantar. Effekten er ofte bakgrunnssensitiv: På ein mørk verktøylinje ser det verre ut enn på eit lyst panel.

3) DPI-bytte i køyringstid: cache, handles, OwnerDraw

Nokre kontroller cache-ar bilete eller overtek ImageList-handles på eit tidspunkt der DPI-en ikkje er endeleg. Særleg for verktøylinjer, TreeViews/ListViews og OwnerDraw-scenario ser ein etter DPI-bytte sporadisk feil bileteformat eller tomme ikon, inntil eit Repaint eller ein RecreateWnd skjer.

4) Terminalserver og Remote-Desktop som realitetstest

Dersom applikasjonen blir brukt over RDP, er DPI-bytte og session-reconnects vanlege. Det er nett der ein urobust ImageList-strategi svikter: Brukaren ser etter reconnect utoverflata eller feilskala verktøylinjer, sjølv om alt var OK lokalt.

Ryddig tilnærming: tilby fleire oppløysingar i staden for brutalt oppskalering

Den viktigaste avgjerda er konseptuell: Vil du skalere ikon i køyringstid frå ei einskild basisgrafikk (t.d. 16×16 -> 32×32), eller tilbyr du fleire native oppløysingar og vel etter DPI?

I praksis vinn nesten alltid fleire oppløysingar. Oppskalering kan nyttast når kjelda er vektorbassert (SVG, Icon-Font) eller når du verkeleg treng moderate faktorar. Når du sterkoppskalerer frå eit lite rasterbilete, mistar du kantkvalitet, og det ser ein umiddelbart på moderne skjermar.

I VCL-verda er to byggjelement relevante for denne tilnærminga:

  • TImageCollection: behaldar for bilete i fleire storleikar/variantar.
  • TVirtualImageList: genererer derfrå i køyringstid ei ImageList i den aktuell nødvendige storleiken og responderer på DPI-endringar.

Det fjernar ikkje alle problem, men flyttar ansvaret til rett nivå: Du definerer biletkjelder ryddig, og skalering/seleksjon skjer konsekvent.

Skalere VCL High-DPI-ikonar i køyringstid: når det gir meining (og når ikkje)

Det finst legitime grunnar til å skalere ikon i køyringstid:

  • Du lastar ikon dynamisk (t.d. frå ein plugin-mappe, kundetilpassa branding-pakkar, konfigurasjonspakkar).
  • Du vil ha ei einskapleg pipeline for ulike kjelder (ICO, PNG, SVG) og ønskjer ikkje å binde alle variantar ved byggetid.
  • Du genererer ikon programmatisk (status-badges, overlays, samansette symbol).

Køyringstidsskalering gir lite meining når du eigentleg berre har klassiske toolbar-ikon frå eit fast sett. Då er den mest vedlikehaldsvenlege vegen: lever fleire oppløysingar og la VCL velje.

Hvis du brukar kjøretidsskalering, gjer det med klare reglar:

  • Aldri skaler på nytt frå eit allereie skalert bitmap. Gå alltid ut frå ei masterkjelde (ideelt sett vektorbasert eller høgoppløyst).
  • Cache per målstorleik og DPI, elles skalerer du ved kvart Paint på nytt — det kostar CPU og kan gi hakking.
  • Behald alpha: minimér konverteringar, bruk 32-bit RGBA, ikkje rasteriser bakgrunnen.

Pragmatisk arkitektur: Icon-Pipeline som separat komponent

I større applikasjonar løner det seg å ikkje spreie temaet overalt, men byggje ei lita pipeline. Det treng ikkje vere eit rammeverk — snarare eit klart ansvarsområde:

  • Icon-Kjelde: Kor kjem master-asseta frå (ressursar, filer, database, API)?
  • Rasterizer/Scaler: Korleis blir målstorleiken laga frå master (interpolasjon, eventuelt SVG-render)?
  • Cache: Nøkkel (Icon-ID, mål-pikslar, DPI, Theme) og livssyklus (invalidér ved DPI-skift, Theme-skift, pakkeskift).
  • Consumer-Adapter: Korleis kjem resultatet inn i VCL-strukturane (TImageList/TVirtualImageList, OwnerDraw, PaintBox)?

Fordel: Du kan feilsøkje DPI-bugs reproducerbart på éi stad, i staden for å leite i 40 Forms etter „kor blir det skalert igjen“.

DPI-skift korrekt handtert: Hendingar, Rebuild, Repaint

Bærbar med to skjermer med ulik DPI, vindusskift viser ulike ikonstorleikar i ein desktop-app
Per-monitor DPI er realitetstesten: Ved skjermbytte må ikon-pipelinen rasteriserast på nytt, ikkje berre teiknast på nytt.

Under Windows er DPI-skift ein eigen livssyklus. I VCL finst det, avhengig av versjon og DPI-awareness, fleire hendingar/mekanismer, men hovudprinsippet står att:

  • Når DPI-en til vindauget endrar seg, må biletebaserte ressursar som skal vere pikselnøyaktige, bli levert på nytt.
  • Når du fyller ImageLists dynamisk, held ofte ikkje eit enkelt Invalidate — du treng eit Rebuild av bilda i den nye målstorleiken.

Eit praktisk mønster er: Ved DPI-endring (t.d. Form-Scale/monitorbytte) invalidiserer du ikon-cachen for denne DPI-en og byggjer opp dei påverka ImageLists på nytt. Viktig er å ikkje skalere i Paint-hendingar, men gjere det i ein kontrollert oppdateringsblokk (Toolbar.BeginUpdate/EndUpdate, ListView-Redraw av, så på att). Slik unngår du flimmer og halvferdige UI-tilstandar.

Kvifor TImageList så ofte blir uskarp: Interpolasjon, DPI-runding, kanter

Når du først har forstått at det ikkje er DPI i seg sjølv som er problemet, men interpolasjon pluss avrunding, kan mange effektar forklarast:

  • DPI-avrunding: 125% er ikkje ein rein dobling. Frå 16 px blir det 20 px (16 * 1,25). Frå 24 px blir det 30 px. Det gir ujamne tal som gjer pikselkantar vanskelegare.
  • Resampling-filter: Bilinear/Bicubic gjer kantane mjukare. Det er for bilete greitt, for ikon ofte ikkje.
  • Subpikselseffekter: Windows kan, avhengig av rendervegen, nytte eller ikkje nytte subpixel-antialiasing. For ikon ønskjer du kontrollerte kanter — og helst ikkje fleire filtersteg.

Har du raster-ikon, er det i mange team vanleg praksis å levere eigne PNG-ar per målstorleik (16/20/24/32/40/48). Høyrast ut som mykje, men er ofte mindre arbeid enn å år etter år debuggje kvifor det ser rart ut på denne skjermen.

Debugging: Gjer pixelfeilen reproducerbar i staden for å fikse etter magekjensle

Arbeidsplass med debug-notat for ikonskalering og bakgrunnstestar av alpha-kanten
Gode DPI-debugging-rutinar testar storleikar, bakgrunnar og gjenbyggingstidspunkt — ikkje berre første skjermbilete.

High-DPI-feil verkar ofte tilfeldige. Med nokre enkle sjekkar blir dei deterministiske:

1) DPI og ImageList-storleikar ved køyring logge

Logg ved oppstart og ved DPI-endreing: CurrentPPI til forma, Screen.PixelsPerInch (merk: dette kan vere system-DPI), samt ImageList.Width/Height for dei berørte listene. Ser du etter ein monitorendring framleis 16 px, sjølv om du ventar 32, er årsaka klar: gjenbygging manglar eller kjem for seint.

2) Gjere ikon synleg større

Eit raskt testgrep er å setje verktøylinje-ikon midlertidig til 48 px. Dårleg skalering synest då straks. Gode pipeline held seg skarpe også ved 48 px, fordi dei rasteriserer frå ei passande kjelde.

3) Theme- og bakgrunnsbyte teste

Haloar i kantane er ofte Alpha-/Premultiply-problem. Test på lyst/mørkt og på flatar med fargegradients. Sjå kantane forskjellege ut avhengig av bakgrunnen, tyder det på feil i transparenshandsaminga.

4) Remote Desktop / monitorbytte som testskript

Lag eit kort testskript for QA: start app på monitor A (100%), flytt vindauget til monitor B (150%), tilbake, så RDP-reconnect. Er dette stabilt, har du løydd mange kundeproblem.

Migrasjon i eksisterande applikasjonar: Trinnvis i staden for Big Bang

I vaksne Delphi-VCL-applikasjonar sit ikonlogikken ofte mange stadar: menyar, toolbars, ActionLists, TreeViews, statusindikatorar. Ein Big-Bang-ombygging inneber risiko. Eit trinnvis tilnærming har vist seg å fungere:

  • Oppgjer: Kva ImageLists finst? Kva Controls brukar dei? Kva storleikar blir venta?
  • Prioritere: Start med dei mest synlege flata (hovudverktøylinje, navigasjon, kontekstmenyar).
  • Ein førebels kjelde: Sentralsier ikon (ImageCollection eller eigen loader) i staden for å laste enkeltfiler per form.
  • DPI-endreingar teste: Frå og med det første ombygde modulen køyr konsekvente DPI-endreingstestar.

Viktig: Hvis du køyrer både gamal og ny pipeline parallelt, dokumenter klare reglar. Annars oppstår eit blandingslandskap der nokre ikon er skarpe og andre tydeleg verkar uskarpe.

Ytelse og minne: Kjøretidsskaling utan sideverknader

Skalering kostar CPU og minne. I ein forretningsapplikasjon merkar ein det sjeldan i tomgang, men ved å dra eit vindauge over på ein ny skjerm eller ved oppstart med mange Forms kan det hakke. Tre praktiske retningsliner:

  • Begrens cache for grafikk: Ikkje behold kvar mellomstorleik i evig tid. Hvis du berre treng 100% og 150%, cache berre desse.
  • Lazy Build: Rasteriser ikon først når skjermen verkeleg treng dei. Ved store menyar sparar dette starttid.
  • Batch-Rebuild: Ved DPI-skifte, triggar ikkje kvar kontroll kvar for seg. Ein sentral rebuild forhindrar redundant skalering.

Når du arbeider med TVirtualImageList, er mykje av dette allereie tatt med i konseptet, men du må likevel passe på å ikkje byggje inn ein ekstra skaleringslag på toppen.

Fallback-strategiar: Kva gjere når ikkje alle ikonstorleikar føreligg?

I realiteten har du ikkje alltid alle assets i alle storleikar. Då trengst du ei klar fallback-strategi for å unngå tilfeldige resultat:

  • Føretrekk nedskalering: Heller skaler ned frå 64 px til 32 px enn å forstørre frå 16 px til 32 px.
  • Definer nivå: Fastset kva målstorleikar du reelt støttar (t.d. 16/20/24/32/40/48) og kartlegg DPI konsekvent mot desse.
  • Test transparens: Ved fallbacks, ver særleg merksam på alfa-kanalen — det er der haloar oppstår.

Eit typisk feil er å ta den næraste grafikkstorleiken utan reglar. Det fører til variasjon i oppfatta skarheit frå ikon til ikon. Betre er ein streng, dokumentert mapping-plan.

Når lønner arbeidet seg verkeleg?

Det finst tre klare indikatorar på at ei rein High-DPI-ikon-pipeline er verd innsatsen:

  • Brukarane dine nyttar blanding av skjermar (bærbar + ekstern) eller mykje via RDP.
  • Applikasjonen er langlivet og vert vedlikehalden over år — UI-opplevinga er ein del av akseptansen.
  • Du har uansett moderniseringssteg framfor deg (auke DPI-awareness, byte ut kontroller, gjennomarbeide toolbar-layout).

Hvis appen derimot køyrer på eit fast kiosk-system med identisk oppløysing, kan ein halde temaet på eit minimum: lever ei passende ikonstorleik, sett DPI-awareness korrekt, ferdig.

Fazit: High-DPI er ikkje eit kosmetisk detalj, men ei rendering‑avgjerd

Uskarpe ikon i VCL er sjeldan ein isolert feil, men eit symptom på ei ureint kjede av kjelder, skalering og caching. Den mest robuste tilnærminga er å tilby ikon i fleire oppløysingar og levere dei konsekvent via ei sentral pipeline (t.d. ImageCollection/VirtualImageList eller eit eige ikonlag). Kjøretidsskaling gir meining når du har dynamiske kjelder eller samansette symbol, men berre med ei master-kjelde, DPI-basert cache og klare rebuild-reglar.

Hvis du har konkrete symptom (DPI-skifte som øydelegg ikon, haloar i kanten, feil storleikar etter RDP), løner det seg å isolere temaet målretta og behandle det som ein liten arkitekturkomponent i staden for å stable workaround per form. Hvis du treng støtte til debugging eller ei gradvis modernisering, finn du her ein passande inngang: Kontakt zur Net-Base Software GmbH.

For dette temaet er òg Timagelist High Dpi og Delphi Vcl Dpi-Awareness viktige. Artikkelen set desse aspekta på ein forståeleg måte og viser kva som er viktig i det daglege.

Drøft prosjekt eller moderniseringsprosjekt med Net-Base.

neste steg

Når temaet blir eit reelt prosjekt, bør arkitektur, eksisterande system og drift tidleg saman vurderast.

Vi støttar ikkje berre ved enkeltspørsmål, men òg når korte kildekodesnuttar, legacy-tema eller portalidéar skal utviklast til eit robust bedriftsprosjekt.

  • Eksisterande tilstand, målbiletet og tekniske risikoar blir vurderast samla.
  • REST, datatilgang, portalar og utrulling blir ikkje utsett til seinare fasar.
  • De ser tidleg kva veg som er økonomisk og driftsmessig berekraftig.

Del innlegg

Del dette innlegget direkte

LinkedIn, X, XING, Facebook, WhatsApp og e-post er straks tilgjengelege. For Instagram klargjer vi lenke og kort tekst med det same.

E-post

Instagram opnar i ein ny fane. Lenkje og kort tekst blir kopiert til utklippstavla på førehand.