簡體   English   中英

WPF ClickOnce DPI感知每個監視器v2

[英]WPF ClickOnce DPI awareness Per-Monitor v2

我將設置此問題並親自回答,以便其他人可以輕松地搜索並找到正確的答案。 我不得不谷歌搜索幾個小時,並從多個來源匯編最終結果...

因此,問題是- 如何在ClickOnce場景(特別是WPF,特別是c#)中啟用Per-Monitor v2 DPI感知?

在Win 10 Creators Update(1703)中添加了Per-monitor v2。 眾所周知,ClickOnce不支持在app.manifest文件中聲明的DPI感知, 例如

首先,任何想大聲疾呼的人-只需針對每個監視器目標.NET 4.6.2,默認情況下就會啟用DPI感知-這是不對的。
.NET 4.6.2中默認情況下啟用的是幕后的樣板代碼-窗口聲明代碼中非常討厭的c ++鈎子,以支持對每個顯示器的dpi感知。
您仍然必須通過app.manifest聲明您支持每個顯示器的dpi感知,但ClickOnce不支持。
(請注意,除非您手動添加樣板代碼 ,否則即使使用應用程序清單,.NET的早期版本也不支持每個監視器的dpi意識)

現在來回答:

  1. 確保您的項目以.NET 4.6.2為目標。 (為此,最好使用Visual Studio 2017)
  2. 在裝配體屬性中禁用DPI感知。 相信我,我們稍后將在代碼中重新啟用它。 為此,請在項目“ 屬性”節點下打開AssemblyInfo.cs (通常在右側展開SolutionExplorer中的扳手圖標)。 將以下代碼添加到最后一行: [assembly: DisableDpiAwareness] (這需要using System.Windows.Media;語句,只需單擊將鼠標懸停在紅色波浪線上方時出現的燈泡,然后添加建議的using語句即可)
  3. 添加一個app.manifest文件並聲明對Win 10和其他OS版本的支持。 SolutionExplorer- >添加->新項目->應用程序清單文件中右鍵單擊您的項目。 打開創建的清單文件,中間有一個包含操作系統版本的部分,取消對它們的注釋: app.manifest中的操作系統版本 不要取消有關DPI意識的部分的注釋(進一步)。 如果這樣做,ClickOnce將引發錯誤。
  4. 現在,您將在項目中的某處需要以下c#代碼,我建議為此創建一個新的靜態類:

     internal static class NativeMethods { [DllImport("user32.dll", SetLastError = true)] internal static extern bool SetProcessDpiAwarenessContext(int dpiFlag); [DllImport("SHCore.dll", SetLastError = true)] internal static extern bool SetProcessDpiAwareness(PROCESS_DPI_AWARENESS awareness); [DllImport("user32.dll")] internal static extern bool SetProcessDPIAware(); internal enum PROCESS_DPI_AWARENESS { Process_DPI_Unaware = 0, Process_System_DPI_Aware = 1, Process_Per_Monitor_DPI_Aware = 2 } internal enum DPI_AWARENESS_CONTEXT { DPI_AWARENESS_CONTEXT_UNAWARE = 16, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = 17, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = 18, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = 34 } } 
  5. 最后一部分是調用上述p / invoke方法並聲明dpi感知支持。 我們需要在運行任何其他代碼之前執行此操作。 為此,在SolutionExplorer中右鍵單擊app.xaml ,然后選擇View Code 然后添加以下代碼:

     protected override void OnStartup(StartupEventArgs e) { if (Environment.OSVersion.Version >= new Version(6, 3, 0)) // win 8.1 added support for per monitor dpi { if (Environment.OSVersion.Version >= new Version(10, 0, 15063)) // win 10 creators update added support for per monitor v2 { NativeMethods.SetProcessDpiAwarenessContext((int)NativeMethods.DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); } else NativeMethods.SetProcessDpiAwareness(NativeMethods.PROCESS_DPI_AWARENESS.Process_Per_Monitor_DPI_Aware); } else NativeMethods.SetProcessDPIAware(); base.OnStartup(e); } 
  6. 確保其余代碼可以正確處理DPI。 從.NET 4.6.2開始,可以使用OnDpiChanged事件和VisualTreeHelper.GetDpi()方法。

請享用 :)

@Marko-好答案! 但這是一個小細節:如果將WinForms與WPF混合使用,則必須添加WinForms配置。 請更新您的答案,我沒有足夠的意思發表評論...

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

推薦人: https ://docs.microsoft.com/en-us/dotnet/framework/winforms/high-dpi-support-in-windows-forms

在app.manifest中聲明的DPI感知被稱為 .NET 4.7.2功能之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM