Tworzenie aplikacji klasycznych o wysokiej rozdzielczości DPI w systemie Windows
Ta zawartość jest przeznaczona dla deweloperów, którzy chcą zaktualizować aplikacje klasyczne do obsługi współczynnika skalowania wyświetlania (kropek na cal lub DPI) zmiany dynamicznie, dzięki czemu aplikacje mogą być ostre na każdym ekranie, na którym są renderowane.
Aby rozpocząć, jeśli tworzysz nową aplikację systemu Windows od podstaw, zdecydowanie zaleca się utworzenie aplikacji platformy uniwersalnej systemu Windows (UWP). Aplikacje platformy UNIWERSALNEJ systemu Windows są automatycznie i dynamicznie skalowane dla każdego wyświetlacza, na którym są uruchomione.
Aplikacje klasyczne korzystające ze starszych technologii programowania systemu Windows (nieprzetworzone programowanie Win32, Windows Forms, Windows Presentation Framework (WPF) itp.) nie mogą automatycznie obsługiwać skalowania DPI bez dodatkowej pracy dewelopera. Bez takiej pracy aplikacje będą pojawiać się rozmyte lub niepoprawnie rozmiary w wielu typowych scenariuszach użycia. Ten dokument zawiera kontekst i informacje o tym, co jest związane z aktualizowaniem aplikacji klasycznej w celu poprawnego renderowania.
Wyświetlanie współczynnika skalowania & DPI
W miarę postępu technologii wyświetlania producenci paneli wyświetlania spakowali coraz większą liczbę pikseli do każdej jednostki przestrzeni fizycznej na swoich panelach. Spowodowało to, że kropki na cal (DPI) nowoczesnych paneli wyświetlania są znacznie wyższe niż historycznie. W przeszłości większość wyświetlaczy miała 96 pikseli na cal liniowy miejsca fizycznego (96 DPI); w 2017 r. wyświetlacze z prawie 300 DPI lub wyższym są łatwo dostępne.
Większość starszych platform interfejsu użytkownika pulpitu ma wbudowane założenia, że wyświetlanie dpi nie zmieni się w okresie istnienia procesu. To założenie nie jest już prawdziwe, a wyświetlanie interfejsów DPI często zmienia się kilka razy w całym okresie istnienia procesu aplikacji. Niektóre typowe scenariusze, w których współczynnik skalowania wyświetlania/zmiany DPI są następujące:
- Konfiguracje wielu monitorów, w których każdy ekran ma inny współczynnik skalowania, a aplikacja jest przenoszona z jednego ekranu do innego (na przykład wyświetlacz 4K i 1080p)
- Zadokowanie i oddokowanie laptopa o wysokiej rozdzielczości DPI z wyświetlaczem zewnętrznym o niskiej rozdzielczości DPI (lub odwrotnie)
- Nawiązywanie połączenia za pośrednictwem pulpitu zdalnego z laptopa/tabletu DPI z urządzeniem o niskiej rozdzielczości DPI (lub odwrotnie)
- Zmiana ustawień współczynnika skali wyświetlania podczas uruchamiania aplikacji
W tych scenariuszach aplikacje platformy UNIWERSALNEJ systemu Windows automatycznie ponownie rysują się dla nowej rozdzielczości DPI. Domyślnie i bez dodatkowej pracy dewelopera aplikacje klasyczne nie. Aplikacje klasyczne, które nie wykonują tej dodatkowej pracy w celu reagowania na zmiany DPI, mogą pojawić się rozmyte lub niepoprawnie dopasowane do użytkownika.
Tryb rozpoznawania DPI
Aplikacje klasyczne muszą poinformować system Windows, czy obsługują skalowanie DPI. Domyślnie system uwzględnia aplikacje klasyczne DPI nieświadome i mapy bitowe rozciągają okna. Ustawiając jeden z następujących dostępnych trybów rozpoznawania dpi, aplikacje mogą jawnie poinformować system Windows, jak chcą obsługiwać skalowanie DPI:
Nieuważne dpi
Aplikacje nieświadome DPI są renderowane przy stałej wartości DPI 96 (100%). Za każdym razem, gdy te aplikacje są uruchamiane na ekranie ze skalą wyświetlania większą niż 96 DPI, system Windows rozciągnie mapę bitową aplikacji do oczekiwanego rozmiaru fizycznego. Spowoduje to pojawienie się rozmytej aplikacji.
Rozpoznawanie dpi systemu
Aplikacje klasyczne obsługujące dpi systemu zwykle otrzymują dpi podstawowego połączonego monitora od czasu logowania użytkownika. Podczas inicjowania odpowiednio ułożyją interfejs użytkownika (kontrolki ustalania rozmiaru, wybierania rozmiarów czcionek, ładowania zasobów itp.) przy użyciu tej wartości dpi systemu. W związku z tym systemowe aplikacje obsługujące dpi nie są skalowane dpi (mapa bitowa rozciągnięta) przez system Windows na potrzeby renderowania w tym pojedynczym dpi. Gdy aplikacja zostanie przeniesiona do ekranu z innym współczynnikiem skalowania lub jeśli współczynnik skalowania wyświetlania ulegnie zmianie, system Windows przeskaluje okna aplikacji, co spowoduje ich rozmycie. W rzeczywistości aplikacje klasyczne z obsługą dpi systemu renderowane są wyraźnie tylko w jednym współczynniku skalowania ekranu, co staje się rozmyte za każdym razem, gdy zmienia się dpi.
rozpoznawanie dpi Per-Monitor i Per-Monitor (wersja 2)
Zaleca się zaktualizowanie aplikacji klasycznych w celu korzystania z trybu rozpoznawania dpi na monitorze, co pozwala na natychmiastowe renderowanie ich za każdym razem, gdy zmienia się dpi. Gdy aplikacja zgłasza systemOwi Windows, że chce działać w tym trybie, system Windows nie rozciągnie aplikacji po zmianie dpi, zamiast tego wysyła WM_DPICHANGED do okna aplikacji. Następnie pełną odpowiedzialność aplikacji za obsługę zmiany rozmiaru nowej rozdzielczości DPI. Większość struktur interfejsu użytkownika używanych przez aplikacje klasyczne (typowe kontrolki systemu Windows (comctl32), Windows Forms, Windows Presentation Framework itp.) nie obsługują automatycznego skalowania DPI, co wymaga od deweloperów zmiany rozmiaru i położenia zawartości okien.
Istnieją dwie wersje Per-Monitor świadomość, że aplikacja może zarejestrować się jako: wersja 1 i wersja 2 (PMv2). Zarejestrowanie procesu jako uruchomionego w trybie rozpoznawania PMv2 powoduje:
- Aplikacja jest powiadamiana o zmianie dpi (zarówno najwyższego poziomu, jak i podrzędnych identyfikatorów HWND)
- Aplikacja wyświetla nieprzetworzone piksele każdego wyświetlacza
- Aplikacja nigdy nie jest mapowana bitową skalowaną przez system Windows
- Automatyczny obszar niekliencki (podpis okna, paski przewijania itp.) Skalowanie DPI według systemu Windows
- Okna dialogowe Win32 (z CreateDialog) automatycznie skalowane przez system Windows
- Zasoby map bitowych narysowanych motywami w typowych kontrolkach (pola wyboru, tło przycisków itp.) są automatycznie renderowane przy odpowiednim współczynniku skalowania DPI
W przypadku uruchamiania w trybie rozpoznawania Per-Monitor w wersji 2 aplikacje są powiadamiane o zmianie dpi. Jeśli aplikacja nie zmienia rozmiaru dla nowego dpi, interfejs użytkownika aplikacji będzie wyświetlany za mały lub zbyt duży (w zależności od różnicy w poprzednich i nowych wartościach DPI).
Nuta
Per-Monitor świadomość wersji 1 (PMv1) jest bardzo ograniczona. Zaleca się, aby aplikacje używały protokołu PMv2.
W poniższej tabeli przedstawiono sposób renderowania aplikacji w różnych scenariuszach:
Tryb rozpoznawania DPI | Wprowadzono wersję systemu Windows | Widok DPI aplikacji | Zachowanie zmiany DPI |
---|---|---|---|
Nieświadomy | N/A | Wszystkie wyświetlane ekrany to 96 DPI | Rozciągnięcie mapy bitowej (rozmyte) |
System | Widok | Wszystkie wyświetlane ekrany mają tę samą wartość DPI (DPI podstawowego ekranu w momencie uruchomienia bieżącej sesji użytkownika) | Rozciągnięcie mapy bitowej (rozmyte) |
Per-Monitor | 8.1 | DPI ekranu, na który znajduje się przede wszystkim okno aplikacji |
|
Per-Monitor V2 | Windows 10 Creators Update (1703) | DPI ekranu, na który znajduje się przede wszystkim okno aplikacji |
automatyczne skalowanie DPI:
|
Rozpoznawanie dpi na monitor (wersja 1)
Per-Monitor tryb rozpoznawania dpi (PMv1) został wprowadzony w systemie Windows 8.1. Ten tryb rozpoznawania DPI jest bardzo ograniczony i oferuje tylko funkcje wymienione poniżej. Zaleca się, aby aplikacje klasyczne używały trybu rozpoznawania Per-Monitor w wersji 2 obsługiwanego w systemie Windows 10 1703 lub nowszym.
Początkowa obsługa rozpoznawania monitora oferowała tylko następujące aplikacje:
- Rekordy HWND najwyższego poziomu są powiadamiane o zmianie DPI i pod warunkiem nowego sugerowanego rozmiaru
- System Windows nie będzie map bitowych rozciągnąć interfejs użytkownika aplikacji
- Aplikacja widzi wszystkie wyświetlane w pikselach fizycznych (zobacz wirtualizacja)
W systemie Windows 10 1607 lub nowszym aplikacje PMv1 mogą również wywoływać EnableNonClientDpiScaling podczas WM_NCCREATE, aby zażądać, aby system Windows prawidłowo skalował obszar niekliencki okna.
Obsługa skalowania DPI na monitorze według struktury interfejsu użytkownika/technologii
W poniższej tabeli przedstawiono poziom obsługi rozpoznawania dpi na monitor oferowany przez różne struktury interfejsu użytkownika systemu Windows od systemu Windows 10 1703:
Struktura/technologia | Wsparcie | Wersja systemu operacyjnego | Skalowanie DPI obsługiwane przez | Linki zewnętrzne |
---|---|---|---|---|
Platforma uniwersalna systemu Windows (UWP) | Pełny | 1607 | Struktura interfejsu użytkownika | platformy uniwersalnej systemu Windows (UWP) |
Nieprzetworzone kontrolki Win32/Common Controls V6 (comctl32.dll) |
|
1703 | Aplikacja | przykładowe usługi GitHub |
Formularze systemu Windows | Ograniczone automatyczne skalowanie DPI na monitor dla niektórych kontrolek | 1703 | Struktura interfejsu użytkownika | obsługa wysokiej rozdzielczości DPI w formularzy systemu Windows |
Windows Presentation Framework (WPF) | Natywne aplikacje WPF będą skalować dpi WPF hostowane w innych strukturach i innych platformach hostowanych w WPF nie są automatycznie skalowane | 1607 | Struktura interfejsu użytkownika | przykładowe usługi GitHub |
GDI | Żaden | N/A | Aplikacja | Zobacz GDI High-DPI Skalowanie |
GDI+ | Żaden | N/A | Aplikacja | Zobacz GDI High-DPI Skalowanie |
MFC | Żaden | N/A | Aplikacja | N/A |
Aktualizowanie istniejących aplikacji
Aby zaktualizować istniejącą aplikację klasyczną w celu prawidłowego obsługi skalowania DPI, należy ją zaktualizować w taki sposób, aby co najmniej ważne części interfejsu użytkownika były aktualizowane w celu reagowania na zmiany DPI.
Większość aplikacji klasycznych działa w trybie rozpoznawania dpi systemu. Aplikacje obsługujące dpi systemu zwykle są skalowane do dpi wyświetlacza podstawowego (wyświetlacz, na który znajdował się taca systemowa w momencie uruchomienia sesji systemu Windows). Po zmianie dpi system Windows rozciągnie interfejs użytkownika tych aplikacji, co często skutkuje rozmyciem. Podczas aktualizowania aplikacji obsługującej dpi systemu w celu uzyskania obsługi dpi na monitorze kod obsługujący układ interfejsu użytkownika musi zostać zaktualizowany tak, aby był wykonywany nie tylko podczas inicjowania aplikacji, ale także za każdym razem, gdy zostanie odebrane powiadomienie o zmianie DPI (WM_DPICHANGED w przypadku win32). Zwykle obejmuje to ponowne zaplanowanie wszelkich założeń w kodzie, które interfejs użytkownika musi być skalowany tylko raz.
Ponadto w przypadku programowania Win32 wiele interfejsów API Win32 nie ma żadnego dpi ani kontekstu wyświetlania, więc będą zwracać tylko wartości względem rozdzielczości DPI systemu. Przydatne może być grep za pośrednictwem kodu, aby wyszukać niektóre z tych interfejsów API i zastąpić je wariantami obsługującymi dpi. Niektóre typowe interfejsy API z wariantami obsługującymi dpi są następujące:
Pojedyncza wersja DPI | wersja Per-Monitor |
---|---|
GetSystemMetrics | GetSystemMetricsForDpi |
Dostosuj WindowRectEx | Dostosuj WindowRectExForDpi |
SystemParametersInfo | SystemParametersInfoForDpi |
GetDpiForMonitor | GetDpiForWindow |
Dobrym pomysłem jest również wyszukanie zakodowanych na stałe rozmiarów w bazie kodu, które zakładają stałą dpi, zastępując je kodem, który poprawnie odpowiada na skalowanie DPI. Poniżej przedstawiono przykład, który zawiera wszystkie te sugestie:
Przykład:
W poniższym przykładzie przedstawiono uproszczony przypadek Win32 tworzenia podrzędnego HWND. Wywołanie metody CreateWindow zakłada, że aplikacja działa przy rozdzielczości 96 DPI (USER_DEFAULT_SCREEN_DPI
stałej), a rozmiar przycisku ani pozycja nie będą poprawne w wyższych interfejsach DPI:
case WM_CREATE:
{
// Add a button
HWND hWndChild = CreateWindow(L"BUTTON", L"Click Me",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
50,
50,
100,
50,
hWnd, (HMENU)NULL, NULL, NULL);
}
Zaktualizowany kod poniżej pokazuje:
- Kod tworzenia okna DPI skalowanie położenia i rozmiaru podrzędnego HWND dla DPI okna nadrzędnego
- Reagowanie na zmianę DPI przez zmianę położenia i zmiany rozmiaru podrzędnego HWND
- Trwale zakodowane rozmiary zostały usunięte i zastąpione kodem, który reaguje na zmiany DPI
#define INITIALX_96DPI 50
#define INITIALY_96DPI 50
#define INITIALWIDTH_96DPI 100
#define INITIALHEIGHT_96DPI 50
// DPI scale the position and size of the button control
void UpdateButtonLayoutForDpi(HWND hWnd)
{
int iDpi = GetDpiForWindow(hWnd);
int dpiScaledX = MulDiv(INITIALX_96DPI, iDpi, USER_DEFAULT_SCREEN_DPI);
int dpiScaledY = MulDiv(INITIALY_96DPI, iDpi, USER_DEFAULT_SCREEN_DPI);
int dpiScaledWidth = MulDiv(INITIALWIDTH_96DPI, iDpi, USER_DEFAULT_SCREEN_DPI);
int dpiScaledHeight = MulDiv(INITIALHEIGHT_96DPI, iDpi, USER_DEFAULT_SCREEN_DPI);
SetWindowPos(hWnd, hWnd, dpiScaledX, dpiScaledY, dpiScaledWidth, dpiScaledHeight, SWP_NOZORDER | SWP_NOACTIVATE);
}
...
case WM_CREATE:
{
// Add a button
HWND hWndChild = CreateWindow(L"BUTTON", L"Click Me",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
0,
0,
0,
0,
hWnd, (HMENU)NULL, NULL, NULL);
if (hWndChild != NULL)
{
UpdateButtonLayoutForDpi(hWndChild);
}
}
break;
case WM_DPICHANGED:
{
// Find the button and resize it
HWND hWndButton = FindWindowEx(hWnd, NULL, NULL, NULL);
if (hWndButton != NULL)
{
UpdateButtonLayoutForDpi(hWndButton);
}
}
break;
Podczas aktualizowania aplikacji obsługującej dpi systemu należy wykonać kilka typowych kroków:
- Oznacz proces jako świadomy DPI (wersja 2) monitora przy użyciu manifestu aplikacji (lub innej metody, w zależności od używanych struktur interfejsu użytkownika).
- Ustaw logikę układu interfejsu użytkownika na wielokrotne użycie i przenieś ją z kodu inicjowania aplikacji, aby można było go użyć ponownie, gdy nastąpi zmiana DPI (WM_DPICHANGED w przypadku programowania w systemie Windows (Win32).
- Unieważnij dowolny kod, który zakłada, że dane poufne DPI (DPI/czcionki/rozmiary/itp.) nigdy nie muszą być aktualizowane. Bardzo powszechną praktyką jest buforowanie rozmiarów czcionek i wartości DPI podczas inicjowania procesu. Podczas aktualizowania aplikacji w celu stosowania do monitorowania dpi dane wrażliwe na dpi muszą być ponownie oceniane za każdym razem, gdy wystąpi nowe dpi.
- W przypadku zmiany DPI załaduj ponownie (lub ponownie rasteryzuj) wszystkie zasoby mapy bitowej dla nowego dpi lub opcjonalnie mapa bitowa rozciągnij aktualnie załadowane zasoby do odpowiedniego rozmiaru.
- Grep dla interfejsów API, które nie są Per-Monitor rozpoznawania DPI i zastępować je interfejsami API obsługującymi dpi Per-Monitor (jeśli ma to zastosowanie). Przykład: zastąp ciąg GetSystemMetrics ciągiem GetSystemMetricsForDpi.
- Przetestuj aplikację w systemie z wieloma wyświetlaczami/wieloma dpi.
- W przypadku jakichkolwiek okien najwyższego poziomu w aplikacji, których nie można zaktualizować do prawidłowej skali DPI, użyj skalowania DPI w trybie mieszanym (opisanego poniżej), aby umożliwić rozciągnięcie map bitowych tych okien najwyższego poziomu przez system.
Mixed-Mode skalowanie DPI (Sub-Process skalowanie DPI)
Podczas aktualizowania aplikacji pod kątem obsługi rozpoznawania dpi na monitor może czasami stać się niepraktyczne lub niemożliwe do zaktualizowania każdego okna w aplikacji w jednym kroku. Może to być spowodowane czasem i nakładem pracy wymaganym do zaktualizowania i przetestowania całego interfejsu użytkownika lub dlatego, że nie jesteś właścicielem całego kodu interfejsu użytkownika, który należy uruchomić (jeśli aplikacja może załadować interfejs użytkownika innej firmy). W takich sytuacjach system Windows oferuje sposób ułatwienia w świecie rozpoznawania monitora, umożliwiając uruchamianie niektórych okien aplikacji (tylko najwyższego poziomu) w oryginalnym trybie rozpoznawania DPI, podczas gdy koncentrujesz się na czasie i energii aktualizując ważniejsze części interfejsu użytkownika.
Poniżej przedstawiono ilustrację, jak to może wyglądać: zaktualizujesz główny interfejs użytkownika aplikacji ("Okno główne" na ilustracji), aby uruchomić z rozpoznawaniem dpi na monitorze podczas uruchamiania innych okien w istniejącym trybie ("Okno pomocnicze").
Przed rocznicową aktualizacją systemu Windows 10 (1607) tryb rozpoznawania DPI procesu był właściwością obejmującą cały proces. Począwszy od rocznicowej aktualizacji systemu Windows 10, tę właściwość można teraz ustawić na okna najwyższego poziomu. (podrzędne okna muszą nadal odpowiadać rozmiarowi skalowania elementu nadrzędnego). Okno najwyższego poziomu jest definiowane jako okno bez elementu nadrzędnego. Zazwyczaj jest to "zwykłe" okno z przyciskami minimalizowania, maksymalizowania i zamykania. Scenariusz, dla którego rozpoznawanie DPI podrzędnego procesu jest przeznaczone, jest posiadanie pomocniczego interfejsu użytkownika skalowanego przez system Windows (mapa bitowa rozciągnięta) podczas koncentracji czasu i zasobów na aktualizowaniu podstawowego interfejsu użytkownika.
Aby włączyć rozpoznawanie dpi podprocesu, wywołaj SetThreadDpiAwarenessContext przed i po wywołaniach tworzenia okna. Utworzone okno zostanie skojarzone z rozpoznawaniem dpi ustawionym za pomocą polecenia SetThreadDpiAwarenessContext. Użyj drugiego wywołania, aby przywrócić rozpoznawanie dpi bieżącego wątku.
Podczas korzystania ze skalowania DPI podprocesu można polegać na systemie Windows w celu wykonania niektórych skalowania DPI dla aplikacji, może to zwiększyć złożoność aplikacji. Ważne jest, aby zrozumieć wady tego podejścia i charakter złożoności, które wprowadza. Aby uzyskać więcej informacji na temat rozpoznawania dpi podprocesu, zobacz Mixed-Mode skalowania DPI i interfejsów API obsługujących dpi.
Testowanie zmian
Po zaktualizowaniu aplikacji w taki sposób, aby była uwzględniana przez monitor DPI, ważne jest, aby zweryfikować poprawność reagowania aplikacji na zmiany DPI w środowisku mieszanego DPI. Niektóre szczegółowe informacje dotyczące testowania obejmują:
- Przenoszenie okien aplikacji w przód i z powrotem między wyświetlaniem różnych wartości DPI
- Uruchamianie aplikacji na ekranach różnych wartości DPI
- Zmiana współczynnika skalowania monitora podczas działania aplikacji
- Zmiana ekranu używanego jako ekran podstawowy wylogowania się z systemu Windows, a następnie ponowne testowanie aplikacji po ponownym zalogowaniu. Jest to szczególnie przydatne podczas znajdowania kodu, który używa zakodowanych na sztywno rozmiarów/wymiarów.
Typowe pułapki (Win32)
Nie używasz sugerowanego prostokąta podanego w WM_DPICHANGED
Gdy system Windows wysyła okno aplikacji WM_DPICHANGED komunikat, ten komunikat zawiera sugerowany prostokąt, którego należy użyć do zmiany rozmiaru okna. Ważne jest, aby aplikacja używała tego prostokąta do zmiany rozmiaru, tak jak w następujący sposób:
- Upewnij się, że kursor myszy pozostanie w tym samym względnym położeniu w oknie podczas przeciągania między ekranami
- Zapobiegaj przechodzeniu okna aplikacji do cykli zmiany dpi, w którym jedna zmiana DPI wyzwala kolejną zmianę DPI, która wyzwala kolejną zmianę DPI.
Jeśli masz wymagania specyficzne dla aplikacji, które uniemożliwiają korzystanie z sugerowanego prostokąta, który system Windows udostępnia w komunikacie WM_DPICHANGED, zobacz WM_GETDPISCALEDSIZE. Ten komunikat może służyć do nadania systemowi Windows żądanego rozmiaru, który ma być używany po wystąpieniu zmiany DPI, jednocześnie unikając problemów opisanych powyżej.
brak dokumentacji dotyczącej wirtualizacji
Gdy HWND lub proces jest uruchomiony jako nieświadomy DPI lub system DPI, może być mapą bitową rozciągniętą przez system Windows. W takim przypadku system Windows skaluje i konwertuje informacje poufne DPI z niektórych interfejsów API na przestrzeń współrzędną wątku wywołującego. Jeśli na przykład wątek nieświadomy DPI wykonuje zapytanie o rozmiar ekranu podczas pracy na wyświetlaczu o wysokiej rozdzielczości DPI, system Windows zwirtualizuje odpowiedź udzieloną aplikacji tak, jakby ekran znajdował się w 96 jednostkach DPI. Alternatywnie, gdy wątek obsługujący dpi systemu wchodzi w interakcję z wyświetlaczem w innej rozdzielczości DPI niż był używany podczas uruchamiania sesji bieżącego użytkownika, system Windows przeprowadzi skalowanie dpi niektórych wywołań interfejsu API do przestrzeni współrzędnej, której będzie używać HWND, gdyby był uruchomiony w oryginalnym współczynniku skalowania DPI.
Podczas prawidłowego aktualizowania aplikacji klasycznej do skalowania DPI może być trudno wiedzieć, które wywołania interfejsu API mogą zwracać zwirtualizowane wartości na podstawie kontekstu wątku; te informacje nie są obecnie wystarczająco udokumentowane przez firmę Microsoft. Należy pamiętać, że w przypadku wywoływania dowolnego interfejsu API systemu z kontekstu wątku obsługującego dpi lub z obsługą dpi wartość zwracaną może być zwirtualizowana. W związku z tym upewnij się, że wątek jest uruchomiony w kontekście DPI oczekiwanym podczas interakcji z ekranem lub poszczególnymi oknami. Podczas tymczasowej zmiany kontekstu DPI wątku przy użyciu SetThreadDpiAwarenessContextnależy przywrócić stary kontekst, aby uniknąć nieprawidłowego zachowania w innej części aplikacji.
wiele interfejsów API systemu Windows nie ma kontekstu DPI
Wiele starszych interfejsów API systemu Windows nie zawiera kontekstu DPI ani HWND w ramach interfejsu. W związku z tym deweloperzy często muszą wykonać dodatkową pracę, aby obsłużyć skalowanie dowolnych informacji poufnych dpi, takich jak rozmiary, punkty lub ikony. Na przykład deweloperzy używający LoadIcon muszą załadować ikony rozciągniętej mapy bitowej lub użyć alternatywnych interfejsów API, aby załadować poprawnie rozmiar ikony dla odpowiedniego dpi, takiego jak LoadImage.
wymuszone resetowanie rozpoznawania dpi w całym procesie
Ogólnie rzecz biorąc, tryb rozpoznawania dpi procesu nie może zostać zmieniony po zainicjowaniu procesu. System Windows może jednak przymusowo zmienić tryb rozpoznawania DPI procesu, jeśli próbujesz przerwać wymaganie, że wszystkie HWND w drzewie okien mają ten sam tryb rozpoznawania DPI. We wszystkich wersjach systemu Windows, od systemu Windows 10 1703, nie można mieć różnych HWND w drzewie HWND działać w różnych trybach rozpoznawania DPI. Jeśli spróbujesz utworzyć relację podrzędną nadrzędną, która przerywa tę regułę, rozpoznawanie dpi całego procesu może zostać zresetowane. Może to być wyzwalane przez:
- Wywołanie CreateWindow, w którym przekazane w oknie nadrzędnym jest inny tryb rozpoznawania dpi niż wątek wywołujący.
- Wywołanie SetParent, w którym dwa okna są skojarzone z różnymi trybami rozpoznawania dpi.
W poniższej tabeli przedstawiono, co się stanie w przypadku próby naruszenia tej reguły:
Operacja | Windows 8.1 | Windows 10 (1607 i starsze) | Windows 10 (1703 i nowsze) |
---|---|---|---|
CreateWindow (In-Proc) | N/A | Podrzędne dziedziczy (tryb mieszany) | Podrzędne dziedziczy (tryb mieszany) |
CreateWindow (Cross-Proc) | wymuszonego resetowania (procesu wywołującego) | Podrzędne dziedziczy (tryb mieszany) | wymuszonego resetowania (procesu wywołującego) |
SetParent (In-Proc) | N/A | wymuszone resetowanie (bieżącego procesu) | niepowodzenie (ERROR_INVALID_STATE) |
SetParent (Cross-Proc) | wymuszonego resetowania (proces okna podrzędnego) | wymuszonego resetowania (proces okna podrzędnego) | wymuszonego resetowania (proces okna podrzędnego) |
Tematy pokrewne
dokumentacja interfejsu API o wysokiej rozdzielczości DPI
Mixed-Mode skalowania DPI i interfejsów API obsługujących dpi.