44 votes

Mise à l'échelle de la zone non client (barre de titre, barre de menus) pour la prise en charge haute résolution par moniteur

Windows 8.1 a introduit la possibilité d'avoir différents paramètres PPP pour les différents moniteurs. Cette fonctionnalité est appelée "par-moniteur de haute résolution d'appui." Il persiste et a été raffiné dans Windows 10.

Si une demande n'est pas opt-in (c'est à dire, est soit DPI n'est pas au courant ou haute résolution au courant), il sera automatiquement mis à l'échelle par DWM pour la bonne DPI. La plupart des applications de l'automne dans l'une de ces deux catégories, y compris la plupart des utilitaires fournis avec Windows (par exemple, le bloc-notes). Sur mon système de test, la haute résolution du moniteur est réglée à 150% de l'échelle (144 DPI), tandis que le moniteur normal est défini pour le système de DPI (sur une échelle de 100%, de 96 PPP). Par conséquent, lorsque vous ouvrez l'une de ces applications sur la haute résolution de l'écran (ou faites-la glisser là-bas), la virtualisation des coups de pied dans, loupe tout, mais aussi ce qui la rend incroyablement floue.

Sur l'autre main, si une application indique explicitement qu'il prend en charge par le moniteur de haute résolution, alors pas de virtualisation est effectuée et que le développeur est responsable de la mise à l'échelle. Microsoft a une explication assez complète ici*, mais pour le bénéfice d'une auto-contenue question, je vais résumer. Tout d'abord, vous indiquer la prise en charge par le paramètre <dpiAware>True/PM</dpiAware> dans le manifeste. Cette opte vous en recevant WM_DPICHANGED messages, qui vous indique à la fois le nouveau réglage DPI et d'une proposition de nouveau la taille et la position de votre fenêtre. Il vous permet également d'appeler le GetDpiForMonitor fonction et d'obtenir la réelle DPI, sans être menti pour des raisons de compatibilité. Kenny Kerr a également écrit un didacticiel complet.

J'ai obtenu tout ce passe à merveille dans un peu de C++ application de test. Il ya beaucoup de passe-partout et la plupart du temps les paramètres du projet, donc je ne vois pas beaucoup de point en publiant un exemple complet d'ici. Si vous voulez le tester, soit de suivre Kenny instructions de ce tutoriel sur la MSDN, ou télécharger le SDK officiel de l'échantillon. Maintenant, le texte dans la zone client semble bon (à cause de mon traitement de WM_DPICHANGED), mais parce que la virtualisation n'est plus assurée, il n'y a pas de mise à l'échelle de la zone non client. Le résultat est que le titre/la barre de légende et de la barre de menus sont de la bonne taille, ils ne sont plus sur la haute résolution de l'écran:

La question est donc, comment puis-je obtenir la non-zone client de la fenêtre à l'échelle de la nouvelle DPI?
Il n'a pas d'importance si vous créez votre propre classe de fenêtre ou utiliser une boîte de dialogue-ils ont un comportement identique à cet égard.

Il a été suggéré qu'il n'y est pas de réponse-que votre seul choix est de coutume de dessiner l'ensemble de la fenêtre, y compris les non-clients de la zone. Tout cela est certainement possible, et en effet ce UWP applications (celles précédemment connu sous le Métro), comme le Windows 10 Calculatrice, ce n'est pas une option viable pour les applications de bureau qui utilisent beaucoup de non-client de widgets et de l'espoir à regarder natif.

A côté de cela, il est manifestement fausse. Personnalisé tiré les barres de titre ne peut être la seule façon d'obtenir le bon comportement, depuis l'environnement Windows, qui équipe l'a fait. L'humble boîte de dialogue Exécuter, se comporte exactement comme prévu, correctement redimensionnement à la fois les clients et non-clients, comme vous le faites-le glisser entre les moniteurs avec différents inhalateurs de poudre sèche:

