高DPI設定(150%など)のマシンでアプリを正しく実行するように構成するにはどうすればよいですか?


101

C#で簡単なWinformsアプリケーションを作成しました。高DPI設定(150%など)のマシンでアプリケーションを実行すると、アプリケーションがスケールアップします。ここまでは順調ですね!ただし、フォントサイズを大きくしてフォントをレンダリングする代わりに、すべてのテキストも拡大されます。もちろん、これは非常にぼやけたテキストになります(ボタンなどのすべてのコントロール上)。

ウィンドウがテキストのレンダリングを正しく処理するべきではありませんか?たとえば、私のアプリケーションのタイトルバーはくっきりと明確にレンダリングされます。

回答:


131

100%(または「XPスタイルのDPIスケーリング」チェックボックスをオンにして125%)を超えると、デフォルトでWindowsがUIのスケーリングを引き継ぎます。これは、アプリに出力をビットマップにレンダリングさせ、そのビットマップを画面に描画させることで実現します。そのビットマップの再スケーリングにより、テキストは必然的にぼやけて見えます。「DPI仮想化」と呼ばれる機能は、古いプログラムを高解像度モニターで使用できるようにします。

<dpiAware>要素をマニフェストに追加することで、より高いDPI設定を処理できることを明示的に通知する必要があります。MSDNページはここにありますが、UAC設定が省略されているため、完全ではありません。プロジェクト+新しい項目を追加し、「アプリケーションマニフェストファイル」を選択します。マニフェストテキストを編集するか、これをコピーして貼り付けます。

<?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>

Main()メソッドでSetProcessDPIAware()をpinvokeすることもできます。たとえば、ClickOnceでデプロイする場合に必要です。

    [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();

更新、VS2015 Update 1以降を使用すると、この一般的なニーズがやや簡単になります。追加されたマニフェストにはすでに関連するディレクティブがあります。コメントを削除してください。


このポストバックを見つけることができるように検索のキーワード:dpiAware


ありがとう、あなたの解決策はうまくいきます。残っている唯一の問題は、すべての画像が元のサイズになっていることです。GUIに「網膜」アイコンを追加する方法を見つける必要があると思います...
ボリス

@HansPassantぼやけたフォントでも同じ問題があり、この解決策を適用した後、コントロールが拡大縮小されず、収まらない。両方を機能させる方法は?
gajo357 2014年

2
このWin8の狂気を調査する人にとってSetProcessDPIAwareは非推奨であり、また(少なくともWin8.1では)適切に機能しないため、さまざまなコントロールで予測できないスケーリングが発生します。代わりにマニフェストアプローチを使用することを強くお勧めします。
Jason Williams

5
Hmya、Windows 8.1はモニターごとのDPIを取得しました。私はそれが必要だとは知りませんでした。
ハンスパッサント2014

1
配置にClickOnceを使用する場合は、マニフェストでdpiAwareオプションを使用できません。代わりにSetProcessDPIAware()を使用してください。
マティアス2015年

17

アプリケーションは、2つの異なるモードで開発できます。

1つ目は、アプリケーションを非DPI対応として宣言することです(何も宣言しないと、これがデフォルトになります)。この場合、オペレーティングシステムは予想される96 DPIでアプリケーションをレンダリングし、前述のビットマップスケーリングを実行します。その結果、アプリケーションはぼやけて見えますが、正しいレイアウトになります。

2番目のオプションは、アプリケーションをDPI対応として宣言することです。この場合、OSはスケーリングを行わず、アプリケーションが画面の元のDPIに従ってレンダリングできるようにします。モニターごとのDPI環境の場合、アプリケーションはすべての画面の中で最も高いDPIでレンダリングされ、このビットマップは各モニターの適切なサイズに縮小されます。ダウンスケーリングを使用すると、アップスケーリングよりも優れた表示エクスペリエンスが得られますが、あいまいさがわかる場合があります。

これを避けたい場合は、アプリケーションをモニターごとのDPI対応として宣言する必要があります。次に、アプリケーションが異なるモニター間でドラッグされたことを検出し、現在のモニターのDPIに従ってレンダリングする必要があります。

DPI認識の宣言は、マニフェストファイルで行われます。

次のリンクを参照してください stackoverflowの


ユーザーがウィンドウを復元れたサイズにして、その一部を別のモニターに移動するように移動した場合はどうなりますか?すべてを2回レンダリングし、モニターの境界を境界ボックスとして使用する必要がありますか?そのどれだけがwinformsライブラリでカバーされていますか?
Cee McSharpface 2018年

4

.NET Framework 4.7およびWindows 10 Creators Update(1703)以降を使用して、Windowsフォームアプリケーションの高DPIサポートを構成するには、次のことを行う必要があります。

Windows 10との互換性を宣言します。

これを行うには、manifestファイルに以下を追加します。

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

app.configファイルでモニターごとのDPI認識を有効にします。

Windowsフォームでは、新しいSystem.Windows.Forms.ApplicationConfigurationSection要素が導入され、.NET Framework 4.7以降に追加された新しい機能とカスタマイズをサポートしています。高DPIをサポートする新機能を利用するには、アプリケーション構成ファイルに以下を追加します。

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

重要

以前のバージョンの.NET Frameworkでは、マニフェストを使用して高DPIサポートを追加しました。このアプローチは、app.configファイルで定義された設定をオーバーライドするため、推奨されなくなりました。

静的なEnableVisualStylesメソッドを呼び出します。

これは、アプリケーションエントリポイントの最初のメソッド呼び出しでなければなりません。例えば:

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

これの利点は、Windowsフォームアプリケーションの起動後にユーザーがDPIまたはスケールファクターを変更する動的DPIシナリオがサポートされることです。

ソース:Windowsフォームでの高DPIサポート


3

これらの提案はどれもうまくいきませんでしたが、Form.Font = new...をから削除した後に何かが起こりました。Form.Design.csフォームが適切に再スケーリングを開始し、コンストラクタでFontが定義されているかどうかで機能します。どうして?他の誰かが説明できるかもしれません。私が行った変更について話し、数分かけてそれが私が作業していたフォームの根本的な原因であると理解するのにかかりました。それが役に立てば幸い。


2

少なくともVisual Studio 2017以降は、マニフェストファイルを追加して、このセクションのコメントを外す必要があります。

<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
        <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
</application>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.