【问题标题】:How to get correct DPI on System.Drawing.Graphics in a Per-Monitor DPI aware app?如何在 Per-Monitor DPI 感知应用程序中的 System.Drawing.Graphics 上获得正确的 DPI?
【发布时间】:2019-05-03 04:34:54
【问题描述】:

我在 Per-Monitor v2 DPI Aware 模式下运行 .NET 桌面应用程序。正确绘制 UI 的 WinForms 部分要求所有绘制者都知道当前的 DPI 值。高级画家可以从HWND 获得它,这是一个可行的解决方案。但是,较低级别的画家只有一个 GDI+ System.Drawing.Graphics 对象。

我正在努力让System.Drawing.Graphics 告诉正确的 DPI。现在,无论其HWND 的当前 DPI 是什么,我都可以在其上看到系统级 DPI。它的DpiX/DpiY 属性是只读的,因此它们必须受到间接影响。

Graphics 有两种为控件创建控件的基本方法,可以是HWND,也可以是HDC(可能来自::GetDC::BeginPaint,甚至@ 987654333@ 参数)。无论哪种方式,它都只有 SYSTEM DPI 值,而不是每个监视器感知的值。制作一个Bitmap 可能会起作用,对其进行适当的配置并首先对其进行绘制,然后在控件上进行blit,但这不是太整洁也不是最优的。

所以:对于 WinForms 控件的 HWND,我看到了一个良好的每个监视器感知 DPI,我希望在 Graphics 对象 DpiX/DpiY 属性上看到同样好的值那个控件,有办法吗?

【问题讨论】:

  • 看看这个答案stackoverflow.com/a/55556061/10128127。提到了如何获得实际DPI比例因子的解决方案
  • 谢谢,但这个答案已经过时了(它获得了GetDC(NULL) 的 DPI,这对于在多个显示器上运行的应用程序或特别是在混合 DPI 托管行为模式下运行的应用程序是不正确的)。无论如何,我有办法获得某个 HWND 的 DPI,但我希望使用该 DPI 正确初始化 Graphics 对象并将其告知所有各方。如果某个画家只有Graphics 而没有HWND,那么就没有获得DPI 的好方法。 Graphics 上的错误 DPI 值会产生误导。

标签: c# winforms dpi


【解决方案1】:

现在应该有办法了。要在两个监视器上显示表单,您必须创建 2 个实例。要将图形/图像加载到两种形式中,您只需要该图形的一个实例。 图形独立于您的显示器,内部不需要它(只是像素的集合)。

【讨论】:

  • 抱歉,我看不出这段文字与问题有什么关系。
  • 对不起我的回答!我首先完全误解了你的问题。我更深入地研究了 v2 DPI Aware,有趣的东西。但我发现只有一种方法可以获得正确的 DPI 值:新的Control.DeviceDpi 属性。如果您反映此代码,您会发现一个 DpiHelper 类使用 GetDeviceCaps 和带有不安全调用的 DC。如果您不能直接调用控件属性,可能会有所帮助。
  • 是的,我可以得到 DPI,但我不能让它进入 Graphics DpiXDpiY 属性,这样在绘画时从中读取它的人都不会使用错误的值。迟早会有人使用这些属性并让 UI 失真。在正常情况下您不会注意到这一点(因为您周围都有相同的 DPI),只有当您将桌面远程放入盒子或连接具有其他像素密度的显示器时。
  • 如果您喜欢阅读有关 PMv2 的内容,您可能想更深入地阅读有关 DPI_HOSTING_BEHAVIOR_MIXED 的内容。这就是它变得非常奇怪的地方。尤其是您可以将 SYSTEM 插入 PMv2 的部分,但如果您反过来尝试,您的 UI 部分就会脱落。
猜你喜欢
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
  • 1970-01-01
  • 2015-01-07
  • 1970-01-01
  • 2011-05-03
  • 1970-01-01
相关资源
最近更新 更多