Net-Base Žurnāls

18.08.2026

VCL High-DPI: ikonu skalēšana izpildlaikā un pikseļu izplūduma novēršana TImageList

High-DPI VCL nav tikai atzīmēšanas rūtiņa; tā ir ImageList konfigurācijas, DPI pārslēgšanās notikumu un precīzas renderēšanas ķēde. Šajā praktiskajā rakstā parādīts, kā pārmērot ikonas izpildlaikā, kā novērst artefaktus un kā reproducējami atkļūdot diagnosticēt tipiskas TImageList problēmas.

18.08.2026

No žurnāla tēmas līdz projektu praksei

Atbilstošas pakalpojumu un tehniskās lapas rakstam

Kas VCL lietojumprogrammas izmanto uz moderniem Windows klientiem, agrāk vai vēlāk sastop to pašu simptomu: ikonas pie 125 %/150 %/200 % izskatās kā izplūdušas, izplēstas vai tām parādās pelēka mala. Tieši šeit tēma VCL High-DPI Icons kļūst praktiska: ne tāpēc, ka High-DPI būtu jauns, bet tāpēc, ka problēmas parasti parādās ikdienas darbā — uz Terminalserveriem, pie klēpjdatora dokstacijas maiņas vai tiklīdz katram monitoram ir atšķirīga DPI.

Galvenā problēma gandrīz nekad nav „PNG ir bojāts“, bet gan pipeline: no kurienes nāk ikona (resurss, fails, SVG, fonts), kādā lielumā tā tiek piegādāta, kā tā nonāk TImageList un kurš kad un kā mērogo. VCL kontekstā saplūst vairāki jēdzieni, kurus jānošķir: DPI-Awareness (vai Windows mērogo lietotni vai lietotne mērogo sevi), Per-Monitor-DPI (katram monitoram var būt atšķirīga DPI) un ImageList-Strategie (uzglabāt vairākas izšķirtspējas vai rastrošanas laikā ģenerēt bitkartu).

Šajā rakstā mērķtiecīgi nerunāsim par UI dizaina debatēm, bet par tīru, darbam drošu pieeju: ikonas mērogot izpildlaikā tā, lai tās neveidotos par pikseļu biezeni, lai alfa kanāli saglabātos neskarti un lai DPI maiņas notiktu bez mirgošanas vai nepareiziem attēla izmēriem. Pievienoti slazdi, atkļūdošanas norādes un godīga izvērtēšana, kad papildu darbs atmaksājas.

Kāpēc rodas pikseļu biezenis: VCL mērogošanas ķēdes izpratne

Grafika par ikonu mērogošanu: Master-Icon tiek rastrēts vairākos mērķa izmēros; dubulta mērogošana ātri rada redzamu neskaidrību
Vienreizēja mērogošana no master avota ir kontrolējama — dubulti resampling soļi ātri rada redzamu neskaidrību.

Visbiežākais iemesls, kāpēc ikonas kļūst neskaidras, ir vienreizējs down-/upscaling nepareizā brīdī. Klasisks process legacy‑VCL:

  • Lietojumprogramma piegādā ikonas tikai 16×16 vai 24×24.
  • Windows vai VCL mērogo uz 20×20 / 32×32 / 48×48.
  • Mērogošanas algoritms izmanto interpolāciju, kas fotogrāfijām der, bet pikseļgrafikai izpludina malas.
  • Turklāt caurspīdīgums (alpha) tiek spiests maskas loģikā vai konvertēts vairākas reizes.

Īpaši nepatīkami kļūst, ja notiek vairāki mērogošanas soļi pēc kārtas: piemēram, ja TImageList jau nodrošina skaliētu bitmapu, un Windows sakarā ar DPI‑Unaware vai sistēmas DPI mērogo to vēlreiz. Rezultāts: dubultā izplūdināšana.

Otra, projektos bieži novērtēta pazīme ir mērogošanas laiks. Pie Per‑Monitor‑DPI (vai PMv2, t.i., Per‑Monitor‑DPI‑Awareness v2) efektīvā DPI var mainīties, kad logs pārvietojas uz citu monitoru vai kad Remote‑Desktop klients dinamiski pielāgo DPI. Ja TImageList vai kešs netiek korekti pārbūvēts, pēkšņi redzam ikonas nepareizā izmērā vai ar nepareizu rastru.

