【问题标题】:Save and restore Aero Snap position on Windows 7在 Windows 7 上保存和恢复 Aero Snap 位置
【发布时间】:2025-12-24 23:10:24
【问题描述】:

假设我有一个窗口,我想在窗口关闭时保存它的位置,并在窗口再次打开时恢复它。执行此操作的典型方法是调用 GetWindowPlacement / SetWindowPlacement。这需要记住位置和最大化/最小化状态。

在 Windows 7 上,您可以使用 "Aero Snap" 功能将窗口停靠在屏幕一侧。我的问题是如何保存和恢复已“捕捉”的窗口,以便恢复“捕捉”状态。 GetWindowPlacement / SetWindowPlacement 不能解决这个问题(据我所知),我还没有在 Windows 7 中看到任何“Snap”API。

这里有一个类似的问题 How to detect window was resized by Windows7 但在这种情况下,OP 似乎只想要恢复位置,而不是“Snap”状态。

【问题讨论】:

  • 不,没有暴露。存储工作区大小也可能是一种解决方法。这些天有人改变视频分辨率吗?
  • 我不知道一种保存快照状态的方法,当您再次拖动时,Windows 将恢复“正常”状态。请注意,捕捉并没有最大化。
  • @Hans Passant,存储工作区大小的问题是,即使那样,我也无法知道窗口已被捕捉(我可以从 rcNormal != windowPos 的事实推断出来)
  • @Deanna,这也是我要得出的结论,我看不出有任何方法可以让窗口进入捕捉状态,当你将它拖离边缘时它会恢复,我'很惊讶他们没有揭露这一点,哦,好吧!

标签: winapi windows-7 aero-snap


【解决方案1】:

解决方法是调用GetWindowRect() 来获取实际的窗口坐标并将它们复制到WINDOWPLACEMENT::rcNormalPosition 中的错误坐标上。

【讨论】:

  • 要补充的一点是,如果 showCmd 为 SW_NORMAL,您只应覆盖 WINDOWPLACEMENT::rcNormalPosition。例如,如果窗口最大化,如果您将最大化的窗口大小存储为正常大小,您将无法轻松地将窗口恢复到正常位置。
  • if(SW_NORMAL == wp.showCmd) GetWindowRect(&wp.rcNormalPosition);
  • 问题是GetWindowRect使用的是屏幕坐标,而GetWindowPlacement使用的是工作区坐标。
【解决方案2】:

我解决它的方法是覆盖 CWinAppEx::SaveState,在保存之前更新 WINDOWPLACEMENT:

BOOL MyApp:SaveState(LPCTSTR lpszSectionName, CFrameImpl *pFrameImpl)
{
  WINDOWPLACEMENT wp;
  wp.length = sizeof(WINDOWPLACEMENT);
  m_pMainWnd->GetWindowPlacement(&wp);
  if (wp.showCmd == SW_SHOWNORMAL)
  {
    m_pMainWnd->GetWindowRect(&wp.rcNormalPosition);
    m_pMainWnd->SetWindowPlacement(&wp);
  }

  return __super::SaveState(lpszSectionName, pFrameImpl);
}

【讨论】: