Net-Base списание

18.08.2026

VCL High-DPI: Скалирање на икони при извршување и избегнување размазување на пиксели во TImageList

High-DPI во VCL не е само чекбокс, туку низа од ImageList-Setup, настани за промена на DPI и правилно рендерирање. Овој практичен напис покажува како да скалираш икони во време на извршување, да избегнеш артефакти и репродуцибилно да дебагираш типични TImageList-замки.

18.08.2026

Од тема во магазинот до проектна пракса

Соодветни страници за услуги и технички информации поврзани со објавата

Кој управува со VCL-апликации на модерни Windows-клиенти, порано или подоцна наидува на исто симптом: иконите при 125%/150%/200% изгледаат заматени, распуштени или добиваат сив раб. Токму тука пракса станува темата VCL High-DPI Icons: не затоа што High‑DPI е ново, туку затоа што проблемите обично се појавуваат во секојдневна употреба — на терминал-сервери, при приклучување/одклучување на лаптоп од док, или кога е вклучено различно DPI по монитор.

Суштинската тема речиси никогаш не е „PNG-то е расипано“, туку пипата: од каде доаѓа иконата (ресурс, датотека, SVG, фонтови), во која големина се доставува, како завршува во TImageList и кој кога и како ја скалира. Во VCL се собираат неколку поими кои треба да се раздвојат: DPI-Awareness (дали Windows ја скалира апликацијата или апликацијата сама се скалира), Per-Monitor-DPI (секој монитор може да биде различен) и ImageList-Strategie (да се имаат повеќе резолуции или да се прави растеризација во време на работа).

Во овој напис свесно не станува збор за дебати за UI-дизајн, туку за еден чист, оперативно сигурен пристап: да се скалираат иконите во време на работа, но така што да не се претворат во пикселна кашеста маса, да останат интегрални Alpha-каналите и смените на DPI да функционираат без трепкање или погрешни големини на сликата. Плус замките, совети за дебагирање и искрена проценка кога дополнителниот вложувач вреди.

Зошто настанува пикселно заматување: разбирање на ланецот на скалирање во VCL

Grafik zur Icon-Skalierung: Master-Icon wird in mehrere Zielgrf6dfen gerastert, doppelte Skalierung ffchrt zu Unsche4rfe
Еднократно скалирање од мастер-извор е контролирано — двојните ресемплирачки чекори брзо водат до видливо заматување.

Најчестата причина за заматени икони е еднократно down-/upscaling во погрешно време. Класичен тек во legacy‑VCL:

  • Апликацијата доставува икони само во 16×16 или 24×24.
  • Windows или VCL ги скалира до 20×20 / 32×32 / 48×48.
  • Скалирачот користи интерполација која е прифатлива за фотографии, но за пиксел-графика размазува рабови.
  • Дополнително, транспарентноста (alpha) се турка во логика на маски или се конвертира повеќекратно.

Посебно опасно е кога се случуваат повеќе скалирања едно по друго: на пример кога ImageList веќе дава скалирано битмап, а Windows поради DPI‑unaware или системско DPI повторно го скалира. Резултат: двојно размазување.

Втор, во проекти потценет аспект е временската точка на скалирање. При Per‑Monitor‑DPI (PMv2, односно Per‑Monitor‑DPI‑Awareness v2) ефективното DPI може да се промени кога прозорецот го менува мониторот или кога Remote Desktop клиент динамично ја прилагодува DPI вредноста. Ако тогаш TImageList или некој кеш не се изгради правилно повторно, одеднаш ќе се видат икони во погрешна големина или со погрешен растер.

TImageList unter High-DPI: typische Fallen in echten Anwendungen

TImageList историски е наменет за мали битмапи, со фиксни димензии, индекси и релативно строга логика на складирање. Под High-DPI од тоа произлегуваат практични замки:

1) Фиксно зададени Width/Height

Многу VCL-формулари го оставуваат ImageList.Width/Height поставено на време на дизајн и не го менуваат. При 150% на пр. Windows може да сака од 16×16 да направи 24×24. Ако листата остане на 16×16, иконите или ќе се исечат или ќе се скалираат на друго место — и двете решенија се неубави.

2) PNG-Alpha и логика на маски

Во зависност од Delphi-верзијата и VCL-контролите, брзо завршуваш во мешан режим: PNG-ови со alpha понекогаш се чуваат внатрешно како 32-bit Bitmap, а понекогаш како Mask+Color. Штом конвертираш повеќекратно (PNG → Bitmap → ImageList → Draw), се појавуваат сивкави ореоли или остри рабови. Ефектот често зависи од позадината: на темна алатна лента изгледа полошо отколку на светол панел.

3) Промена на DPI во текот на извршување: кешеви, handles, OwnerDraw

Некои контроли кешираат прикажување на слика или преземаат ImageList-handles во момент кога DPI уште не е финален. Особено кај Toolbars, TreeViews/ListViews и OwnerDraw-сценарија, по DPI-промени повремено се гледаат погрешни големини на сликите или празни икони, сè додека не се изврши Repaint или RecreateWnd.

4) Terminalserver и Remote-Desktop како тест во реални услови

Кога апликацијата се користи преку RDP, промени на DPI и session-reconnects не се ретки. Токму таму нерационална ImageList-стратегија може да се покаже: корисникот по reconnect гледа заматени икони или погрешно скалирани ленти со икони, иако локално сè било во ред.

Чист пристап: достави повеќе резолуции наместо грубо зголемување

Најважната одлука е концепциска: дали ќе ги скалираш иконите во текот на извршувањето од единствена основна слика (на пр. 16×16 → 32×32), или ќе понудиш повеќе нативни резолуции и ќе ја избереш соодветната според DPI?

Во пракса речиси секогаш победи пристапот со повеќе резолуции. Upscaling може да има смисла ако изворот е векторски (SVG, Icon-Font) или ако навистина треба само умерен фактор. Штом значително го зголемиш размерот од мала растерска слика, губиш квалитет на рабовите — и тоа веднаш се гледа на модерните дисплеи.

Во VCL-околина за овој пристап денеска релевантни се два компонента:

  • TImageCollection: контејнер за слики во повеќе големини/варијанти.
  • TVirtualImageList: создава од нив при време на извршување ImageList во моментално потребната големина и реагира на DPI-промени.

Ова не ги решава сите проблеми, но го поместува проблемот на вистинското место: јасно ги дефинираш изворите на слики, а скалирањето/селекцијата се изведува конзистентно.

Скалирање на VCL High-DPI икони во текот на извршување: кога има смисла (и кога не)

Постојат валидни причини за скалирање на икони во време на извршување:

  • Ги вчитуваш иконите динамично (на пр. од папка со плагини, кориснички пакети за брендирање, конфигурациски пакети).
  • Сакаш унифицирана пипелина за различни извори (ICO, PNG, SVG) и не сакаш да ги вклучиш сите варијанти во време на build.
  • Ги генерираш иконите програмски (status-badges, overlays, составени символи).

Не е разумно да се користи скалирање во текот на извршување (Laufzeit-Skalierung), ако всушност имаш само класични Toolbar-икони од фиксна поставеност. Тогаш најмалку напорно за одржување решение е: достави неколку резолуции чисто и остави ја VCL да избере.

Ако правиш скалирање во текот на извршување, тогаш со јасни правила:

  • Никогаш не скалирај повторно од веќе скалиран Bitmap. Секогаш полагaj на главен извор (идеално векторски или со висока резолуција).
  • Кеш по целна големина и DPI, инаку ќе скалираш при секој Paint — тоа троши CPU и може да предизвика лаг/задржување.
  • Сочувај Alpha: Минимизирај конверзии, користи 32-bit RGBA, не растеризирај го задниниот слој.

Pragmatische Architektur: Icon-Pipeline als eigener Baustein

Во поголеми апликации има смисла да не го разпрскуваш проблемот насекаде, туку да изградиш мала pipeline. Не мора да е framework — повеќе е јасно дефиниран опсег на одговорност:

  • Icon-Quelle: Од каде доаѓаат master-asset-ите (ресурси, фајлови, база на податоци, API)?
  • Rasterizer/Scaler: Како се создава целната големина од master (интерполација, евентуално SVG-render)?
  • Cache: Клуч (Icon-ID, целни пиксели, DPI, Theme) и животен циклус (invalidieren при промена на DPI, промена на тема, промена на пакет).
  • Consumer-Adapter: Како резултатот доаѓа во VCL-структури (TImageList/TVirtualImageList, OwnerDraw, PaintBox)?

Предност: Можеш DPI-багови да ги репродуцираш и дебагираш на едно место, наместо да бараш низ 40 Forms каде „повторно се скалира“.

DPI-Wechsel korrekt behandeln: Ereignisse, Rebuild, Repaint

Лаптоп со два монитора со различни DPI, прозоречна промена покажува различни големини на иконите во една десктоп-апликација
Per-Monitor-DPI е вистинскиот тест: при промена на мониторот Icon-Pipeline мора повторно да растеризира, не само повторно да црта.

