![](/img/trans.png)
[英]Per-monitor DPI-Aware: black window glitch with NVIDIA Optimus
[英]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% 为 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.