TImageList zem High‑DPI: tipiskās lamatas reālās lietojumprogrammās

TImageList vēsturiski ir domāta priekš mazām bitmapām, ar fiksētiem izmēriem, indeksiem un relatīvi stingru atmiņas loģiku. Pie High‑DPI no tā radušās praktiskas lamatas:

1) Stingri piesaistītas Width/Height

Daudzas VCL formas uzstāda ImageList.Width/Height dizaina laikā un to nemaina. Pie 150% lietotājs tomēr, piem., gribēs Windows attēlot no 16 → 24. Ja saraksts paliek uz 16, attēli tiek vai nu apgriezti (clipped), vai skalēti citur — abos gadījumos rezultāts nav labs.

2) PNG‑Alpha un masku loģika

Atkarībā no Delphi-versijas un no VCL kontrolēm jūs ātri nonākat jauktā režīmā: PNG ar alpha kanālu iekšēji tiek turēti daļēji kā 32‑bitu bitmapi, daļēji kā Mask+Color. Tiklīdz veicat vairākkārtīgas konversijas (PNG → Bitmap → ImageList → Draw), parādās pelēkas auras vai cietas malas. Efekts bieži ir atkarīgs no fona: uz tumšas rīkjoslas tas izskatās sliktāk nekā uz gaiša paneļa.

3) DPI maiņa laikā: keši, handles, OwnerDraw

Dažas kontroles kešo attēlu attēlošanu vai pārņem ImageList handles brīdī, kad DPI vēl nav galīgs. Īpaši rīkjoslās, TreeViews/ListViews un OwnerDraw scenārijos pēc DPI maiņām var redzēt sporādiski nepareizas attēlu izmērus vai tukšus ikonattēlus, līdz notiek Repaint vai RecreateWnd.

4) Terminalserver un Remote‑Desktop kā realitātes tests

Ja aplikāciju izmanto pār RDP, DPI maiņas un sesijas atkārtota izveide nav nekas neparasts. Tieši tur vāja ImageList stratēģija parasti izgāžas: pēc reconnect lietotājam var parādīties izplūdušas ikonas vai nepareizi skalētas rīkjoslas, kaut lokāli viss bija kārtībā.

Saudzīgs risinājums: nodrošināt vairākas izšķirtspējas, nevis brutālu upscale

Visnozīmīgākais lēmums ir konceptuāls: vai tu ikonas laikapstākļos mērogo no vienas bāzesgrafikas (piem., 16 → 32), vai nodrošini vairākas nativās izšķirtspējas un izvēlies atbilstošo atkarībā no DPI?

Praksē gandrīz vienmēr uzvar pieeja ar vairākām izšķirtspējām. Upscaling ir pieļaujams, ja avots ir vektorbāzēts (SVG, icon‑font) vai ja nepieciešami tikai mēreni faktori. Ja no mazas rastr‑bildes stipri palielini, zūd malu kvalitāte, un to uz mūsdienu ekrāniem redz uzreiz.

VCL pasaulē šai pieejai šodien būtiski ir divi komponenti:

  • TImageCollection: konteineris attēliem vairākos izmēros/variantos.
  • TVirtualImageList: ģenerē no tā izmaiņas laikā ImageList ar pašreiz nepieciešamo izmēru un reaģē uz DPI izmaiņām.

Tas tev neatrisina visas problēmas, bet novieto atbildību pareizajā līmenī: tu definē attēlu avotus konsekventi, un skalēšana/izvēle notiek vienmērīgi.

VCL High‑DPI ikonu skalēšana laikā: kad tas ir jēdzīgi (un kad ne)

Pastāv pamatotas jēgas, kad ikonas mērogot laikā:

  • Tu ielādē ikonas dinamiski (piem., no plugin‑mapes, klienta specifiskiem branding pakotnēm, konfigurācijas pakām).
  • Tu vēlies vienotu kanālu dažādiem avotiem (ICO, PNG, SVG) un negribi sasaistīt visas variants build‑laikā.
  • Tu ģenerē ikonas programmatiski (statusa žetoni, overlay, kombinētas ikonas).

Nav jēgas izmantot izpildlaika mērogošanu, ja tev faktiski ir tikai klasiskas rīkjoslas ikonas no fiksēta komplekta. Tad uzturēšanas ziņā visvienkāršākais risinājums ir: piegādāt vairākas izšķirtspējas tīri un ļaut VCL izvēlēties.

Ja tu veic izpildlaika mērogošanu, tad ar skaidriem noteikumiem:

  • Nekad neskalot no jau skalēta bitmap attēla. Vienmēr iziet no master-avota (ideāli vektorbāzēts vai augstas izšķirtspējas).
  • Kešot pa mērķizmēru un DPI, citādi tu pārmērosi pie katras pārzīmēšanas — tas patērē CPU un var radīt stostīšanos.
  • Saglabāt alfa: minimizēt konvertācijas, izmantot 32-bit RGBA, fona attēlu nerasterizēt pirms kompozīcijas.

Pragmatiska arhitektūra: ikonu cauruļvads kā atsevišķs komponents

Lielākās lietojumprogrammās ir vērts šo tēmu neizkliedēt pa visu kodu, bet uzbūvēt nelielu cauruļvadu. Tam nav jābūt framework — drīzāk skaidri definētam atbildības blokam:

  • Icon-Quelle: No kurienes nāk master-asseti (resursi, faili, datubāze, API)?
  • Rasterizer/Scaler: Kā no master tiek radīti mērķa izmēri (interpolācija, iesp. SVG-renderēšana)?
  • Cache: Atslēga (Icon-ID, mērķa pikseļi, DPI, tēma) un dzīves cikls (invalidēt pie DPI maiņas, tēmas maiņas, pakotnes maiņas).
  • Consumer-Adapter: Kā rezultāts nonāk VCL-struktūrās (TImageList/TVirtualImageList, OwnerDraw, PaintBox)?

Priekšrocība: tu vari DPI kļūdas reproducējamā vietā atkļūdot, nevis meklēt pa 40 formām, kur vēlreiz tiek mērogots.

DPI maiņu pareiza apstrāde: notikumi, rekonstrukcija, pārzīmēšana

Notebook mit zwei Monitoren unterschiedlicher DPI, Fensterwechsel zeigt unterschiedliche Icon-Grf6dfen in einer Desktop-App
Per-monitor-DPI ir realitātes tests: pie monitora maiņas ikonu cauruļvadam jāveic jauna rasterizācija, nevis tikai pārzīmēšana.

Pie Windows ir definēts, ka DPI maiņas ir atsevišķs dzīves cikls. VCL atkarībā no versijas un DPI-awareness piedāvā vairākus notikumus/mehanismus, taču pamata princips nemainās:

  • Ja loga DPI mainās, attēla bāzētie resursi, kuriem jābūt pikseļprecīziem, ir jānodrošina no jauna.
  • Ja tu dinamiskā veidā aizpildi ImageList, vienkāršs Invalidate bieži vien nepietiek — nepieciešams Rebuild attēliem jaunajā mērķizšķirtspējā.

Praxē lietojams modelis: pie DPI izmaiņas (piem., Form-Scale/monitora maiņa) tu invalidē ikonu kešu šai DPI un pārveido skartās ImageList. Svarīgi ne mērogot Paint-notikumos, bet darīt to kontrolētā atjauninājuma blokā (Toolbar.BeginUpdate/EndUpdate, ListView-Redraw izslēgts, pēc tam ieslēgts). Tā izvairies no mirgošanas un nepilnīgiem UI stāvokļiem.

Kāpēc TImageList bieži kļūst neskaidra: interpolācija, DPI noapaļošana, malas

Kad saproti, ka problēma nav DPI kā tāds, bet interpolācija plus noapaļošana, daudzas parādības var izskaidrot:

  • DPI-noapaļošana: 125% nav tīrs dubultotājs. No 16 px sanāk 20 px (16 * 1,25). No 24 px sanāk 30 px. Tās ir nepāra vērtības, kas sarežģī pikseļu malas.
  • Resampling-filtres: bilineārs/bikubisks padara malas mīkstākas. Tas fotoattēliem ir pieņemami, ikonām bieži nav.
  • Subpikseļu efekti: Windows var atkarībā no renderēšanas ceļa izmantot vai neizmantot subpikseļu antialiasingu. Pie ikonām vēlies kontrolētas malas un pēc iespējas bez vairākkārtējām filtrēšanas pakāpēm.

Ja tev ir rastra ikonas, daudzās komandās par ierastu praksi kļūst piegādāt atsevišķus PNG katrai mērķa izmēram (16/20/24/32/40/48). Skaidās daudz, bet bieži prasa mazāku darbu nekā gadiem ilgi debugot, kāpēc uz konkrētā monitora tas izskatās dīvaini.