Под Windows промена на DPI е сопствен животен циклус. Во VCL зависно од верзијата и DPI-Awareness има неколку настани/механизми, но основното правило е исто:

  • Ако DPI-то на прозорецот се промени, графичките ресурси кои треба да се пиксел-прецизни мора да се преподготват.
  • Ако динамично пополнуваш ImageLists, едноставното „Invalidate“ често не е доволно — ти треба Rebuild на имџите во новата целна големина.

Практичен образец е: при промена на DPI (на пр. Form-Scale/смена на монитор) инвалидирате кешот за икони за таа DPI и го реизградите погодените ImageLists. Важно е да не скалираш во Paint-настани, туку да го правиш тоа во контролирана update-зона (Toolbar.BeginUpdate/EndUpdate, ListView-Redraw off, па потоа on). На тој начин избегнуваш трепкање и недовршени состојби на UI.

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

Ако еднаш сфатиш дека проблемот не е DPI самото по себе, туку интерполација плус заокружување, многу ефекти може да се објаснат:

  • DPI-округлување: 125a0% ist kein sauberer Verdoppler. Aus 16 px werden 20 px (16 * 1,25). Aus 24 px werden 30 px. Das sind krumme Zahlen, die Pixelkanten erschweren.
  • Филтри за ресемплирање: Bilinear/Bicubic ги омекнуваат рабовите. Тоа е во ред за фотографии, но често не е за икони.
  • Субпиксел ефекти: Windows kann je nach Renderpfad Subpixel-Antialiasing nutzen oder nicht. Bei Icons willst du kontrollierte Kanten und möglichst keine mehrfachen Filterstufen.

Wenn du Raster-Icons hast, ist es in vielen Teams ge4ngige Praxis, pro Zielgrf6dfe eigene PNGs zu liefern (16/20/24/32/40/48). Klingt nach viel, ist aber oft weniger Aufwand als jahrelang bbwarum sieht das auf diesem Monitor komisch ausab zu debuggen.

Debugging: Pixelmatsch reproduzierbar machen statt nach Bauchgeffchl zu fixen

Работно место со белешки за дебагирање за скалирање на икони и тестови на позадина за алфа раб
Добри DPI-рутнини за дебагирање ги тестираат големините, позадините и Rebuild-Zeitpunkte — nicht nur den ersten Screenshot.

High-DPI-Bugs wirken oft zufe4llig. Mit ein paar Checks werden sie deterministisch:

1) Логирај DPI и ImageList-големини zur Laufzeit

Logge bei Start und bei DPI-Wechsel: CurrentPPI des Forms, Screen.PixelsPerInch (Achtung: das kann System-DPI sein), sowie ImageList.Width/Height der betroffenen Listen. Wenn du nach einem Monitorwechsel noch 16d716 siehst, obwohl du 32 erwartest, ist die Ursache klar: Rebuild fehlt oder kommt zu spe4t.

2) Икони — sichtbar vergrf6dfern

Ein schneller Test ist, die Toolbar-Icons tempore4r auf 48 px zu setzen. Schlechte Skalierung springt dann sofort ins Auge. Gute Pipelines bleiben auch bei 48 px scharf, weil sie aus einer passenden Quelle rastern.

3) Theme- und Hintergrundwechsel testen

Halos am Rand sind oft Alpha-/Premultiply-Probleme. Teste auf hell/dunkel und auf Fle4chen mit Farbverlauf. Wenn die Kante je nach Hintergrund anders aussieht, stimmt die Transparenzbehandlung nicht.

4) Remote Desktop / Monitorwechsel als Testskript

Erstelle ein kurzes Testskript für die QS: App starten auf Monitor A (100a0%), Fenster auf Monitor B (150a0%), zurück, dann RDP reconnect. Wenn das stabil ist, sind viele Kundenprobleme bereits erschlagen.

Миграција во постоечки Anwendungen: Schrittweise statt Big Bang

In gewachsenen Delphi-VCL-Anwendungen steckt die Icon-Logik oft an vielen Stellen: Menüs, Toolbars, ActionLists, TreeViews, Statusanzeigen. Ein Big-Bang-Umbau bringt Risiko. Bewährt hat sich ein schrittweises Vorgehen:

  • Инвентар: Welche ImageLists gibt es? Welche Controls nutzen sie? Welche Grf6dfen werden erwartet?
  • Приоритезација: Zuerst die prominentesten Flächen (Haupttoolbar, Navigation, Kontextmenüs).
  • Единствен извор: Icons zentralisieren (ImageCollection oder eigener Loader), statt pro Form Einzeldateien zu laden.
  • DPI-Wechsel testen: Ab dem ersten umgebauten Modul konsequent DPI-Wechsel-Tests fahren.

Важно: Ако паралелно ги користиш старите и новите pipeline-ови, документирај јасни правила. Инаку ќе се создаде мешана средина во која некои икони се остри, а други видливо заматени.

