繁体   English   中英

每个显示器 DPI 感知的问题 MFC MDI 应用程序

[英]Problems with per-monitor DPI aware MFC MDI app

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

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

如果主显示器具有 100% DPI 缩放 (96) 而辅助显示器具有 125% 缩放 (120 DPI) 或 150% 缩放 (144 DPI) 或任何其他更高的值,则当子 windows 最大化时,子 Z05B8C74CBD96FBF2DE4C1A352702FFF4Z 系统的一部分bar 是可见的,如下所示:

125% 缩放: 在此处输入图像描述

150% 缩放: 在此处输入图像描述

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

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

When you maximize the child window, there is a series of Windows messages that are sent to the window: WM_GETMINMAXINFO > WM_WINDOWPOSCHANGING > WM_GETMINMAXINFO > WM_NCCALSIZE > WM_WINDOWSPOSCHANGED > WM_MOVE > WM_SIZE . WM_GETMINMAXINFO在 window 的大小或 position 即将更改时发送,以便应用程序可以覆盖,例如,窗口的默认最大化大小和 Z4757FE07FD492A8BE0EA6A760D683DE6 对此有一个注释:

对于具有多个显示器的系统,ptMaxSize 和 ptMaxPosition 成员描述了主显示器上 window 的最大尺寸和 position,即使 window 最终在辅助显示器上最大化。 在这种情况下,window 管理器会调整这些值以补偿主监视器和显示 window 的监视器之间的差异。 因此,如果用户保持 ptMaxSize 不变,则在大于主监视器的监视器上的 window 将最大化为较大监视器的大小。

Raymond Chan 有一篇文章,对此进行了解释:window manager 如何为多个显示器调整 ptMaxSize 和 ptMaxPosition? .

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

我试图做一个肮脏的把戏并处理WM_NCCALCSIZE消息并将 position(左,上)设置为 0(相对于父级)。

void CMyMDIChildWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
   CMDIChildWnd::OnNcCalcSize(bCalcValidRects, lpncsp);   
   if (condition)
   {
      lpncsp->rgrc[0].left = 0;
      lpncsp->rgrc[0].top = 0;
   }
}

只要子 window 有焦点,就可以正常工作。 如果我单击另一个 window 并且它失去焦点,则重新绘制该条并显示在先前的 position 中。 这个技巧只是说客户区域从哪里开始,所以当非客户被重绘时,我会回到原来的问题。

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

我可能遇到了相同的现象,尽管来自不同的路线,我的解决方案与您的解决方案非常相似,但有一点额外,也许这可能对您有所帮助?

void CFixedFrame::OnNcCalcSize ( BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp )
{
    MDIBASEWND::OnNcCalcSize ( bCalcValidRects, lpncsp ) ;

    if ( bCalcValidRects )
    {
        RECT& rcNew = lpncsp->rgrc[0];
        RECT& rcOld = lpncsp->rgrc[1];
        RECT& rcClient = lpncsp->rgrc[2];

        // My problem arose because of the Aero bug (hardwired border widths)
        // And also problems with Theming
        const CNonClientMetrics ncm;
        rcNew.top = ncm.iCaptionHeight + Aero related stuff not relevant to your problem
    }
}

CNonClientMetrics在哪里...

class CNonClientMetrics : public NONCLIENTMETRICS
{
public:
    CNonClientMetrics ( )
    {
        cbSize = sizeof ( NONCLIENTMETRICS ) - sizeof ( this->iPaddedBorderWidth ) ;
        SystemParametersInfo ( SPI_GETNONCLIENTMETRICS, sizeof ( NONCLIENTMETRICS ), this, 0 ) ;
    }
} ;

[以 DPI 感知方式] 这让我摆脱了烦人的蓝色边框(带按钮)。 据我了解,您不能再禁用绘制该部分的 DWM。

我现在找不到我原来的参考资料,但在我对这个问题的注释中,它只发生在 MFC 的 MDI 框架 Windows 上。

不过, 这个链接也可能有用吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM