Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
API importanti
Nota
Questa pagina illustra lo sviluppo WPF legacy per Windows 8.1. Se si sviluppano applicazioni WPF per Windows 10, vedere la documentazione più recente su GitHub.
Windows 8.1 offre agli sviluppatori nuove funzionalità per creare applicazioni desktop compatibili con DPI per monitor. Per sfruttare questa funzionalità, un'applicazione compatibile con DPI per monitor deve eseguire le operazioni seguenti:
- Modificare le dimensioni della finestra per mantenere una dimensione fisica coerente in qualsiasi visualizzazione
- Ridisporre e rielaborare la grafica per le nuove dimensioni della finestra
- Selezionare i tipi di carattere ridimensionati in modo appropriato per il livello DPI
- Selezionare e caricare asset bitmap personalizzati per il livello DPI
Per facilitare la creazione di un'applicazione compatibile con DPI per monitor, Windows 8.1 fornisce le seguenti api Microsoft Win32API:
- SetProcessDpiAwareness (o voce del manifesto DPI) imposta il processo su un livello di consapevolezza DPI specificato, che determina quindi il modo in cui Windows ridimensiona l'interfaccia utente. Sostituisce SetProcessDPIAware.
- GetProcessDpiAwareness restituisce il livello di consapevolezza DPI. Sostituisce IsProcessDPIAware.
- GetDpiForMonitor restituisce il valore DPI per un monitor.
- La notifica della finestra di WM_DPICHANGED viene inviata alle applicazioni consapevoli del DPI per monitor quando la posizione di una finestra cambia in modo che la maggior parte dell'area interseca un monitor con un valore DPI diverso da quello prima della modifica della posizione o quando l'utente sposta il cursore del display. Per creare un'applicazione che ridimensiona e esegue nuovamente il rendering di se stessa quando un utente lo sposta in una visualizzazione diversa, usare questa notifica.
Per ulteriori dettagli sui vari livelli di supporto DPI per le applicazioni desktop in Windows 8.1, consulta l'argomento Scrittura di applicazioni desktop e Win32 DPI-Aware.
Ridimensionamento DPI e WPF
Le applicazioni Windows Presentation Foundation (WPF) sono compatibili con DPI di sistema per impostazione predefinita. Per le definizioni dei diversi livelli di consapevolezza dei DPI, vedere l'argomento Scrittura delle applicazioni DPI-Aware Desktop e Win32. Il sistema grafico WPF usa unità indipendenti dal dispositivo per abilitare la risoluzione e l'indipendenza del dispositivo. WPF ridimensiona automaticamente ogni pixel indipendente dal dispositivo in base alla dpi di sistema corrente. In questo modo, le applicazioni WPF possono essere ridimensionate automaticamente quando il valore DPI della finestra di monitoraggio si trova nello stesso dpi di sistema. Tuttavia, poiché le applicazioni WPF sono compatibili con dpi di sistema, l'applicazione verrà ridimensionata dal sistema operativo quando l'applicazione viene spostata in un monitor con un valore DPI diverso o quando il dispositivo di scorrimento nel pannello di controllo viene usato per modificare il valore DPI. Il ridimensionamento del sistema operativo può comportare la visualizzazione sfocata delle applicazioni WPF, soprattutto quando il ridimensionamento non è integrale. Per evitare di ridimensionare le applicazioni WPF, è necessario aggiornare in modo che siano compatibili con DPI per monitor.
Procedura dettagliata di esempio WPF compatibile con monitoraggio
Il esempio WPF compatibile con monitoraggio è un'applicazione WPF di esempio aggiornata in modo da essere compatibile con DPI per monitor. L'esempio è costituito da due progetti:
- NativeHelpers.vcxproj: si tratta di un progetto helper nativo che implementa la funzionalità di base per rendere un'applicazione WPF compatibile con DPI per-monitor utilizzando le Win32 APIs sopra elencate. Il progetto contiene due classi:
- PerMonDPIHelpers: classe che fornisce funzioni helper per operazioni correlate a DPI, ad esempio il recupero del valore DPI corrente del monitoraggio attivo, l'impostazione di un processo in grado di essere compatibile con DPI per monitor e così via.
- PerMonitorDPIWindow: classe base derivata da System.Windows.Window che implementa la funzionalità per rendere una finestra dell'applicazione WPF compatibile con dpi per monitor. Regola le dimensioni della finestra, le dimensioni del rendering della grafica e le dimensioni del carattere in base alla DPI del monitor anziché alla DPI di sistema.
- WPFApplication.csproj: applicazione WPF di esempio che utilizza PerMonitorDPIWindow (PerMonitorDPIWindow) e illustra come la finestra dell'applicazione e il rendering vengono ridimensionate quando la finestra viene spostata in un monitor con un valore DPI diverso o quando viene usato il dispositivo di scorrimento nel pannello di controllo Display per modificare il valore DPI.
Per eseguire l'esempio, seguire questa procedura:
- Scaricare e decomprimere l'esempio WPF compatibile per monitor .
- Avviare Microsoft Visual Studio e selezionare File > Apri > progetto/soluzione
- Navigare fino alla directory contenente l'esempio decompresso. Passare alla directory denominata per l'esempio e fare doppio clic sul file della soluzione Visual Studio (.sln)
- Premere F7 o usare Compila > Compila soluzione per compilare l'esempio
- Premere CTRL+F5 o usare Debug > Avvia senza eseguire il debug per eseguire l'esempio
Per visualizzare l'impatto della modifica di DPI in un'applicazione WPF aggiornata in modo che sia compatibile con dpi per monitor usando la classe base nell'esempio, spostare la finestra dell'applicazione da e verso gli schermi con DPI diversi. Quando la finestra viene spostata tra monitor, le dimensioni della finestra e la scala dell'interfaccia utente vengono aggiornate in base alla DPI dello schermo usando il sistema grafico scalabile di WPF, anziché essere ridimensionato dal sistema operativo. Il rendering dell'interfaccia utente dell'applicazione viene eseguito in modo nativo e non appare sfocato. Se non si dispone di due schermi con valori DPI diversi, modificare il valore DPI modificando il dispositivo di scorrimento nel pannello di controllo Display. Modificando il cursore e facendo clic su Applica, la finestra dell'applicazione verrà ridimensionata e la scala dell'interfaccia utente verrà aggiornata automaticamente.
Aggiornamento di un'applicazione WPF esistente in modo che sia compatibile con dpi per monitor usando il progetto helper nell'esempio WPF
Se si dispone di un'applicazione WPF esistente e si vuole sfruttare l'utilità helper DPI dell'esempio per renderla consapevole dei DPI, seguire queste procedure.
Scaricare e decomprimere l'esempio WPF compatibile con Per Monitor
Avviare Visual Studio e selezionare File > Apri > progetto/soluzione
Passare alla directory che contiene un'applicazione WPF esistente e fare doppio clic sul file della soluzione Visual Studio (.sln)
Fare clic con il pulsante destro del mouse su Soluzione > Aggiungi > il progetto esistente

