辅助监视器上的视图定位不正确,主监视器上的 MainWindow
Posted
技术标签:
【中文标题】辅助监视器上的视图定位不正确,主监视器上的 MainWindow【英文标题】:Views positioned incorrectly on Secondary Monitor, MainWindow on Primary Monitor 【发布时间】:2020-03-06 15:36:12 【问题描述】:使用 MFC,VS2017
我有一个MFC应用,主窗体来源于
CMDIFrameWndEx
然后有 5 个类型的子窗口(并且我已经验证设置了 WS_CHILD 属性)
CMiniFrameWnd
每个都包含嵌入的 CFormView 或 CListView。所有这些嵌入式窗口都是通过 CreateView() 创建的。现在奇怪的是所有 5 个 CMiniFrameWnd 都位于辅助监视器上,我不知道为什么。我已经通过 GetClientRect() 检查了 5 个 CMiniFrameWnd 的 ClientRect 坐标,它们相对于 CMDIFrameWndEx 看起来很正常。 我正在使用 SetWindowPos() 来定位所有 5 个。
我不明白为什么子窗口出现在辅助监视器上,因为主窗口位于主监视器上。我没有使用 MonitorFromWindow(),但我不需要,因为它在 Primary 上。
有什么明显的我做错了吗?
【问题讨论】:
Child Windows: "子窗口具有WS_CHILD
样式并且限制在其父窗口的客户区。" 如果您的“子”窗口位于“父”之外,那么这些实际上不是子窗口。我们看不到的代码有问题。
谢谢。你说的对。这是祖父-父母-孩子的关系。 CFormView,CListView是CMiniFrameWnd的一个WS_CHILD,但是CMiniFrameWnd不是CMDIFrameWndEx的一个child,它是一个顶层窗口。我试着这样做,但 CWnd::CreateEx() 失败了。但我应该能够破解它。我认为是坐标系。我有 MFC 源代码,我注意到 CWnd::CenterWindow 能够居中***窗口,因此我应该检查一下。
重要的一点是,您正在询问您的代码问题,但尚未在问题中发布该代码。通常需要minimal reproducible example。也就是说,我相信 MFC 会自动将其 UI 布局存储到注册表中(至少它曾经这样做过),并尝试在应用程序启动时恢复它。鉴于几乎不可能以适应序列化的方式可靠地将窗口坐标映射到显示设备,很可能那里出了问题。
@IInspectable 我看到您引用了 MS 文档,但是具有附加 WS_POPUP 样式的子窗口可以位于父窗口区域之外。这是错的吗?
尼克,MS 文档是错误的。基本的事情是如果窗口有 WS_CHILD 属性,坐标是客户端坐标,但如果没有,坐标是屏幕坐标。 WS_POPUP 与 WS_CHILD 互斥,因此 WS_POPUP 窗口是***窗口,因此坐标是屏幕坐标。
【参考方案1】:
回答最后一件事,是的,我做的事情根本上是错误的。现在问题已经解决了。
如果使用 SetWindowPos() 或 MoveWindow(),则提供的坐标必须是屏幕坐标。那是我的错误。我提供了从 GetClientRect() 获得的客户端坐标。使用 GetWindowRect() 给出屏幕坐标。这是为了在注册表中保存/恢复 Windows 位置。但是用于保存/恢复窗口位置的正确函数是 GetWindowPlacement()/SetWindowPlacement()。
【讨论】:
以上是关于辅助监视器上的视图定位不正确,主监视器上的 MainWindow的主要内容,如果未能解决你的问题,请参考以下文章
为什么“缩放”的显示设置和使用多个监视器导致我的WPF应用程序窗口在我的显示器上的其他区域中设置动画?
MFC Feature Pack 应用程序在辅助监视器中恢复为最大化时大小错误