WPF : indépendance de la résolution d'écran avec Perspective

WPF : indépendance de la résolution d'écran avec Perspective

L'unité du système de coordonnées 2D de WPF est le Device Independent Pixel (DIP). C'est un pixel logique, indépendant de la résolution du périphérique d'affichage : 96 DIP correspondent à 1 pouce (2,54 cm).

Il est donc facile de déterminer par programmation des dimensions en unités de mesure physique, en particulier en pouces. Pour les adeptes du système métrique, la bibliothèque Perspective (à partir de sa version 0.5) fournit des fonctions de conversion dans la classe DipHelper : MmToDip(), CmToDip(), InchToDip(), DipToCm() et DipToMm().

Cela fonctionne très bien pour l'impression. Pour l'affichage à l'écran, c'est bien moins évident.

En effet, le système ne connait pas les dimensions de l'écran (sa diagonale) et donc ne peut pas connaître sa densité réelle de points.

Windows dispose bien d'un paramétrage permettant de lui indiquer manuellement cette densité. Mais son rôle est ambigu, car il est présenté à l'utilsateur comme un moyen de modifier la taille des polices (et indirectement d'appliquer un facteur d'échelle à l'ensemble du système). Ce paramétrage se fait via le menu contextuel du bureau :

  • Sous Windows 7 : Personnaliser - Affichage
  • Sous Windows Vista : Personnaliser – Régler la taille de la police (en PPP).
  • Sous Windows XP : Propriétés – Paramètres – Avancés.

Réglage de l’échelle du système sous Windows 7

Windows considère par défaut que l'écran a une résolution de 96 dpi. Ce qui s'avère exact pour un 17 pouces plat avec une matrice de 1280x1024, mais faux pour un 19 pouces de même définition, et dans de nombreux autres cas... Donc généralement, 96 DIP ne correspondent pas à un pouce !

Sauf si on indique à Windows la densité réelle de l'écran, au moyen du réglage personnalisé - sous Windows 7, lien Définir la taille du texte personnalisé (PPP).

Réglage personnalisé de l’échelle du système sous Windows 7

Le réglage se fait en faisant glisser la graduation affichée jusqu'à ce qu'elle correspondent à celle d'une règle graduée en pouces (que chaque Français possède évidemment ;-) posée sur l'écran.

Mais le système subit alors globalement une mise à l'échelle, que certaines applications peuvent mal supporter.

Une solution consiste à effectuer une mise à l'échelle selon le même principe mais uniquement au niveau de l'application WPF. Le facteur d'échelle à appliquer peut être déterminé de 2 manières au moyen d'outils fournis par la bibliothèque Perspective :

  • DipHelper.GetScreenIndependentScaleFactor() détermine ce facteur à partir de la taille de la diagonale de l'écran, exprimée en pouces. Cela suppose que cette taille soit connue, et surtout qu'elle corresponde bien à la surface affichée (ce qui n'est pas toujours le cas pour les écrans cathodiques).
  • La classe Ruler affiche une règle graduée en centimètres ;-) (ou en pouces si vous le préférez). Elle peut être utilisée comme le paramétrage de Windows, en lui appliquant une mise à l'échelle jusqu'à ce que ses dimensions correspondent à celle d'une règle appliquée sur l'écran. Le facteur obtenu peut ensuite être utilisé pour une mise à l'échelle générale de l'application (sauf celui de l'écran de paramétrage bien sûr).

Ces 2 techniques sont illustrées dans l'application PerspectiveDemo, page Pages/pWpf/DpiScaling.xaml, projet PerspectiveDemo.UI.

Perspective : Détermination du facteur d'échelle WPF

La classe ScreenSizeToScaleFactorConverter (qui utilise DipHelper.GetScreenIndependentScaleFactor()) permet le binding du facteur d'échelle à la zone de saisie de la diagonale de l'écran (elle-même liée à un Slider). Voir DpiScaling.xaml.

Cette application illustre par ailleurs le stockage des paramètres de mise à l'échelle dans l'Isolated Storage de .NET via la classe AssemblyConfigManager (qui exploite IsolatedStorageHelper).

private void bSaveScale_Click(object sender, RoutedEventArgs e)
{
    DipHelper.ScreenIndependentScaleX = ScreenIndependentScaleTransform.ScaleX;
    DipHelper.ScreenIndependentScaleY = ScreenIndependentScaleTransform.ScaleY;
    DipHelper.ScreenSize = sScreenSize.Value;
    AssemblyConfigManager.SaveSettings();
}

A propos de cet article

Auteur : Olivier Dewit.

Historique :

  • 30 juin 2010 : mise à jour pour la version 2.0 de Perspective, et pour Windows 7.
  • 16 mai 2008 : mise à jour pour la version 0.9 de Perspective. Article original
  • 6 janvier 2008 : 1ère publication (Perspective version 0.5). Article original