在Windows 7上保存和恢复Aero Snap位置

13
假设我有一个窗口,并希望在窗口关闭时保存其位置,并在下次打开该窗口时恢复其位置。通常的做法是调用GetWindowPlacement / SetWindowPlacement。它会记住位置和最大化/最小化状态。
在Windows 7上,您可以使用"Aero Snap"功能将窗口停靠在屏幕的一侧。我的问题是如何保存和恢复已经被“Snapped”(停靠)的窗口,以便您可以恢复“Snap”状态。GetWindowPlacement / SetWindowPlacement无法解决此问题(据我所知),我也没有看到任何Windows 7中的“Snap” API。
这里有一个类似的问题: 如何检测窗口是否被Windows7调整大小, 但在这种情况下,似乎OP只想要恢复位置,而不是“Snap”状态。

1
不,没有公开的接口。存储工作区大小可能是一种解决方法。如今有人会更改视频分辨率吗? - Hans Passant
1
我不知道有什么方法可以保存捕捉状态,以便在您再次拖动时,Windows会恢复“正常”状态。请注意,捕捉并非最大化。 - Deanna
@Hans Passant,存储工作区大小的问题在于即使如此,我也无法知道窗口是否被捕捉(我可以从 rcNormal != windowPos 推断出)。 - Maurice Flanagan
@ Deanna,我也得出了这个结论,我看不到任何方法可以让窗口进入捕捉状态并在您将其拖离边缘时恢复,我很惊讶他们没有暴露它,哦好吧! - Maurice Flanagan
2个回答

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

需要补充的一点是,只有在showCmd为SW_NORMAL时才应该覆盖WINDOWPLACEMENT::rcNormalPosition。例如,如果窗口被最大化了,如果您将最大化的窗口大小存储为正常大小,则无法轻松地将窗口恢复到正常位置。 - Christian Cheney
2
if(SW_NORMAL == wp.showCmd) GetWindowRect(&wp.rcNormalPosition); - Christian Cheney
3
问题在于 GetWindowRect 使用屏幕坐标,而 GetWindowPlacement 使用工作区坐标。 - David Heffernan

0
我解决这个问题的方式是重写 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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接