Tous les ContainerControls doivent être définis sur le même AutoScaleMode = Font
. (La police gérera à la fois les modifications PPP et les modifications apportées au paramètre de taille de police système; DPI ne gérera que les modifications DPI, pas les modifications apportées au paramètre de taille de police système.)
Tous les ContainerControls doivent également être définis avec le même AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
, en supposant 96 dpi (voir la puce suivante) et la police par défaut de MS Sans Serif (voir la puce deux vers le bas). Cela est ajouté automatiquement par le concepteur en fonction du DPI dans lequel vous ouvrez le concepteur ... mais il manquait dans beaucoup de nos fichiers de concepteur les plus anciens. Peut-être que Visual Studio .NET (la version antérieure à VS 2005) n'ajoutait pas cela correctement.
Faites tout votre travail de concepteur en 96 dpi (nous pourrions peut-être passer à 120 dpi; mais la sagesse sur Internet dit de s'en tenir à 96 dpi; l'expérimentation est en ordre là-bas; de par la conception, cela ne devrait pas avoir d'importance car cela change simplement la AutoScaleDimensions
ligne qui le concepteur insère). Pour définir Visual Studio pour qu'il s'exécute à un 96 dpi virtuel sur un affichage haute résolution, recherchez son fichier .exe, cliquez avec le bouton droit pour modifier les propriétés et sous Compatibilité, sélectionnez «Remplacer le comportement de mise à l'échelle DPI élevé. Mise à l'échelle effectuée par: Système».
Assurez-vous de ne jamais définir la police au niveau du conteneur ... uniquement sur les contrôles feuille OU dans le constructeur de votre formulaire le plus basique si vous voulez une police par défaut à l'échelle de l'application autre que MS Sans Serif. (La définition de la police sur un conteneur semble désactiver la mise à l'échelle automatique de ce conteneur car elle vient par ordre alphabétique après la définition des paramètres AutoScaleMode et AutoScaleDimensions.) Notez que si vous modifiez la police dans le constructeur de votre formulaire le plus vos AutoScaleDimensions pour calculer différemment de 6x13; en particulier, si vous passez à Segoe UI (la police par défaut de Win 10), alors ce sera 7x15 ... vous devrez toucher chaque formulaire dans le concepteur afin qu'il puisse recalculer toutes les dimensions de ce fichier .designer, y compris le AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
.
N'utilisez PAS Anchor Right
ou Bottom
ancré à un UserControl ... son positionnement ne s'échelonnera pas automatiquement; à la place, déposez un Panel ou un autre conteneur dans votre UserControl et ancrez vos autres Contrôles à ce Panel; ont l'utilisation Panneau Dock Right
, Bottom
ou Fill
dans votre UserControl.
Seuls les contrôles dans les listes de contrôles lorsque ResumeLayout
à la fin de InitializeComponent
est appelé seront mis à l'échelle automatiquement ... si vous ajoutez des contrôles de manière dynamique, vous devez SuspendLayout();
AutoScaleDimensions = new SizeF(6F, 13F);
AutoScaleMode = AutoScaleMode.Font;
ResumeLayout();
sur ce contrôle avant de l'ajouter. Et votre positionnement devra également être ajusté si vous n'utilisez pas les modes Dock ou un gestionnaire de mise en page comme FlowLayoutPanel
ou TableLayoutPanel
.
Classes de base dérivées de ContainerControl
doivent abandonner AutoScaleMode
fixé à Inherit
(l'ensemble de la valeur par défaut dans la classe ContainerControl
, mais pas le jeu par défaut par le concepteur). Si vous le définissez sur autre chose et que votre classe dérivée essaie de le définir sur Font (comme il se doit), le fait de le définir Font
effacera le paramètre du concepteur AutoScaleDimensions
, ce qui entraînera la désactivation de la mise à l'échelle automatique! (Cette directive combinée avec la précédente signifie que vous ne pouvez jamais instancier des classes de base dans un concepteur ... toutes les classes doivent être conçues comme des classes de base ou comme des classes feuilles!)
Évitez d'utiliser de Form.MaxSize
manière statique / dans le Designer. MinSize
et MaxSize
sur la forme ne s'adaptent pas autant que tout le reste. Donc, si vous effectuez tout votre travail en 96 dpi, lorsque vous utilisez un DPI plus élevé, vous ne causerez MinSize
pas de problèmes, mais vous ne serez peut-être pas aussi restrictif que prévu, mais vous MaxSize
risquez de limiter la mise à l'échelle de votre taille, ce qui peut causer des problèmes. Si vous le souhaitez MinSize == Size == MaxSize
, ne le faites pas dans le concepteur ... faites cela dans votre constructeur ou OnLoad
remplacez ... définissez les deux MinSize
et MaxSize
sur votre taille correctement mise à l'échelle.
Tous les contrôles sur un particulier Panel
ou Container
devraient utiliser l'ancrage ou l'ancrage. Si vous les mélangez, la mise à l'échelle automatique effectuée par cela Panel
se comportera souvent mal de manière subtile et bizarre.
Lorsqu'il effectue sa mise à l'échelle automatique, il essaiera de mettre à l'échelle le formulaire global ... cependant, si dans ce processus il se heurte à la limite supérieure de la taille de l'écran, c'est une limite stricte qui peut alors visser (clip) la mise à l'échelle. Par conséquent, vous devez vous assurer que tous les formulaires dans le concepteur à 100% / 96 dpi ne sont pas dimensionnés plus grand que 1024x720 (ce qui correspond à 150% sur un écran 1080p ou 300% qui est la valeur recommandée par Windows sur un écran 4K). Mais vous devez soustraire la barre de titre / légende de Win10 géante ... donc plus comme 1000x680 Max Size ... qui dans le concepteur sera comme 994x642 ClientSize. (Ainsi, vous pouvez faire un FindAll References sur ClientSize pour trouver les contrevenants.)
NumericUpDown
ne met pas saMargin
correctement, aussi. Il semble que la marge soit redimensionnée deux fois. Si je le réduis une fois, ça a l'air bien.AutoScaleMode = Font
ne fonctionne pas bien pour les utilisateurs qui utilisent une très grande police et avec sur Ubuntu. Nous préféronsAutoScaleMode = DPI
Mon expérience a été assez différente de la réponse actuelle aux votes les plus élevés. En parcourant le code du framework .NET et en parcourant le code source de référence, j'ai conclu que tout était en place pour que la mise à l'échelle automatique fonctionne, et qu'il n'y avait qu'un problème subtil quelque part qui le gâchait. Cela s'est avéré être vrai.
Si vous créez une mise en page correctement redimensionnable / auto-dimensionnée, alors presque tout fonctionne exactement comme il se doit, automatiquement, avec les paramètres par défaut utilisés par Visual Studio (à savoir, AutoSizeMode = Font sur le formulaire parent et Inherit sur tout le reste).
Le seul problème est si vous avez défini la propriété Font sur le formulaire dans le concepteur. Le code généré triera les affectations par ordre alphabétique, ce qui signifie qu'elles
AutoScaleDimensions
seront affectées avantFont
. Malheureusement, cela rompt complètement la logique de mise à l'échelle automatique de WinForms.Le correctif est simple cependant. Soit ne définissez pas du tout la
Font
propriété dans le concepteur (définissez-la dans votre constructeur de formulaire), soit réorganisez manuellement ces affectations (mais vous devez continuer à le faire chaque fois que vous modifiez le formulaire dans le concepteur). Voila, mise à l'échelle presque parfaite et entièrement automatique avec un minimum de tracas. Même les tailles de formulaire sont correctement mises à l'échelle.Je vais énumérer les problèmes connus ici au fur et à mesure que je les rencontre:
TableLayoutPanel
calcule pas correctement les marges de contrôle . Aucune solution connue à moins d'éviter complètement les marges et les rembourrages - ou d'éviter les panneaux de disposition de tableau imbriqués.la source
Font
dans le concepteur: Une pensée me vient à l'esprit: allez-y et définissez la police dans le concepteur, afin que vous puissiez concevoir avec la police souhaitée. ALORS dans le constructeur, après la mise en page, lire cette propriété de police et redéfinir la même valeur? Ou peut-être simplement demander à nouveau la mise en page? [ Mise en garde : je n'ai pas eu de raison de tester cette approche.] Ou selon la réponse de Knowleech , dans le concepteur, spécifiez en pixels (afin que le concepteur Visual Studio ne soit pas redimensionné sur un moniteur à haute résolution), et dans le code, lisez cette valeur, convertissez à partir de pixels aux points (pour obtenir une mise à l'échelle correcte).AutoScaleDimensions
n'était pas défini surnew SizeF(6F, 13F)
comme recommandé dans la première réponse. Il s'est avéré que dans tous les cas, la propriété Font du formulaire avait été définie (pas par défaut). Il semble que quandAutoScaleMode = Font
, alorsAutoScaleDimensions
est calculé en fonction de la propriété de police du formulaire. En outre, le paramètre de mise à l' échelle dans le panneau de configuration de Windows semble avoir un effet surAutoScaleDimensions
.Ciblez votre application pour .Net Framework 4.7 et exécutez-la sous Windows 10 v1703 (Creators Update Build 15063). Avec .Net 4.7 sous Windows 10 (v1703), MS a apporté de nombreuses améliorations DPI .
Pour le prendre en charge, ajoutez un manifeste d'application à votre application et signalez que votre application prend en charge Windows 10:
Ensuite, ajoutez un
app.config
et déclarez l'application Per Monitor Aware. Cela se fait MAINTENANT dans app.config et PAS dans le manifeste comme avant!Ce PerMonitorV2 est nouveau depuis la mise à jour Windows 10 Creators:
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
Vous pouvez désormais vous abonner à 3 nouveaux événements pour être averti des modifications DPI:
Vous disposez également de 3 méthodes d'assistance sur la gestion / mise à l'échelle DPI:
Control.LogicalToDeviceUnits , qui convertit une valeur de pixels logiques en pixels de périphérique.
Control.ScaleBitmapLogicalToDevice , qui met à l'échelle une image bitmap au DPI logique d'un périphérique.
Control.DeviceDpi , qui renvoie le DPI pour le périphérique actuel.
Si des problèmes persistent, vous pouvez désactiver les améliorations DPI via les entrées app.config .
Si vous n'avez pas accès au code source, vous pouvez accéder aux propriétés de l'application dans l'Explorateur Windows, accéder à la compatibilité et sélectionner
System (Enhanced)
qui active la mise à l'échelle GDI pour améliorer également la gestion DPI:
Suivez toutes ces étapes et vous devriez obtenir une meilleure expérience DPI pour les applications WinForms. Mais rappelez-vous, vous devez cibler votre application pour .net 4.7 et au moins Windows 10 Build 15063 (Creators Update). Dans la prochaine mise à jour 1709 de Windows 10, nous pourrions obtenir d'autres améliorations.
la source
Un guide que j'ai écrit au travail:
la source
J'ai trouvé très difficile d'obtenir WinForms pour jouer correctement avec un DPI élevé. Donc, j'ai écrit une méthode VB.NET pour remplacer le comportement du formulaire:
la source
Je suis récemment tombé sur ce problème, en particulier en combinaison avec le redimensionnement de Visual Studio lorsque l'éditeur est ouvert sur un système à haute résolution. Je l' ai trouvé mieux pour garder
AutoScaleMode = Font
, mais pour définir les formes de police à la police par défaut, mais en spécifiant la taille en pixels , pas le point, à savoir:Font = MS Sans; 11px
. Dans le code, je réinitialise ensuite la police par défaut:Font = SystemFonts.DefaultFont
et tout va bien.Juste mes deux cents. Je pensais partager, car «garder AutoScaleMode = Font» et «Définir la taille de la police en pixel pour le Designer» était quelque chose que je n'ai pas trouvé sur Internet.
J'ai quelques détails supplémentaires sur mon blog: http://www.sgrottel.de/?p=1581&lang=en
la source
En plus des ancres qui ne fonctionnent pas très bien: j'irais plus loin et je dirais que le positionnement exact (c'est-à-dire en utilisant la propriété Location) ne fonctionne pas très bien avec la mise à l'échelle de la police. J'ai dû aborder ce problème dans deux projets différents. Dans les deux, nous avons dû convertir le positionnement de tous les contrôles WinForms en utilisant TableLayoutPanel et FlowLayoutPanel. L'utilisation de la propriété Dock (généralement définie sur Fill) dans le TableLayoutPanel fonctionne très bien et s'adapte parfaitement à la police système DPI.
la source