Bir uygulama, yüksek DPI ayarına sahip bir makinede (örneğin% 150) doğru çalışacak şekilde nasıl yapılandırılır?


104

C # ile basit bir Winforms uygulaması oluşturdum. Uygulamayı yüksek DPI ayarlarına sahip bir makinede çalıştırdığımda (örneğin% 150), uygulamanın ölçeği büyütülüyor. Çok uzak çok iyi! Ancak yazı tiplerini daha yüksek bir yazı tipi boyutunda oluşturmak yerine, tüm metinler de sadece büyütülür. Bu, elbette çok bulanık metne yol açar (düğmeler vb. Tüm kontrollerde).

Pencereler metinleri doğru şekilde oluşturmamalı mı? Örneğin, uygulamamın başlık çubuğu net ve net bir şekilde görüntüleniyor.

Yanıtlar:


132

% 100'ü (veya "XP tarzı DPI ölçeklendirme" onay kutusu işaretlenmiş olarak% 125'i) geçtiğinizde, Windows varsayılan olarak kullanıcı arabiriminizin ölçeklendirmesini üstlenir. Bunu, uygulamanızın çıktısını bir bitmap'e dönüştürmesini ve bu bitmap'i ekrana çizmesini sağlayarak yapar. Bu bitmap'in yeniden ölçeklendirilmesi, metnin kaçınılmaz olarak bulanık görünmesine neden olur. "DPI sanallaştırma" adı verilen bir özellik, eski programları yüksek çözünürlüklü monitörlerde kullanılabilir durumda tutar.

<dpiAware>Öğeyi bildiriminize ekleyerek daha yüksek DPI ayarlarını kullanabileceğinizi açıkça belirtmeniz gerekir. MSDN sayfası buradadır, ancak UAC ayarlarını ihmal ettiği için tamamlanmamıştır. Proje + Yeni Öğe Ekle, "Uygulama Manifest Dosyası" nı seçin. Manifest metnini düzenleyin veya bunu kopyalayın / yapıştırın:

<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
    <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                <requestedExecutionLevel level="asInvoker" uiAccess="false" />
            </requestedPrivileges>
        </security>
    </trustInfo>
    <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <dpiAware>true</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>
</assembly>

Ayrıca, Main () yönteminizde SetProcessDPIAware () 'i pinvoke edebilirsiniz, örneğin ClickOnce ile dağıtırsanız gerekli:

    [STAThread]
    static void Main() {
        if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware();
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());             // Edit as needed
    }

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern bool SetProcessDPIAware();

GÜNCELLEME, VS2015 Güncelleme 1 veya üstünü kullanırsanız, bu yaygın ihtiyaç nihayet biraz daha kolay. Eklenen bildirim zaten ilgili yönergeye sahip, sadece yorumları kaldırın.


Bu yazıyı geri bulabilmem için arama için anahtar kelime: dpiAware


Teşekkürler, çözümünüz iyi çalışıyor. Geriye kalan tek sorun, tüm görüntülerin artık orijinal boyutlarında olmasıdır. Sanırım GUI'ime ek "retina" simgeleri eklemenin bir yolunu bulmam gerekecek ...
Boris

@HansPassant Bulanık yazı tipleriyle aynı sorunu yaşıyorum ve bu çözümü uyguladıktan sonra kontrollerim ölçeklenmiyor ve sığamıyor. İkisi de nasıl çalışır?
gajo357

