在每个显示器感知的应用程序中,子窗口是否与父母具有相同的DPI?

可选的背景信息

前一段时间,我问这个问题 ,具体谈到文本大小和DLU,并没有意识到每个DPI的意识实际上意味着什么。 但是,它从未去过任何地方。 问我最有可能是因为没有写出一个明确的问题,而是问自己的具体实现问题,而不是问题的出现(“xx问题”?)。

我问了这个问题,因为我正在编写一个dynamic的GUI布局引擎 – 一个可以处理更改以控制存在和可见性的引擎,并且需要知道基本单元相对于哪个窗口。 当时,我决定坐标应该以父母为基础,尺寸应该基于孩子,但是现在我意识到,如果孩子的DPI比父母的大,那么会引起问题。

当然,这种types的事情不仅仅是DLU的计算。 例如,一个窗口在两个垂直方向上绘制图片将不得不担心每个显示器的DPI在中间变化。 所以请允许我提出一个普遍的,毫不含糊的问题。


实际的问题

今天我发现了这两个MSDN文章:

  • https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266(v=vs.85).aspx
  • https://msdn.microsoft.com/en-us/library/windows/desktop/mt744321(v=vs.85).aspx

读完之后,我现在对系统DPI的意识有了很多了解:

  • PROCESS_SYSTEM_DPI_AWARE
    • 当被问及DPI的东西时,系统会给主监视器的DPI
    • 这个值不能在程序的整个生命周期中不会改变
    • 相当于调用较旧的SetProcessDPIAware()
  • PROCESS_DPI_UNAWARE
    • PROCESS_SYSTEM_DPI_AWARE除了DPI被固定在96
  • PROCESS_PER_MONITOR_DPI_AWARE
    • 系统给出了窗口恰好在的任何监视器的DPI; 当这个变化时,发送一个WM_DPICHANGED
    • 该消息的页面说这也可能发生,如果显示器的DPI改变; 我不知道你现在可以这样做

我想知道的是:

PROCESS_PER_MONITOR_DPI_AWARE的情况下,窗口的所有子窗口(非拥有)的DPI是否与父窗口相同?

请注意最高级:关于新闻部不改变程序寿命的部分意味着其他两个意识值的答案是“是”。

或者作为另一个例子,假设我有一个宽度为300px的窗口,两个控件的宽度都是100px,在相对的边缘。 如果我用两个不同的DPI监视器拖动窗口,使其中一个控件在一个监视器上,另一个控件在另一个上,然后查询他们的DPI(使用GetDC()GetDeviceCaps() ),它们是相同?

如果答案是肯定的,那么我不需要担心在父窗口和子窗口之间转换坐标。

如果答案是否定的,那么接下来的问题是将WM_DPICHANGED发送给子窗口,还是只发送给顶层? 因为我仍然需要一种方法来知道孩子的DPI何时改变,所以我至less可以尝试重新排列它看起来是正确的(我还没有想出如何去做,哪一个是完全的另一个问题,我认为应该只是MulDiv() )。

谢谢。

当系统确定大部分窗口已经跨越到另一个监视器上时,顶层窗口被发送WM_DPICHANGED ,并且整个窗口预期将被调整为新的DPI。

换句话说,系统不会尝试使用混合DPI的窗口。