J'ai une demande de formulaire en C #. Lorsque je modifie le DPI du moniteur, tous les contrôles se déplacent. J'ai utilisé le code this.AutoScaleMode = AutoScaleMode.Dpi
, mais cela n'a pas évité le problème.
Est-ce que quelqu'un a une idée?
EDIT: Depuis .NET 4.7, Windows Forms a amélioré la prise en charge de High DPI. En savoir plus à ce sujet sur docs.Microsoft.com Cela ne fonctionne que pour Win 10 Creators Update et supérieur, il n'est donc pas encore possible de l'utiliser en fonction de votre base d'utilisateurs.
Difficile, mais pas impossible. Votre meilleure option est de passer à WPF bien sûr, mais cela pourrait ne pas être faisable.
J'ai passé BEAUCOUP de temps avec ce problème. Voici quelques règles/directives pour le faire fonctionner correctement sans FlowLayoutPanel ou TableLayoutPanel:
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); // for design in 96 DPI
Je vous garantis que si vous suivez ces directives, vous serez d'accord, même si vous avez placé des contrôles avec des ancres spécifiques et n'utilisez pas de panneau de flux. Nous avons une application construite de cette façon déployée sur des centaines de machines avec différentes configurations DPI et nous n'avons plus de plaintes. Tous les formulaires/conteneurs/grilles/boutons/champs de texte, etc. sont mis à l'échelle correctement, tout comme la police. Les images fonctionnent également, mais elles ont tendance à être un peu pixellisées à haute résolution.
EDIT: Ce lien a beaucoup de bonnes informations, surtout si vous choisissez d'utiliser AutoScaleMode.DPI: lien vers la question de stackoverflow associée
J'ai finalement trouvé une solution au problème de l'orientation de l'écran et de la gestion DPI.
Microsoft a déjà fourni un document l'expliquant mais avec une petite faille qui tuera complètement la gestion DPI. Suivez simplement la solution fournie dans le document ci-dessous sous "Création d'un code de mise en page distinct pour chaque orientation" http://msdn.Microsoft.com/en-us/library/ms838174.aspx
Alors partie IMPORTANTE! À l'intérieur du code pour les méthodes Paysage () et Portrait () à la fin de chacune, ajoutez ces lignes:
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
Ainsi, le code de ces 2 méthodes serait comme:
protected void Portrait()
{
this.SuspendLayout();
this.crawlTime.Location = new System.Drawing.Point(88, 216);
this.crawlTime.Size = new System.Drawing.Size(136, 16);
this.crawlTimeLabel.Location = new System.Drawing.Point(10, 216);
this.crawlTimeLabel.Size = new System.Drawing.Size(64, 16);
this.crawlStartTime.Location = new System.Drawing.Point(88, 200);
this.crawlStartTime.Size = new System.Drawing.Size(136, 16);
this.crawlStartedLabel.Location = new System.Drawing.Point(10, 200);
this.crawlStartedLabel.Size = new System.Drawing.Size(64, 16);
this.light1.Location = new System.Drawing.Point(208, 66);
this.light1.Size = new System.Drawing.Size(16, 16);
this.light0.Location = new System.Drawing.Point(192, 66);
this.light0.Size = new System.Drawing.Size(16, 16);
this.linkCount.Location = new System.Drawing.Point(88, 182);
this.linkCount.Size = new System.Drawing.Size(136, 16);
this.linkCountLabel.Location = new System.Drawing.Point(10, 182);
this.linkCountLabel.Size = new System.Drawing.Size(64, 16);
this.currentPageBox.Location = new System.Drawing.Point(10, 84);
this.currentPageBox.Size = new System.Drawing.Size(214, 90);
this.currentPageLabel.Location = new System.Drawing.Point(10, 68);
this.currentPageLabel.Size = new System.Drawing.Size(100, 16);
this.addressLabel.Location = new System.Drawing.Point(10, 4);
this.addressLabel.Size = new System.Drawing.Size(214, 16);
this.noProxyCheck.Location = new System.Drawing.Point(10, 48);
this.noProxyCheck.Size = new System.Drawing.Size(214, 20);
this.startButton.Location = new System.Drawing.Point(8, 240);
this.startButton.Size = new System.Drawing.Size(216, 20);
this.addressBox.Location = new System.Drawing.Point(10, 24);
this.addressBox.Size = new System.Drawing.Size(214, 22);
//note! USING JUST AUTOSCALEMODE WILL NOT SOLVE ISSUE. MUST USE BOTH!
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); //IMPORTANT
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; //IMPORTANT
this.ResumeLayout(false);
}
protected void Landscape()
{
this.SuspendLayout();
this.crawlTime.Location = new System.Drawing.Point(216, 136);
this.crawlTime.Size = new System.Drawing.Size(96, 16);
this.crawlTimeLabel.Location = new System.Drawing.Point(160, 136);
this.crawlTimeLabel.Size = new System.Drawing.Size(48, 16);
this.crawlStartTime.Location = new System.Drawing.Point(64, 120);
this.crawlStartTime.Size = new System.Drawing.Size(248, 16);
this.crawlStartedLabel.Location = new System.Drawing.Point(8, 120);
this.crawlStartedLabel.Size = new System.Drawing.Size(48, 16);
this.light1.Location = new System.Drawing.Point(296, 48);
this.light1.Size = new System.Drawing.Size(16, 16);
this.light0.Location = new System.Drawing.Point(280, 48);
this.light0.Size = new System.Drawing.Size(16, 16);
this.linkCount.Location = new System.Drawing.Point(80, 136);
this.linkCount.Size = new System.Drawing.Size(72, 16);
this.linkCountLabel.Location = new System.Drawing.Point(8, 136);
this.linkCountLabel.Size = new System.Drawing.Size(64, 16);
this.currentPageBox.Location = new System.Drawing.Point(10, 64);
this.currentPageBox.Size = new System.Drawing.Size(302, 48);
this.currentPageLabel.Location = new System.Drawing.Point(10, 48);
this.currentPageLabel.Size = new System.Drawing.Size(100, 16);
this.addressLabel.Location = new System.Drawing.Point(10, 4);
this.addressLabel.Size = new System.Drawing.Size(50, 16);
this.noProxyCheck.Location = new System.Drawing.Point(168, 16);
this.noProxyCheck.Size = new System.Drawing.Size(152, 24);
this.startButton.Location = new System.Drawing.Point(8, 160);
this.startButton.Size = new System.Drawing.Size(304, 20);
this.addressBox.Location = new System.Drawing.Point(10, 20);
this.addressBox.Size = new System.Drawing.Size(150, 22);
//note! USING JUST AUTOSCALEMODE WILL NOT SOLVE ISSUE. MUST USE BOTH!
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); //IMPORTANT
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; //IMPORTANT
this.ResumeLayout(false);
}
Fonctionne comme un charme pour moi.
note: cela ne résoudra pas le déplacement des commandes, lorsque le dpi change. cela ne corrigera que le texte flou !!.
Comment corriger les formulaires Windows flous dans les paramètres haute résolution:
Maintenant, allez dans Program.cs (ou le fichier où se trouve votre méthode Main) et changez-le pour ressembler à:
namespace myApplication
{
static class Program
{
[STAThread]
static void Main()
{
// ***this line is added***
if (Environment.OSVersion.Version.Major >= 6)
SetProcessDPIAware();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
// ***also dllimport of that function***
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
}
}
Enregistrez et compilez. Maintenant, votre formulaire devrait à nouveau être croustillant.
source: http://crsouza.com/2015/04/13/how-to-fix-blurry-windows-forms-windows-in-high-dpi-settings/
Il semble que ce soit un problème avec Windows. La suppression de ces deux lignes a tout réparé.
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
C'est là que j'ai obtenu la solution:
Il est vraiment difficile de concevoir des applications prenant en charge DPI dans Windows Forms. Vous devez utiliser des conteneurs de disposition qui redimensionnent correctement lorsque le DPI est modifié (tel que TableLayoutPanel ou FlowLayoutPanel). Tous les contrôles doivent également être redimensionnés. La configuration de ces conteneurs peut être un défi.
Pour les applications simples, cela peut être fait dans un délai raisonnable, mais pour les grandes applications, c'est vraiment beaucoup de travail.
De l'expérience:
AutoScaleMode
sur None
sur tous les formulaires et contrôles utilisateur de votre application.La fonction ScaleByDPI recevra un paramètre de contrôle qui est généralement un formulaire, puis itérera récursivement à travers tous les sous-contrôles (si (control.HasChildren == true)), et mettra à l'échelle l'emplacement et les tailles de vos contrôles d'application et les tailles et tailles de polices vers le DPI configuré par le système d'exploitation. Vous pouvez essayer de l'implémenter également pour les images, les icônes et les graphiques.
Notes spéciales pour la fonction ScaleByDPI:
une. Pour tous les contrôles avec des tailles de police par défaut, vous devrez définir leur Font.Size sur 8.25.
b. Vous pouvez obtenir les valeurs devicePixelRatioX et devicePixelRatioY par (control.CreateGraphics (). DpiX/96) et (control.CreateGraphics (). DpiY/96).
c. Vous aurez besoin de l'échelle Control.Size & Control.Location par algorithme basé sur les valeurs control.Dock & control.Anchor. Notez que control.Dock peut avoir 1 sur 6 valeurs possibles et que control.Anchor peut avoir 1 sur 16 valeurs possibles.
ré. cet algorithme devra définir des valeurs pour les variables booléennes suivantes: isDoSizeWidth, isDoSizeHeight, isDoLocationX, isDoLocationY, isDoRefactorSizeWidth, isDoRefactorSizeHeight, isDoRefactorLocationX, isDoRefactorLocationY, isDoClacLocationXBasedOnACOnOnOB.
e. Si votre projet utilise une bibliothèque de contrôles autre que les contrôles Microsoft, ces contrôles peuvent nécessiter un traitement spécial.
Plus d'informations sur les variables booléennes ci-dessus (d.):
* Parfois, un groupe de contrôles (peut-être des boutons) doivent être placés l'un après l'autre sur la même ligne verticale, et leur valeur d'ancrage inclut Droite mais pas Gauche, ou ils doivent être placés l'un après l'autre sur la même ligne horizontale, et leur La valeur d'ancrage inclut Bas mais pas Haut, dans ce cas, vous devez recalculer les valeurs d'emplacement des contrôles.
* Dans le cas des contrôles dont Anchor contient Top & Bottom et\ou Left & Right, vous aurez besoin de re-factoriser les contrôles Taille et emplacement.
Utilisations de la fonction ScaleByDPI:
une. Ajoutez la commande suivante à la fin de tout constructeur de formulaire: ScaleByDPI (this);
b. Également lors de l'ajout dynamique d'un contrôle à un appel de formulaire à ScaleByDPI ([ControlName]).
Lorsque vous définissez dynamiquement la taille ou l'emplacement d'un contrôle après la fin du constructeur, créez et utilisez l'une des fonctions suivantes afin d'obtenir les valeurs mises à l'échelle de la taille ou de l'emplacement: ScaleByDPI_X\ScaleByDPI_Y\ScaleByDPI_Size\ScaleByDPI_Point
Afin de marquer votre application comme étant compatible DPI, ajoutez l'élément dpiAware au manifeste d'assembly de votre application.
Définissez GraphicsUnit de tous Control.Font sur System.Drawing.GraphicsUnit.Point
Dans les fichiers * .Designer.cs de tous les conteneurs, définissez la valeur AutoScaleMode sur System.Windows.Forms.AutoScaleMode.None
dans les contrôles comme ComboBox et TextBox, la modification de Control.Size.Hieght n'a aucun effet. Dans ce cas, changer Control.Font.Size fixera la hauteur du contrôle.
Si la valeur du formulaire StartPosition est FormStartPosition.CenterScreen, vous devrez recalculer l'emplacement de la fenêtre.