Debugēšana: padarīt pikseļu putru reproducējamu, nevis labot pēc vēlmjdoma

Arbeitsplatz mit Debug-Notizen für Icon-Skalierung und Hintergrundtests zur Alpha-Kante
Labas DPI-debugēšanas rutīnas testē izmērus, fonus un rebuild-laikus — ne tikai pirmo ekrānuzņēmumu.

High‑DPI kļūdas bieži izskatās nejaušas. Ar dažām pārbaudēm tās kļūst deterministiskas:

1) Reālā laikā logot DPI un ImageList izmērus

Reģistrē palaides un DPI maiņas brīdī: formas CurrentPPI, Screen.PixelsPerInch (uzmanību — tas var būt sistēmas DPI), kā arī skarto sarakstu ImageList.Width/Height. Ja pēc monitora maiņas joprojām redzi 16, lai gan gaidīji 32, iemesls ir skaidrs: trūkst rebuild vai tas notiek par vēlu.

2) Ikonas redzami palielināt

Ātrs tests ir uz laiku iestatīt rīkjoslas ikonas uz 48 px. Slikta skalēšana uzreiz kritīs acīs. Labas darbnīcas paliek asas arī pie 48 px, jo tās rastro no atbilstoša avota.

3) Tēmas un fona maiņas pārbaudīt

Halos malās bieži ir alpha/premultiply problēmas. Testē gaišā/tumšā režīmā un uz laukumiem ar krāsu pārejām. Ja mala atšķiras atkarībā no fona, caurspīdīguma apstrāde nav pareiza.

4) Remote Desktop / monitora maiņa kā testskripts

Sagatavo īsu QA testskriptu: palaid lietotni uz monitora A (100%), pārnes logu uz monitoru B (150%), atgriezies, tad veic RDP reconnect. Ja tas ir stabils, daudzas klientu problēmas jau būs atrisinātas.

Migrācija esošās lietotnēs: pakāpeniski, ne Big Bang

Audzis Delphi‑VCL lietotnēs ikonu loģika bieži izvietota daudzviet: izvēlnēs, rīkjoslās, ActionLists, TreeViews, statusa indikatoros. Liels vienā rāvienā pārtaisījums palielina riskus. Pārbaudīta pieeja ir pakāpeniska:

  • Inventarizācija: kādas ImageList pastāv? Kuri kontroļi tās izmanto? Kādi izmēri tiek sagaidīti?
  • Prioritizācija: vispirms redzamākās vietas (galvenā rīkjosla, navigācija, konteksta izvēlnes).
  • Vienota avota: centralizēt ikonas (ImageCollection vai savs loader), nevis katrai formai atsevišķi ielādēt failus.
  • DPI maiņu testēšana: no pirmā pārveidotā moduļa konsekventi veikt DPI maiņu testus.

Svarīgi: ja tu paralēli uzturi veco un jauno pipeline, dokumentē skaidras noteikšanas. Citādi rodas jaukta ainava, kur dažas ikonas ir asas, bet citas redzami neskaidras.

Veiktspēja un atmiņa: izpildlaika mērogošana bez blakusparādībām

Mērogošana maksā CPU un atmiņu. Biznesa programmatūrā to reti pamanīs tukšgaitā, bet, pārvietojot logu uz jaunu monitoru vai startējot ar daudziem formām, var rasties raustīšanās. Trīs praktiskas vadlīnijas:

  • Cache-izmērus ierobežot: Neuzglabā katru starpsoļu versiju mūžīgi. Ja nepieciešamas tikai 100% un 150%, kešo tikai tās.
  • Lazy Build: Ikonas rastro tikai tad, kad ekrāns tās tiešām prasa. Lielos izvēlnēs tas ietaupa starta laiku.
  • Batch-Rebuild: DPI maiņā neaktivizē katru kontrols atsevišķi. Centrāls rebuild novērš lieku mērogošanu.

Ja tu strādā ar TVirtualImageList, daudzas no šīm idejām jau ir konceptā iekļautas, bet tev tomēr jāuzmanās, lai nepievienotu papildus savu mērogošanas slāni virsū.

Fallback-Strategien: Was tun, wenn nicht alle Icon-Größen vorliegen?

