child windows 是否与 per-monitor-aware 应用程序中的 parents 具有相同的 DPI?
Do child windows have the same DPI as their parents in a per-monitor-aware application?
可选背景信息
不久前,我问了 this question,其中专门讨论了文本大小和 DLU,而且我没有意识到每个 DPI 意识的实际含义。然而,它从来没有去任何地方。这很可能是我的错,因为我没有通过询问我的 implementation-specific 问题而不是由此产生的一般问题来写一个明确的问题("xX Problem"?)。
我问这个问题是因为我正在编写一个动态 GUI 布局引擎——一个可以处理更改以控制存在和可见性的引擎——并且需要知道 window 基本单位相对于哪个。当时,我决定坐标应基于 parent,尺寸应基于 child,但现在我意识到如果 child 的 DPI 会导致问题比 parent 的大。
当然,这种事情不仅仅是DLU计算。例如,一个 window 在垂直的两半上绘制图片将不得不担心 per-monitor 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
- 系统给出 window 碰巧打开的任何显示器的 DPI;当更改时,发送
WM_DPICHANGED
- 该消息的页面说,如果显示器 DPI 发生变化,也会发生这种情况;我不知道你现在可以这样做
我想知道的是:
在PROCESS_PER_MONITOR_DPI_AWARE
的情况下,window的所有child(不拥有)windows的DPI是否与那个相同parent window?
请注意最高级:关于 DPI 在程序生命周期内不变的部分意味着其他两个意识值的答案是 "yes"。
或者作为另一个例子,假设我有一个 300 像素宽的 window,在相对的边缘有两个控件,都是 100 像素宽。如果我在具有不同 DPI 的两个显示器之间拖动 window,这样一个控件在一个显示器上,另一个控件在另一个显示器上,然后查询它们的 DPI(使用 GetDC()
和 GetDeviceCaps()
), 它们会一样吗?
如果答案是肯定的,那么我就不需要担心 parent windows 和 child windows.
之间的坐标转换问题
如果答案是否定的,那么下一个问题是 WM_DPICHANGED
发送到 child windows,还是只发送到顶层?因为我仍然需要一种方法来知道 children 的 DPI 何时发生变化,所以我至少可以 尝试 重新排列它以使其看起来正确(我还没有弄清楚该怎么做,这完全是另一个问题,但我认为应该只是 MulDiv()
).
谢谢。
当系统确定大部分 window 已越过另一台显示器时,将发送顶层 window WM_DPICHANGED
和整个 window预计将针对新的 DPI 调整大小。
换句话说,系统不会尝试使用混合 DPI windows。
可选背景信息
不久前,我问了 this question,其中专门讨论了文本大小和 DLU,而且我没有意识到每个 DPI 意识的实际含义。然而,它从来没有去任何地方。这很可能是我的错,因为我没有通过询问我的 implementation-specific 问题而不是由此产生的一般问题来写一个明确的问题("xX Problem"?)。
我问这个问题是因为我正在编写一个动态 GUI 布局引擎——一个可以处理更改以控制存在和可见性的引擎——并且需要知道 window 基本单位相对于哪个。当时,我决定坐标应基于 parent,尺寸应基于 child,但现在我意识到如果 child 的 DPI 会导致问题比 parent 的大。
当然,这种事情不仅仅是DLU计算。例如,一个 window 在垂直的两半上绘制图片将不得不担心 per-monitor 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
- 系统给出 window 碰巧打开的任何显示器的 DPI;当更改时,发送
WM_DPICHANGED
- 该消息的页面说,如果显示器 DPI 发生变化,也会发生这种情况;我不知道你现在可以这样做
- 系统给出 window 碰巧打开的任何显示器的 DPI;当更改时,发送
我想知道的是:
在PROCESS_PER_MONITOR_DPI_AWARE
的情况下,window的所有child(不拥有)windows的DPI是否与那个相同parent window?
请注意最高级:关于 DPI 在程序生命周期内不变的部分意味着其他两个意识值的答案是 "yes"。
或者作为另一个例子,假设我有一个 300 像素宽的 window,在相对的边缘有两个控件,都是 100 像素宽。如果我在具有不同 DPI 的两个显示器之间拖动 window,这样一个控件在一个显示器上,另一个控件在另一个显示器上,然后查询它们的 DPI(使用 GetDC()
和 GetDeviceCaps()
), 它们会一样吗?
如果答案是肯定的,那么我就不需要担心 parent windows 和 child windows.
之间的坐标转换问题如果答案是否定的,那么下一个问题是 WM_DPICHANGED
发送到 child windows,还是只发送到顶层?因为我仍然需要一种方法来知道 children 的 DPI 何时发生变化,所以我至少可以 尝试 重新排列它以使其看起来正确(我还没有弄清楚该怎么做,这完全是另一个问题,但我认为应该只是 MulDiv()
).
谢谢。
当系统确定大部分 window 已越过另一台显示器时,将发送顶层 window WM_DPICHANGED
和整个 window预计将针对新的 DPI 调整大小。
换句话说,系统不会尝试使用混合 DPI windows。