C++ 支持每监视器DPI的MFC MDI应用程序存在问题

C++ 支持每监视器DPI的MFC MDI应用程序存在问题,c++,winapi,visual-c++,mfc,dpi-aware,C++,Winapi,Visual C++,Mfc,Dpi Aware,我正在努力使MFC应用程序在具有不同DPI缩放的多个监视器环境中正确显示。有一个问题我无法解释,当主监视器和辅助监视器使用不同的DPI运行并且应用程序位于辅助监视器上时,会发生什么情况 如果主监视器具有100%DPI缩放(96),而辅助监视器具有相同的100%DPI缩放,则一切正常 如果主监视器具有100%DPI缩放(96)和辅助监视器具有125%缩放(120 DPI)或150%缩放(144 DPI)或任何其他更高的值,则当子窗口最大化时,部分子窗口系统栏可见,如下所示: 125%缩放比例:

我正在努力使MFC应用程序在具有不同DPI缩放的多个监视器环境中正确显示。有一个问题我无法解释,当主监视器和辅助监视器使用不同的DPI运行并且应用程序位于辅助监视器上时,会发生什么情况

如果主监视器具有100%DPI缩放(96),而辅助监视器具有相同的100%DPI缩放,则一切正常

如果主监视器具有100%DPI缩放(96)和辅助监视器具有125%缩放(120 DPI)或150%缩放(144 DPI)或任何其他更高的值,则当子窗口最大化时,部分子窗口系统栏可见,如下所示:

125%缩放比例:

150%缩放比例:

如果你仔细看,它的7像素代表125%,14像素代表150%。假设系统栏在100%缩放时为29个像素,在150%缩放时为36和125%,在150%缩放时为43个像素,那么这7和14个像素分别是125%和150%缩放时的栏大小与100%基线之间的高度差

因此,棒的位置和大小似乎是由系统在主监视器上运行时计算的

当您最大化子窗口时,会向该窗口发送一系列Windows消息:
WM\u GETMINMAXINFO
WM\u WINDOWPOSCHANGING
WM\u GETMINMAXINFO
WM\u NCCALSIZE
WM\u windowposchanged
WM\u MOVE
WM\u SIZE
<当窗口的大小或位置即将更改时,会发送code>WM_GETMINMAXINFO,以便应用程序可以覆盖窗口的默认最大大小和位置。关于这一点,有一个注释:

对于具有多个监视器的系统,ptMaxSize和ptMaxPosition 成员描述屏幕上窗口的最大大小和位置 主监视器,即使窗口最终最大化到 辅助监视器。在这种情况下,窗口管理器会调整这些参数 用于补偿主监视器和主监视器之间差异的值 显示窗口的监视器。因此,如果用户离开 ptMaxSize未触及,监视器上的窗口大于主窗口 监视器最大化为较大监视器的大小

陈雷蒙的一篇文章解释了这一点:

因此,
ptMaxSize
应填写主监视器的尺寸。我的主监视器是2560x1440像素,次监视器的大小是1920x1200。但是,我在这里得到的大小值是1757x1023和1761x1027(在连续调用时)。这既不是主监视器的大小,也不是辅助监视器的大小

我尝试了一个肮脏的把戏,处理了
WM\u NCCALCSIZE
消息,并将位置(左,上)设置为0(相对于父对象)

只要子窗口具有焦点,就可以正常工作。如果我点击另一个窗口,它失去了焦点,那么该条将被重新绘制并显示在前一个位置。这个技巧只说明客户端区域从何处开始,所以当重新绘制非客户端时,我回到原始问题


我的问题是,这个问题的根源是什么?我该如何解决它?

编程MFC应用程序的方法有很多种。我不会用标准MFC模板复制任何问题,无论是否使用每监视器高DPI感知设置和两个不同的监视器。但是你有两个图标的蓝色“丝带”看起来不标准。你有复制代码/项目吗?没有,我没有复制代码。我制作了一个MDI MFC应用程序,最大化子窗口效果很好。我的应用程序的UI是完全定制的。但没那么特别。蓝色栏是菜单栏,下面是工具栏。我没有截图整个窗口,只是相关的部分。很抱歉,我不能建立项目来重现你的问题,所以我仍然希望你能提供一个可复制的样本。也许您可以参考可能相关的线程。我猜您在主窗体的非客户端区域处理方面有一些问题。实际上,主框架不处理
WM_NCPAINT
消息或其他非客户端消息(无论是
WM_PAINT
还是
WM_ERASEBKGND
)。那里发生的事情不多。
void CMyMDIChildWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
   CMDIChildWnd::OnNcCalcSize(bCalcValidRects, lpncsp);   
   if (condition)
   {
      lpncsp->rgrc[0].left = 0;
      lpncsp->rgrc[0].top = 0;
   }
}