2
Bu Win8 çılgınlığını araştıran herkes SetProcessDPIAwareiçin kullanımdan kaldırıldı ve aynı zamanda düzgün çalışmıyor (en azından Win8.1'de), farklı kontrollerde öngörülemeyen ölçeklendirmeye neden oluyor. Bunun yerine manifest yaklaşımını kullanmanızı şiddetle tavsiye ederim.
Jason Williams

5
Hmya, Windows 8.1 monitör başına DPI satın aldı. Buna ihtiyacım olduğunun farkında değildim.
Hans Passant

1
Dağıtım için ClickOnce kullanacaksanız, bildirimde dpiAware seçeneğini kullanamazsınız, bunun yerine SetProcessDPIAware () kullanın.
Matías

17

Uygulamalar iki farklı modda geliştirilebilir.

Birincisi, uygulamamızın DPI duyarlı olmadığını beyan etmektir (herhangi bir şey beyan etmemek, bunun için varsayılan olacaktır). Bu durumda işletim sistemi uygulamamızı beklenen 96 DPI altında işleyecek ve daha sonra daha önce tartıştığımız bitmap ölçeklendirmesini yapacaktır. Sonuç, bulanık görünen bir uygulama olacaktır, ancak doğru bir düzen ile.

İkinci seçenek, uygulamayı DPI uyumlu ilan etmektir. Bu durumda, işletim sistemi herhangi bir ölçeklendirme yapmayacak ve uygulamanızın ekranın orijinal DPI'sına göre işlemesine izin verecektir. Bir monitör başına DPI ortamı olması durumunda, uygulamanız tüm ekranlar arasında en yüksek DPI ile işlenir, ardından bu bitmap her monitör için uygun boyuta küçültülür. Ölçeği küçültmek, yukarı ölçeklemeden daha iyi bir görüntüleme deneyimi sağlar, ancak yine de biraz belirsizlik fark edebilirsiniz.

Bundan kaçınmak istiyorsanız, uygulamanızı monitör başına DPI duyarlı olarak beyan etmelisiniz. Ardından, uygulamanızın farklı monitörlere ne zaman sürüklendiğini algılamalı ve mevcut olanın DPI'sine göre oluşturmalısınız.

DPI farkındalığının bildirilmesi bir bildirim dosyasında yapılır.

aşağıdaki bağlantı yığın aşımına bakın


Peki ya kullanıcılar geri yüklenen boyutta bir pencereye sahipse ve onu bazı bölümleri farklı monitörlerde olacak şekilde hareket ettirirse? her şeyi iki kez oluşturmamız ve monitör sınırlarını sınırlayıcı kutular olarak kullanmamız gerekiyor mu? bunun ne kadarı winforms kitaplıkları tarafından karşılanıyor?
Cee McSharpface

5

.NET Framework 4.7 ve Windows 10 Creators Update (1703) veya daha yenisini kullanarak, Windows Form uygulamanız için yüksek DPI desteğini yapılandırmak için aşağıdakileri yapmanız gerekir:

Windows 10 ile uyumluluğu beyan edin.

Bunu yapmak için aşağıdakileri manifestdosyanıza ekleyin :

<compatibility xmlns="urn:schemas-microsoft.com:compatibility.v1">
  <application>
    <!-- Windows 10 compatibility -->
    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
  </application>
</compatibility>

app.configDosyada monitör başına DPI farkındalığını etkinleştirin .

Windows Forms , .NET Framework 4.7'den başlayarak eklenen yeni özellikleri ve özelleştirmeleri desteklemek için yeni bir System.Windows.Forms.ApplicationConfigurationSection öğesi sunar. Yüksek DPI'yı destekleyen yeni özelliklerden yararlanmak için, aşağıdakileri uygulama yapılandırma dosyanıza ekleyin.

<System.Windows.Forms.ApplicationConfigurationSection>
  <add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>

Önemli

.NET Framework'ün önceki sürümlerinde, bildirimi yüksek DPI desteği eklemek için kullandınız. App.config dosyasında tanımlanan ayarları geçersiz kıldığından bu yaklaşım artık önerilmez.

Statik EnableVisualStyles yöntemini çağırın.

Bu, uygulama giriş noktanızdaki ilk yöntem çağrısı olmalıdır. Örneğin:

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());   
}

Bunun avantajı, bir Windows Forms uygulaması başlatıldıktan sonra kullanıcının DPI veya ölçek faktörünü değiştirdiği dinamik DPI senaryoları için destektir.

Kaynak: Windows Forms'da yüksek DPI desteği


3

Bu önerilerin hiçbiri benim için işe yaramadı ama, Form.Font = new... 'den çıkardıktan sonra bir şey oldu Form.Design.cs, form yeniden ölçeklenmeye başladı, Yazı Tipi yapıcıda tanımlanmışsa veya hiç tanımlanmamışsa çalışıyor. Neden? başka biri açıklayabilir, sadece yaptığım değişiklik hakkında konuşabilirim ve üzerinde çalıştığım formun temel nedeninin bu olduğunu anlamam için birkaç dakika sürdü. Umarım yardımcı olur.


3

En azından Visual Studio 2017'den beri, sadece bir bildirim dosyası eklemeniz ve bu bölümün açıklamasını kaldırmanız gerekir:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
        <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
</application>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.