Enquête avec Spy++ confirme c'est juste une méga-standard Win32 dialogue-rien de compliqué. Tous les contrôles sont standard kit de développement Win32 SDK contrôles. Ce n'est pas un UWP application, ni ont-ils coutume dessinés à la barre de titre-qu'il a toujours le WS_CAPTION style. Elle est lancée par l'explorer.exe processus, qui est marqué par le moniteur de haute résolution conscient (vérifié avec l'Explorateur de Processus et GetProcessDpiAwareness). Ce blog confirme que les deux la boîte de dialogue Exécuter et l'Invite de Commande ont été réécrits dans Windows 10 à l'échelle correctement (voir "interfaces de Commande et al."). Qu'est-ce que la boîte de dialogue Exécuter le faire pour redimensionner la barre de titre?

La Commune de Dialogue de l'Élément de l'API, responsable de de nouveaux Ouvrir et Enregistrer des boîtes de dialogue, s'adapte correctement lors du lancement d'un processus qui est par-moniteur de haute résolution conscient, comme vous pouvez le voir en cliquant sur le bouton "Parcourir" dans la boîte de dialogue Exécuter. Même chose pour la boîte de Dialogue de Tâche de l'API, de la création de l'étrange situation où une application lance une boîte de dialogue avec un autre-taille de la barre de titre. (L'héritage de l'API MessageBox n'a pas été mis à jour, cependant, et présente le même comportement que mon test app.)

Si la coque de l'équipe est de le faire, il doit être possible. Je ne peux pas imaginer que l'équipe responsable de la conception/mise en œuvre par le moniteur de DPI soutien négligé de fournir un moyen raisonnable pour les développeurs à produire des applications compatibles. Cela nécessite le support de développeur, ou qu'ils soient cassés out-of-the-box. Même les applications WPF sont brisés de Microsoft Par le Moniteur de Courant WPF Exemple de projet ne parvient pas à l'échelle de la zone non client, résultant dans une barre de titre qui est la bonne taille. Je ne suis pas beaucoup de théories du complot, mais ça sent un marketing déplacer pour décourager bureau de développement d'applications. Si oui, et il n'y a pas de manière officielle, je vais accepter les réponses qui s'appuient sur les sans-papiers comportement.

En parlant de sans-papiers, le comportement, la journalisation des messages de fenêtre lorsque la boîte de dialogue Exécuter est glissé entre les moniteurs avec différents paramètres PPP montre qu'il reçoit un sans-papiers message, 0x02E1. C'est assez intéressant parce que ce message ID est exactement un de plus que le documentée WM_DPICHANGED message (0x02E0). Mon appli de test n'est jamais ce message, bien que, quel que soit son DPI-sensibilisation des paramètres. (Curieusement, à proximité de l'inspection révèle que Windows légèrement augmente la taille de la réduire/agrandir/fermer les glyphes sur la barre de titre de la fenêtre se déplace sur la haute résolution moniteur. Ils ne sont pas encore aussi grand que ils sont, quand ils sont virtualisés, mais ils sont un peu plus grands que les glyphes qu'il utilise pour la non mis à l'échelle du système des DPI applications).

Jusqu'à présent, mon idée a été de gérer l' WM_NCCALCSIZE message pour ajuster la taille de la zone non client. En utilisant l' SWP_FRAMECHANGED drapeau avec l' SetWindowPos de la fonction, je peux forcer la fenêtre de redimensionner et de les redessiner sa non-espace client en réponse à l' WM_DPICHANGED. Cela fonctionne bien pour réduire la hauteur de la barre de titre, ou même le supprimer tout à fait, mais il ne le fera jamais plus grand. La légende semble de pointe à la hauteur déterminée par le système de DPI. Même si elle a travaillé, ce ne serait pas la solution idéale, car il ne serait pas aider avec le système dessinés à la barre de menus ou barres de défilement...mais au moins, ça serait un début. D'autres idées?

* Je sais que cet article dit "on Remarque que la zone non client de l'une par moniteur–PPP au courant de l'application n'est pas mis à l'échelle par Windows, et apparaît proportionnellement plus petits sur une haute résolution d'affichage." Voir ci-dessus pour expliquer pourquoi c'est (1) mauvais et (2) insatisfaisant. Je suis à la recherche d'une solution autre que la coutume de dessin de la zone non client.

27voto

peterfelts Points 427

Dans tous les up-to-date de Windows Insider construit (version >= 14342, version du SDK# >= 14332) il y a un EnableNonClientDpiScaling API (qui prend un HWND comme argument) qui va permettre à des non-client DPI pour haut-niveau Hwnd. Cette fonctionnalité nécessite que le niveau supérieur de la fenêtre de l'être en cours d'exécution dans le moniteur DPI-sensibilisation à la mode. Cette API doit être appelée à partir de la WM_NCCREATE gestionnaire de fenêtre. Lors de cette API est appelée sur une fenêtre de niveau supérieur, la barre de légende, de niveau supérieur, les barres de défilement, le système de menu et de la barre de menu sera DPI à l'échelle lors de l'application du DPI changements (cela peut se produire lorsque l'application est déplacé vers un écran avec un affichage de l'échelle de valeur ou lors de la résolution des changements pour d'autres raisons telles que l'utilisateur a effectué une modification des paramètres ou lorsqu'une connexion RDP modifications du facteur d'échelle).

Cette API ne prend pas en charge le changement d'échelle non-espace client pour enfant de windows, tels que les barres de défilement dans une fenêtre enfant.

À ma connaissance, il n'existe aucun moyen d'avoir un non-client de la zone de DPI à l'échelle automatiquement sans cette API.

Notez que cette API n'a pas encore été finalisé, et il peut être modifiée avant d'être libéré dans le Windows 10 Anniversaire de mise à jour. Gardez un oeil sur MSDN pour la documentation officielle, lorsqu'elle devient définitive.

12voto

Martin Prikryl Points 4584

Avec Par Moniteur V2 DPI de sensibilisation dans Windows 10 Créateurs de mise à Jour (version 15063) vous pouvez résoudre ce problème facilement, sans l' EnableNonClientDpiScaling.

Pour activer Par Moniteur V2 DPI prise de conscience, tout en continuant à soutenir vieux Pour Surveiller les DPI de sensibilisation sur les anciens Windows 10 s'appuie et Windows 8.1 et DPI de sensibilisation sur encore les anciennes versions de Windows, faites votre demande manifeste comme ceci:

<assembly ...>
    <!-- ... --->
    <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <dpiAware>True/PM</dpiAware>
            <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
        </asmv3:windowsSettings>
    </asmv3:application>
</assembly>

Références:

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X