Remarque: veuillez consulter les autres réponses car elles contiennent des techniques très utiles. Ma réponse ici ne fournit que des mises en garde et des mises en garde contre le fait de supposer que la conscience DPI est facile.
J'évite généralement la mise à l'échelle compatible DPI avec TForm.Scaled = True
. La sensibilisation DPI n'est importante pour moi que lorsque cela devient important pour les clients qui m'appellent et sont prêts à payer pour cela. La raison technique derrière ce point de vue est que la conscience DPI ou non, vous ouvrez une fenêtre sur un monde de souffrance. De nombreux contrôles VCL standard et tiers ne fonctionnent pas correctement en haute résolution. L'exception notable est que les parties VCL qui enveloppent les contrôles communs Windows fonctionnent remarquablement bien à DPI élevé. Un grand nombre de contrôles personnalisés tiers et intégrés Delphi VCL ne fonctionnent pas bien, ou pas du tout, à un DPI élevé. Si vous prévoyez d'activer TForm.Scaled, assurez-vous de tester à 96, 125 et 150 DPI pour chaque formulaire de votre projet, et chaque tiers et contrôle intégré que vous utilisez.
Delphi lui-même est écrit en Delphi. Il a le drapeau de sensibilisation High DPI activé, pour la plupart des formulaires, bien que même aussi récemment que dans Delphi XE2, les auteurs de l'EDI eux-mêmes ont décidé de NE PAS activer ce drapeau de manifeste High DPI Awareness. Notez que dans Delphi XE4 et versions ultérieures, l'indicateur de prise de conscience HIGH DPI est activé et l'EDI a l'air bien.
Je suggère de ne pas utiliser TForm.Scaled = true (qui est une valeur par défaut dans Delphi, donc à moins que vous ne l'ayez modifié, la plupart de vos formulaires ont Scaled = true) avec les indicateurs High DPI Aware (comme indiqué dans les réponses de David) avec Applications VCL créées à l'aide du concepteur de formulaires Delphi intégré.
J'ai essayé dans le passé de faire un échantillon minimal du type de rupture que vous pouvez vous attendre à voir lorsque TForm.Scaled est vrai et lorsque la mise à l'échelle du formulaire Delphi a un problème. Ces problèmes ne sont pas toujours et uniquement déclenchés par une valeur PPP autre que 96. J'ai été incapable de déterminer une liste complète d'autres choses, y compris les changements de taille de police Windows XP. Mais comme la plupart de ces problèmes n'apparaissent que dans mes propres applications, dans des situations assez complexes, j'ai décidé de vous montrer des preuves que vous pourrez vérifier vous-même.
Delphi XE ressemble à ceci lorsque vous définissez la mise à l'échelle DPI sur "Polices @ 200%" dans Windows 7, et Delphi XE2 est également cassé sous Windows 7 et 8, mais ces problèmes semblent être corrigés à partir de Delphi XE4:
Il s'agit principalement de contrôles VCL standard qui se comportent mal à un DPI élevé. Notez que la plupart des éléments n'ont pas du tout été mis à l'échelle, de sorte que les développeurs de Delphi IDE ont décidé d'ignorer la prise de conscience DPI, ainsi que de désactiver la virtualisation DPI. Un choix si intéressant.
Désactivez la virtualisation DPI uniquement si vous souhaitez cette nouvelle source supplémentaire de douleur et de choix difficiles. Je vous suggère de le laisser tranquille. Notez que les contrôles communs de Windows semblent généralement fonctionner correctement. Notez que le contrôle de l'explorateur de données Delphi est un wrapper C # WinForms autour d'un contrôle commun d'arborescence Windows standard. C'est un pur problème de microsoft, et sa résolution peut nécessiter qu'Embarcadero réécrive un contrôle d'arborescence .Net natif pur pour son explorateur de données, ou qu'il écrive du code DPI-check-and-modify-properties pour changer la hauteur des éléments dans le contrôle. Même Microsoft WinForms ne peut pas gérer un DPI élevé de manière propre, automatique et sans code kludge personnalisé.
Mise à jour: Fait intéressant: bien que l'EDI delphi ne semble pas être «virtualisé», il n'utilise pas le contenu manifeste montré par David pour réaliser une «virtualisation sans DPI». Peut-être utilise-t-il une fonction API lors de l'exécution.
Mise à jour 2: En réponse à la façon dont je prendrais en charge 100% / 125% DPI, je proposerais un plan en deux phases. La phase 1 consiste à inventorier mon code pour les contrôles personnalisés qui doivent être corrigés pour un DPI élevé, puis à élaborer un plan pour les corriger ou les éliminer progressivement. La phase 2 consisterait à prendre certaines zones de mon code qui sont conçues comme des formulaires sans gestion de la mise en page et à les changer en formulaires qui utilisent une sorte de gestion de la mise en page afin que les changements de DPI ou de hauteur de police puissent fonctionner sans découpage. Je soupçonne que ce travail de mise en page "inter-contrôle" serait beaucoup plus complexe dans la plupart des applications que le travail "intra-contrôle".
Mise à jour: En 2016, le dernier Delphi 10.1 Berlin fonctionne bien sur mon poste de travail 150 dpi.
SetProcessDPIAware
.Vos paramètres dans le fichier .dfm seront mis à l'échelle correctement, aussi longtemps que
Scaled
c'estTrue
.Si vous définissez des dimensions dans le code, vous devez les mettre à l'échelle en les
Screen.PixelsPerInch
divisant parForm.PixelsPerInch
. UtilisezMulDiv
pour faire cela.C'est ce que fait le framework de persistance de formulaire quand
Scaled
estTrue
.En fait, vous pouvez faire un argument convaincant pour remplacer cette fonction par une version qui code en dur une valeur de 96 pour le dénominateur. Cela vous permet d'utiliser des valeurs de dimension absolues et de ne pas vous soucier du changement de signification si vous modifiez la mise à l'échelle de la police sur votre machine de développement et enregistrez à nouveau le fichier .dfm. La raison qui compte est que la
PixelsPerInch
propriété stockée dans le fichier .dfm est la valeur de la machine sur laquelle le fichier .dfm a été enregistré pour la dernière fois.Donc, en poursuivant le thème, une autre chose à laquelle il faut se méfier est que si votre projet est développé sur plusieurs machines avec des valeurs DPI différentes, vous constaterez que la mise à l'échelle utilisée par Delphi lors de l'enregistrement des fichiers .dfm entraîne des contrôles errant sur une série de modifications. . Sur mon lieu de travail, pour éviter cela, nous avons une politique stricte selon laquelle les formulaires ne sont édités qu'à 96 dpi (mise à l'échelle à 100%).
En fait ma version de
ScaleFromSmallFontsDimension
tient également compte de la possibilité que la police du formulaire diffère au moment de l'exécution de celle définie au moment de la conception. Sur les machines XP, les formulaires de ma candidature utilisent Tahoma 8pt. Sur Vista et les versions ultérieures, l'interface utilisateur Segoe 9pt est utilisée. Cela offre encore un autre degré de liberté. La mise à l'échelle doit en tenir compte car les valeurs de dimension absolue utilisées dans le code source sont supposées être relatives à la ligne de base de Tahoma 8pt à 96 dpi.Si vous utilisez des images ou des glyphes dans votre interface utilisateur, ceux-ci doivent également être mis à l'échelle. Un exemple courant serait les glyphes utilisés sur les barres d'outils et les menus. Vous voudrez fournir ces glyphes sous forme de ressources d'icônes liées à votre exécutable. Chaque icône doit contenir une gamme de tailles, puis au moment de l'exécution, vous choisissez la taille la plus appropriée et la chargez dans une liste d'images. Quelques détails sur ce sujet peuvent être trouvés ici: Comment charger des icônes à partir d'une ressource sans souffrir d'alias?
Une autre astuce utile consiste à définir les dimensions en unités relatives, par rapport à
TextWidth
ouTextHeight
. Donc, si vous voulez que quelque chose soit d'environ 10 lignes verticales, vous pouvez utiliser10*Canvas.TextHeight('Ag')
. Il s'agit d'une métrique très approximative car elle ne permet pas d'espacement des lignes, etc. Cependant, il suffit souvent de pouvoir faire en sorte que l'interface graphique évolue correctement avecPixelsPerInch
.Vous devez également marquer votre application comme étant à haute résolution . La meilleure façon de procéder consiste à utiliser le manifeste de l'application. Puisque les outils de construction de Delphi ne vous permettent pas de personnaliser le manifeste que vous utilisez, cela vous oblige à lier votre propre ressource de manifeste.
Le script de ressources ressemble à ceci:
où
Manifest.txt
contient le manifeste réel. Vous devrez également inclure la section comctl32 v6 et définirrequestedExecutionLevel
surasInvoker
. Vous liez ensuite cette ressource compilée à votre application et vous assurez que Delphi n'essaye pas de faire de même avec son manifeste. Dans Delphi moderne, vous y parvenez en définissant l'option de projet Runtime Themes sur Aucun.Le manifeste est le bon moyen de déclarer que votre application est consciente du DPI élevé. Si vous voulez juste l'essayer rapidement sans déranger votre manifeste, appelez
SetProcessDPIAware
. Faites-le comme la toute première chose que vous faites lorsque votre application s'exécute. De préférence dans l'une des premières sections d'initialisation de l'unité, ou comme première chose dans votre fichier .dpr.Si vous ne déclarez pas que votre application est compatible avec le DPI élevé, Vista et les versions ultérieures la rendront dans un mode hérité pour toute mise à l'échelle de police supérieure à 125%. Cela semble assez affreux. Essayez d'éviter de tomber dans ce piège.
Mise à jour DPI de Windows 8.1 par moniteur
À partir de Windows 8.1, le système d'exploitation prend désormais en charge les paramètres DPI par moniteur ( http://msdn.microsoft.com/en-ca/magazine/dn574798.aspx ). C'est un gros problème pour les appareils modernes qui peuvent avoir différents écrans connectés avec des capacités très différentes. Vous pouvez avoir un écran d'ordinateur portable très élevé et un projecteur externe à faible DPI. Soutenir un tel scénario demande encore plus de travail que décrit ci-dessus.
la source
Il est également important de noter que le respect du DPI de l'utilisateur n'est qu'un sous-ensemble de votre vrai travail:
Pendant des décennies, Windows a résolu ce problème avec la notion de mise en page en utilisant des unités de dialogue , plutôt que des pixels. Une "unité de dialogue" est définie pour que le caractère moyen de la police soit
Delphi est livré avec une notion (boguée) de
Scaled
, où un formulaire essaie de s'ajuster automatiquement en fonction duCela ne résout pas le problème lorsque l'utilisateur utilise une police différente de celle avec laquelle vous avez conçu le formulaire, par exemple:
6.21px x 13.00px
, à 96 dpi)utilisateur fonctionnant avec Tahoma 8pt (où le caractère moyen est
5.94px x 13.00px
, à 96 dpi)Comme pour toute personne développant une application pour Windows 2000 ou Windows XP.
ou
5.94px x 13.00px
, à 96 dpi)6.67px x 15px
, à 96 dpi)En tant que bon développeur, vous allez respecter les préférences de police de votre utilisateur. Cela signifie que vous devez également mettre à l'échelle tous les contrôles de votre formulaire pour qu'ils correspondent à la nouvelle taille de police:
Scaled
ne gérera pas cela pour vous.Cela empire quand:
10.52px x 25px
Maintenant, vous devez tout mettre à l'échelle
Scaled
ne gérera pas cela pour vous.Si vous êtes intelligent, vous pouvez voir à quel point honorer DPI n'est pas pertinent:
Vous ne devriez pas regarder le paramètre DPI de l'utilisateur, vous devriez regarder sa taille de police . Deux utilisateurs en cours d'exécution
exécutent la même police . Le DPI n'est qu'une chose qui affecte la taille de la police; les préférences de l'utilisateur sont les autres.
StandardizeFormFont
Clovis a remarqué que je fais référence à une fonction
StandardizeFormFont
qui corrige la police sur un formulaire et l'adapte à la nouvelle taille de police. Ce n'est pas une fonction standard, mais un ensemble complet de fonctions qui accomplissent la tâche simple que Borland n'a jamais traitée.Windows a 6 polices différentes; il n'y a pas de "réglage de police" unique dans Windows.
Mais nous savons par expérience que nos formulaires doivent suivre le paramètre Police du titre de l' icône
Une fois que nous connaissons la taille de la police à laquelle nous allons mettre le formulaire à l'échelle , nous obtenons la hauteur de police actuelle du formulaire ( en pixels ) et augmentons l'échelle de ce facteur.
Par exemple, si je configure le formulaire sur
-16
et que le formulaire est actuellement à-11
, nous devons mettre à l'échelle le formulaire entier en:La normalisation se déroule en deux phases. Mettez d'abord le formulaire à l'échelle en fonction du rapport entre la nouvelle et l'ancienne taille de police. Modifiez ensuite les contrôles (récursivement) pour utiliser la nouvelle police.
Voici le travail de mise à l'échelle d'un formulaire. Cela fonctionne autour des bogues dans la propre
Form.ScaleBy
méthode de Borland . Il doit d'abord désactiver toutes les ancres du formulaire, puis effectuer la mise à l'échelle, puis réactiver les ancres:et nous devons récursive réellement utiliser la nouvelle police:
Les ancres étant désactivées de manière récursive:
Et les ancres étant réactivées de manière récursive:
Avec le travail de changer réellement une police de contrôle à gauche pour:
C'est beaucoup plus de code que vous ne le pensiez; je connais. Le plus triste, c'est qu'il n'y a pas de développeur Delphi sur terre, à part moi, qui corrige réellement leurs applications.
la source
Voici mon cadeau. Une fonction qui peut vous aider avec le positionnement horizontal des éléments dans vos mises en page GUI. Gratuit pour tous.
la source