Realitātē tev ne vienmēr ir visi assets visos izmēros. Tad vajag skaidru fallback stratēģiju, lai izvairītos no nejaušiem rezultātiem:

  • Prefer Downscale: Labāk samazināt no 64 px uz 32 px nekā palielināt no 16 px uz 32 px.
  • Definiere Stufen: Nosaki, kurus mērķa izmērus tu patiešām atbalsti (piem., 16/20/24/32/40/48) un kartē DPI uz tiem konsekventi.
  • Transparenz testen: Fallback gadījumos īpaši pievērs uzmanību alfa-kanālam — tieši tur parasti rodas halos.

Tipiska kļūda ir vienkārši paņemt nākamo pieejamo izmēru. Tas maina uztveramo asumu atkarībā no ikonas. Labāk ir stingrs, dokumentēts mapping plāns.

Wann lohnt sich der Aufwand wirklich?

Ir trīs skaidri indikatori, ka tīra High-DPI-ikonu pipeline atmaksājas:

  • Tavi lietotāji strādā ar jauktu monitoru konfigurāciju (portatīvais + ārējais) vai bieži izmanto RDP.
  • Lietojumprogramma ir ilgmūžīga un tiks uzturēta gadiem; UI uztvere ir daļa no pieņemšanas.
  • Tev jau plānoti modernizācijas soļi (DPI-Awareness paaugstināšana, Controls nomaiņa, toolbar izkārtojuma pārstrāde).

Ja lietotne tiek darbināta tikai uz fiksētas kioska sistēmas ar identisku izšķirtspēju, tēmu var turēt minimālu: piegādā vienu atbilstošu ikonu izmēru, pareizi iestati DPI-Awareness un tas ir pietiekami.

Fazit: High-DPI ist kein kosmetisches Detail, sondern eine Rendering-Entscheidung

Neskaidras ikonas VCL retāk ir izolēta kļūda, drīzāk tās norāda uz nekārtīgu ķēdi no avotiem, mērogošanas un kešošanas. Robusta pieeja ir nodrošināt ikonas vairākos izmēros un piegādāt tās konsekventi caur centrālu pipeline (piem., ImageCollection/VirtualImageList vai paša izveidota ikonu slāņa). Izpildlaika mērogošana ir pamatota, ja tev ir dinamiski avoti vai sastāvējušas ikonas, taču tikai tad, ja ir Master-avots, DPI-bāzēts kešs un skaidras rebuild noteikšanas.

Ja tev ir konkrētas pazīmes (DPI maiņa bojā ikonas, halos pie malām, nepareizi izmēri pēc RDP), ir vērts šo tēmu izolēt un risināt kā nelielu arhitektūras komponenti, nevis krāt workaroundus pa formām. Ja vajadzīga atbalsta debugging vai pakāpeniskā modernizācijā, atradīsi šeit atbilstošu sākumu: Kontakt zur Net-Base Software GmbH.

Šajā tēmā būtiski ir arī Timagelist High Dpi un Delphi Vcl Dpi-Awareness. Raksts šos aspektus saprotami kontekstualizē un parāda, uz ko ikdienā jāpievērš uzmanība.

Apspriest projektu vai modernizācijas ieceri ar Net-Base.

Nākamais solis

Ja no tēmas rodas reāls projekts, arhitektūru, esošo sistēmu un ekspluatāciju jāvērtē kopā jau agrīnā posmā.

Mēs atbalstām ne tikai atsevišķu jautājumu risināšanā, bet arī tad, kad no avota koda fragmentiem, mantojuma sistēmu jautājumiem vai portāla idejām jāizveido stabils uzņēmuma līmeņa projekts.

  • Esošais stāvoklis, mērķa stāvoklis un tehniskie riski tiek kopīgi vērtēti.
  • REST, datu piekļuve, portāli un Rollout netiek pārcelti uz vēlākām fāzēm.
  • Jūs laikus redzat, kurš risinājums ir ekonomiski un darbības ziņā dzīvotspējīgs.

Kopīgot ierakstu

Kopīgot šo ierakstu tieši

LinkedIn, X, XING, Facebook, WhatsApp un e-pasts ir nekavējoties pieejami. Instagramam mēs tūlīt sagatavojam saiti un īsu tekstu.

E-pasts

Instagram atveras jaunā cilnē. Saite un īss teksts tiek iepriekš nokopēti starpliktuvē.