Mixed-Mode Ridimensionamento DPI e API compatibili con DPI
supporto per la consapevolezza dpi Sub-Process
SetThreadDpiAwarenessContext consente l'uso di diverse modalità di ridimensionamento DPI all'interno di un singolo processo. Prima dell'Aggiornamento dell'anniversario di Windows 10, la consapevolezza DPI di una finestra era associata alla modalità di consapevolezza DPI a livello di processo (non consapevole dei DPI, consapevole dei DPI di sistema o Per-Monitor consapevole dei DPI). Ma ora, con SetThreadDpiAwarenessContext, le finestre di primo livello possono avere una modalità di riconoscimento DPI diversa da quella della modalità di riconoscimento DPI a livello di processo. Ciò influisce anche sulle finestre figlio, perché avranno sempre la stessa modalità di riconoscimento DPI della finestra padre.
L'uso di SetThreadDpiAwarenessContext consente agli sviluppatori di decidere dove concentrarsi sulle attività di sviluppo quando si definisce un comportamento specifico di DPI per le applicazioni desktop. Ad esempio, la finestra principale principale di un'applicazione può essere ridimensionata in base al monitoraggio, mentre le finestre secondarie di primo livello possono essere ridimensionate tramite il ridimensionamento bitmap dal sistema operativo.
Contesto di consapevolezza DPI
Prima della disponibilità di SetThreadDpiAwarenessContext, la consapevolezza DPI di un processo veniva definita nel manifest del file binario dell'applicazione o tramite una chiamata a SetProcessDpiAwareness durante l'inizializzazione del processo. Con SetThreadDpiAwarenessContext, ogni thread può avere un contesto di consapevolezza DPI individuale che può essere diverso da quello della modalità di riconoscimento DPI a livello di processo. Il contesto DPI di un thread è rappresentato dal tipo DPI_AWARENESS_CONTEXT e si comporta come segue:
- Un thread può avere il contesto di consapevolezza DPI modificato in qualsiasi momento.
- Tutte le chiamate API effettuate dopo la modifica del contesto verranno eseguite nel contesto DPI corrispondente (e possono essere virtualizzate).
- Quando viene creata una finestra, la consapevolezza DPI viene definita come la consapevolezza DPI del thread chiamante in quel momento.
- Quando viene chiamata la procedura della finestra per una finestra, il thread viene automaticamente passato al contesto di consapevolezza DPI in uso al momento della creazione della finestra.
Uno scenario comune per l'uso di SetThreadDpiAwarenessContext è il seguente: Iniziare con un thread in esecuzione con un contesto (ad esempio DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE) passare temporaneamente a un contesto diverso (DPI_AWARENESS_CONTEXT_UNAWARE), creare una finestra e quindi ripristinare immediatamente lo stato precedente del contesto del thread. La finestra creata avrà un contesto DPI di DPI_AWARENESS_CONTEXT_UNAWARE, mentre il contesto del thread chiamante verrà ripristinato in DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE con una chiamata successiva a SetThreadDpiAwarenessContext. In questo scenario, la finestra associata al thread chiamante viene eseguita con un contesto specifico per monitor (e quindi non viene allungata tramite bitmap dal sistema operativo), mentre la finestra appena creata non sarà consapevole dei DPI (e quindi verrà automaticamente allungata tramite bitmap su un display con ridimensionamento impostato su >100%).
La figura 1 illustra come viene eseguito il thread del processo principale con DPI_AWARENESS_CONTEXT_PER_MONITOR, cambia il contesto in DPI_AWARENESS_CONTEXT_UNAWAREe crea una nuova finestra. La finestra appena creata viene quindi eseguita con un contesto di consapevolezza DPI di DPI_AWARENESS_CONTEXT_UNAWARE ogni volta che viene inviato un messaggio o le chiamate API vengono effettuate da esso. Subito dopo aver creato la nuova finestra, il thread principale viene ripristinato nel contesto precedente di DPI_AWARENESS_CONTEXT_PER_MONITOR.
Nuove API relative ai DPI
Oltre al supporto per diverse modalità di consapevolezza DPI all'interno di un singolo processo che SetThreadDpiAwarenessContext offre, è stata aggiunta la seguente funzionalità specifica per DPI per le applicazioni desktop:
-
EnableNonClientDpiScaling
-
Nota
La per monitor V2 modalità di riconoscimento DPI abilita automaticamente questa funzionalità e chiama EnableNonClientDpiScaling non è quindi necessaria nelle applicazioni che lo usano.
La chiamata EnableNonClientDpiScaling dall'interno di un gestore WM_NCCREATE finestra comporterà il ridimensionamento automatico dell'area non client di una finestra di primo livello per dpi. Se la finestra di primo livello è compatibile con DPI per monitor (indipendentemente dal fatto che il processo stesso sia compatibile con DPI per monitor o perché la finestra è stata creata all'interno di un thread compatibile con DPI per monitor), la barra della didascalia, le barre di scorrimento, i menu e le barre dei menu di queste finestre verranno ridimensionate ogni volta che cambia dpi della finestra.
-
Si noti che le aree non-client di una finestra figlia, ad esempio le barre di scorrimento non-client di un controllo di modifica figlio, non verranno ridimensionate automaticamente quando viene usata questa API.
-
Nota
EnableNonClientDpiScaling deve essere chiamato dall'handler WM_NCCREATE.
-
-
le API *ForDpi
Diverse API usate di frequente, ad esempio GetSystemMetrics non hanno alcun contesto di HWND e pertanto non hanno modo di dedurre la corretta consapevolezza DPI per i valori restituiti. La chiamata di queste API da un thread in esecuzione in una modalità diversa di riconoscimento DPI o contesto può restituire valori non ridimensionati per il contesto del thread chiamante. GetSystemMetricForDpi, SystemParametersInfoForDpie AdjustWindowRectExForDpi eseguiranno la stessa funzionalità delle controparti non consapevoli del DPI, ma accettano un DPI come argomento e ricavano la consapevolezza DPI dal contesto del thread corrente.
GetSystemMetricForDpi e SystemParametersInfoForDpi restituiranno valori delle metriche di sistema con scalabilità DPI e valori dei parametri di sistema in base a questa equazione:
GetSystemMetrics(...) @ dpi == GetSystemMetricsForDpi(..., dpi)
Pertanto, quando si chiama GetSystemMetrics (o SystemParametersInfoForDpi), eseguendolo su un dispositivo con uno specifico valore DPI di sistema, si otterrà lo stesso valore che le loro varianti riconoscenti il DPI (GetSystemMetricsForDpi e SystemParametersInfoForDpi) restituiranno, dato lo stesso valore DPI come input.
AdjustWindowRectExForDpi accetta un HWND e calcola le dimensioni necessarie di un rettangolo di finestra in modo sensibile ai DPI.
-
GetDpiForWindow
-
GetDpiForWindow restituirà il DPI associato all'HWND fornito. La risposta dipende dalla modalità di riconoscimento DPI del HWND:
Modalità di riconoscimento DPI di HWND Valore restituito Ignaro 96 Sistema DPI di sistema Per-Monitor DPI di visualizzazione su cui si trova principalmente la finestra di primo livello associata
Se viene specificata una finestra figlio, verrà restituito il valore DPI della finestra genitore di alto livello corrispondente.
-
GetDpiForWindow restituirà il DPI associato all'HWND fornito. La risposta dipende dalla modalità di riconoscimento DPI del HWND:
-
GetDpiForSystem
-
La chiamata GetDpiForSystem è più efficiente rispetto alla chiamata GetDC e GetDeviceCaps per ottenere il valore DPI di sistema.
-
Qualsiasi componente che può essere in esecuzione in un'applicazione che utilizza la consapevolezza DPI del sottoprocesso non deve presupporre che il valore DPI di sistema sia statico durante il ciclo di vita del processo. Ad esempio, se un thread in esecuzione nel contesto di consapevolezza DPI_AWARENESS_CONTEXT_UNAWARE interroga il DPI di sistema, la risposta sarà 96. Tuttavia, se lo stesso thread è passato a DPI_AWARENESS_CONTEXT_SYSTEM contesto di consapevolezza e ha eseguito di nuovo una query sul dpi di sistema, la risposta potrebbe essere diversa. Per evitare l'uso di un valore DPI di sistema memorizzato nella cache (e possibilmente non aggiornato), usare GetDpiForSystem per recuperare la DPI di sistema rispetto alla modalità di riconoscimento DPI del thread chiamante.
-