Nella finestra di dialogo di selezione file passare alla directory che contiene l'esempio decompresso. Aprire la directory denominata per l'esempio, passare alla cartella "NativeHelpers", selezionare il file di progetto Visual C++ "NativeHelpers.vcxproj" e fare clic su OK
Fare clic con il pulsante destro del mouse sul progetto NativeHelpers e selezionare Compila. Verrà generato NativeHelpers.dll che verrà aggiunto come riferimento all'applicazione WPF nel passaggio successivo

Aggiungi un riferimento a NativeHelpers.dll dalla tua applicazione WPF. Espandi il tuo progetto dell'applicazione WPF, fai clic con il pulsante destro del mouse su Riferimenti e fai clic su Aggiungi riferimento...
Nella finestra di dialogo risultante, espandere la sezione Soluzione. In Progettiselezionare NativeHelpers e fare clic OK

Espandi il progetto di applicazione WPF, espandi Proprietàe apri AssemblyInfo.cs. Apportare le aggiunte seguenti a AssemblyInfo.cs
- Aggiungere un riferimento a System.Windows.Media nella sezione di riferimento (usando System.Windows.Media;)
- Aggiungere l'attributo DisableDpiAwareness (
[assembly: DisableDpiAwareness])
Ereditare la classe di finestra WPF principale dalla classe di base PerMonitorDPIWindow
Aggiornare il file .cs della finestra WPF principale per ereditare dalla classe di base PerMonitorDPIWindow
- Aggiungere un riferimento a NativeHelpers nella sezione di riferimento aggiungendo la riga
using NativeHelpers; - Ereditare la classe della finestra principale dalla classe PerMonitorDPIWindow
- Aggiungere un riferimento a NativeHelpers nella sezione di riferimento aggiungendo la riga
Aggiornare il file xaml della finestra WPF principale per ereditare dalla classe di base PerMonitorDPIWindow
- Aggiungere un riferimento a NativeHelpers nella sezione di riferimento aggiungendo la riga
xmlns:src="clr-namespace:NativeHelpers;assembly=NativeHelpers" - Ereditare la classe della finestra principale dalla classe PerMonitorDPIWindow
- Aggiungere un riferimento a NativeHelpers nella sezione di riferimento aggiungendo la riga
Premere F7 o usare Compila > Compila soluzione per compilare l'esempio
Premere CTRL+F5 o usare Debug > Avvia senza eseguire il debug per eseguire l'esempio
L'esempio WPF con riconoscimento di per monitor'applicazione illustra come un'applicazione WPF può essere aggiornata in modo che sia compatibile con dpi per monitor rispondendo alla notifica della finestra di WM_DPICHANGED. In risposta alla notifica della finestra, l'esempio aggiorna la trasformazione di scala usata da WPF in base al valore DPI corrente del monitor in cui è attivata la finestra. Il wParam della notifica della finestra contiene il nuovo valore DPI nel wParam. Il lParam contiene un rettangolo con le dimensioni e la posizione della nuova finestra suggerita, ridimensionata per il nuovo DPI.
Nota:
Nota
Poiché questo esempio sovrascrive le dimensioni della finestra e la trasformazione della scala del nodo radice della finestra WPF, è possibile che lo sviluppatore dell'applicazione richieda ulteriori operazioni se:
- Le dimensioni della finestra influisce su altre parti dell'applicazione come questa finestra WPF ospitata all'interno di un'altra applicazione.
- L'applicazione WPF che estende questa classe imposta qualche altra trasformazione sull'oggetto visivo radice; l'esempio potrebbe sovrascrivere un'altra trasformazione applicata dalla stessa applicazione WPF.
Panoramica del progetto helper nell'esempio WPF
Per rendere un'applicazione WPF esistente compatibile con DPI per monitor, la libreria NativeHelpers offre le funzionalità seguenti:
Contrassegna l'applicazione WPF come consapevole del DPI per monitor: L'applicazione WPF è contrassegnata come consapevole del DPI per monitor chiamando SetProcessDpiAwareness per il processo corrente. Contrassegnare l'applicazione come compatibile con DPI per monitor garantisce che
- Il sistema operativo non scala l'applicazione quando il DPI di sistema non corrisponde al DPI corrente del monitor su cui si trova la finestra dell'applicazione.
- Il messaggio WM_DPICHANGED viene inviato ogni volta che cambia il valore DPI della finestra
Regola la dimensione della finestra, riorganizza e rinnova il rendering del contenuto grafico, seleziona i tipi di carattere in base alla DPI iniziale del monitor su cui si trova la finestra: Una volta che l'applicazione è contrassegnata come consapevole del DPI per monitor, WPF continuerà a ridimensionare le dimensioni della finestra, la grafica e le dimensioni del carattere in base alla DPI di sistema. Poiché, all'avvio dell'app, il valore DPI di sistema non è garantito che corrisponda al valore DPI del monitor in cui viene avviata la finestra, la libreria regola questi valori dopo il caricamento della finestra. La classe di base PerMonitorDPIWindow aggiorna questi elementi nel gestore onloaded().
Le dimensioni della finestra vengono aggiornate modificando le proprietà della Larghezza e dell'Altezza della finestra. Il layout e le dimensioni vengono aggiornati applicando una trasformazione di scala appropriata al nodo radice della finestra WPF.
void PerMonitorDPIWindow::OnLoaded(Object^ , RoutedEventArgs^ ) { if (m_perMonitorEnabled) { m_source = (HwndSource^) PresentationSource::FromVisual((Visual^) this); HwndSourceHook^ hook = gcnew HwndSourceHook(this, &PerMonitorDPIWindow::HandleMessages); m_source->AddHook(hook); //Calculate the DPI used by WPF. m_wpfDPI = 96.0 * m_source->CompositionTarget->TransformToDevice.M11; //Get the Current DPI of the monitor of the window. m_currentDPI = NativeHelpers::PerMonitorDPIHelper::GetDpiForWindow(m_source->Handle); //Calculate the scale factor used to modify window size, graphics and text m_scaleFactor = m_currentDPI / m_wpfDPI; //Update Width and Height based on the on the current DPI of the monitor Width = Width * m_scaleFactor; Height = Height * m_scaleFactor; //Update graphics and text based on the current DPI of the monitor UpdateLayoutTransform(m_scaleFactor); } } void PerMonitorDPIWindow::UpdateLayoutTransform(double scaleFactor) { // Adjust the rendering graphics and text size by applying the scale transform to the top level visual node of the Window if (m_perMonitorEnabled) { auto child = GetVisualChild(0); if (m_scaleFactor != 1.0) { ScaleTransform^ dpiScale = gcnew ScaleTransform(scaleFactor, scaleFactor); child->SetValue(Window::LayoutTransformProperty, dpiScale); } else { child->SetValue(Window::LayoutTransformProperty, nullptr); } } }Risponde alla notifica della finestra di WM_DPICHANGED: Aggiornare le dimensioni della finestra, la grafica e le dimensioni del carattere in base al valore DPI passato nella notifica della finestra. La classe base PerMonitorDPIWindow gestisce la notifica della finestra nel metodo HandleMessages().
La dimensione della finestra viene aggiornata chiamando SetWindowPos utilizzando le informazioni passate nell' lparam del messaggio della finestra. Il layout e le dimensioni della grafica vengono aggiornati applicando una trasformazione di scala appropriata al nodo radice della finestra WPF. Il fattore di scala viene calcolato usando il valore DPI passato nel wparam del messaggio della finestra.
IntPtr PerMonitorDPIWindow::HandleMessages(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool% ) { double oldDpi; switch (msg) { case WM_DPICHANGED: LPRECT lprNewRect = (LPRECT)lParam.ToPointer(); SetWindowPos(static_cast<HWND>(hwnd.ToPointer()), 0, lprNewRect->left, lprNewRect- >top, lprNewRect->right - lprNewRect->left, lprNewRect->bottom - lprNewRect->top, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); oldDpi = m_currentDPI; m_currentDPI = static_cast<int>(LOWORD(wParam.ToPointer())); if (oldDpi != m_currentDPI) { OnDPIChanged(); } break; } return IntPtr::Zero; } void PerMonitorDPIWindow::OnDPIChanged() { m_scaleFactor = m_currentDPI / m_wpfDPI; UpdateLayoutTransform(m_scaleFactor); DPIChanged(this, EventArgs::Empty); } void PerMonitorDPIWindow::UpdateLayoutTransform(double scaleFactor) { // Adjust the rendering graphics and text size by applying the scale transform to the top level visual node of the Window if (m_perMonitorEnabled) { auto child = GetVisualChild(0); if (m_scaleFactor != 1.0) { ScaleTransform^ dpiScale = gcnew ScaleTransform(scaleFactor, scaleFactor); child->SetValue(Window::LayoutTransformProperty, dpiScale); } else { child->SetValue(Window::LayoutTransformProperty, nullptr); } } }
Gestione delle modifiche DPI per asset come immagini
Per aggiornare il contenuto grafico, l'applicazione WPF di esempio applica una trasformazione di scalabilità al nodo radice dell'applicazione WPF. Sebbene questo funzioni bene per il contenuto di cui viene eseguito il rendering in modo nativo da WPF (rettangolo, testo e così via), ciò implica che gli asset bitmap come le immagini vengono ridimensionati da WPF.
Per evitare bitmap sfocate causate dal ridimensionamento, lo sviluppatore dell'applicazione WPF può scrivere un controllo immagine DPI personalizzato che seleziona un asset diverso in base al valore DPI corrente del monitor in cui è attiva la finestra. Il controllo immagine può basarsi sull'evento DPIChanged() generato per la finestra WPF che utilizza dal PerMonitorDPIWindow, quando cambia il valore DPI.
Nota
Il controllo immagine deve anche selezionare il controllo corretto durante l'avvio dell'app nel Loaded() gestore eventi della finestra WPF.