Перформанси и меморија: Скалирање во време на извршување без несакани ефекти

Скалирањето чини CPU и меморија. Во бизнис софтвер тоа ретко се забележува кога е во мирување, но при преместување на прозорец на нов монитор или при старт со многу форми може да дојде до закинување. Три практични водилки:

  • Ограничи големината на кешот: Не чувај секоја промена засекогаш. Ако ти се потребни само 100% и 150%, кеширај само нив.
  • Lazy Build: Икони да се растеризираат само кога екран навистина ги бара. Кај големи менија тоа штеди време на старт.
  • Batch-Rebuild: При промена на DPI не тригерирај секој контрол поединечно. Централен преизградувач спречува редундантно скалирање.

Ако работиш со TVirtualImageList, многу од ова веќе е вградено како концепт, но сепак мора да внимаваш да не додадеш уште едно сопствено слојно скалирање врз тоа.

Fallback-стратегии: Што да се прави ако не ги имаш сите големини на икони?

Во реалноста не секогаш ги имаш сите assets во сите големини. Потребна е јасна fallback-стратегија за да избегнеш случајни резултати:

  • Prefer Downscale: Подобро е да се скалира надолу од 64 px на 32 px отколку да се зголемува од 16 px на 32 px.
  • Definiere Stufen: Определи кои целни големини навистина ги поддржуваш (на пр. 16/20/24/32/40/48) и мапирај ги DPI-ата правилно на нив.
  • Transparenz testen: При fallback-ови посебно внимавај на алфа-прозирноста — токму таму се појавуваат halo-ефекти.

Типична грешка е да се земе „некоја следна“ големина. Тоа предизвикува перципирана варијација на острина во зависност од иконата. Подобро е да имаш цврст, документиран мапинг-план.

Кога навистина се исплати трудот?

Постојат три јасни индикатори дека се исплати да се изгради чист High-DPI-иконски pipeline:

  • Твоите корисници работат со мешани монитори (лаптоп + екстерен) или често преку RDP.
  • Апликацијата е долготрајна и се одржува години — перцепцијата на UI е дел од прифаќањето.
  • Ионака имаш планирани чекори за модернизација (зголемување на DPI-Awareness, замена на контроли, редизајн на Toolbar-лејаутот).

Ако, пак, апликацијата работи само на фиксно киоск-систем со идентична резолуција, темата може да се одржи минимална: достави соодветна иконска големина, постави DPI-Awareness правилно и готово.

Заклучок: High-DPI не е козметички детал, туку одлука за рендерирање

Незаситени/заматени икони во VCL ретко се изолиран проблем; тие укажуваат на неконзистентен ланец од извори, скалирање и кеширање. Најробустен пристап е да се обезбедат икони во неколку резолуции и да се доставуваат конзистентно преку централизирана pipeline (на пр. ImageCollection/VirtualImageList или сопствен слој за икони). Скалирањето во време на извршување е оправдано кога имаш динамички извори или составени симболи, но само со мастер-извор, DPI-базиран кеш и јасни правила за преизградба.

Ако имаш конкретни симптоми (промена на DPI ги оштетува иконите, halo-ефекти по рабовите, погрешни големини по RDP), вреди да го изолираш проблемот и да го третираш како мал архитектонски елемент, наместо да редиш Workarounds по форма. Ако ти треба поддршка при дебагирање или при постапна модернизација, тука ќе најдеш соодветен почеток: Kontakt zur Net-Base Software GmbH.

За оваа тема важни се и Timagelist High Dpi и Delphi Vcl Dpi-Awareness. Статијата ги објаснува овие аспекти разбирливо и покажува што е пресудно во секојдневната работа.

Разговарајте за проект или план за модернизација со Net-Base.

Следен чекор

Кога од темата ќе стане реален проект, архитектурата, постојниот систем и експлоатацијата треба рано да се разгледаат заедно.

Не поддржуваме само при поединечни прашања, туку и кога од исечоци од изворен код, legacy-теми или идеи за портали треба да прерасне во робустен корпоративен проект.

  • Постоечката состојба, целната слика и техничките ризици се проценуваат заедно.
  • REST, пристапот до податоци, порталите и Rollout не се одложуваат за подоцнежна фаза.
  • Ќе увидите рано кој пат е економски и оперативно одржлив.

Сподели објава

Споделете го овој пост директно.

LinkedIn, X, XING, Facebook, WhatsApp и е-пошта се достапни веднаш. За Instagram подготвуваме линк и краток текст.

Е-пошта

Instagram се отвора во нов таб. Линкот и краткиот текст претходно се копираат во меѓуспремникот.