Aero-Snap による Window サイズの変更を検出する

GetWindowPlacement では、ウィンドウが通常の状態でのウィンドウ座標と、実際にウィンドウが、最大化されている(SW_MAXIMIZE)のか、最小化されている(SW_MINIMIZE)のか、あるいは、通常の状態(SW_SHOWNORMAL)なのかが取得できます。従って、普通なら、この関数を呼び出せば、特に何の問題もなく、ウィンドウの状態を取得することが出来ます。

ところが、 Windows 8 で導入された Aero-Snap ([Win] + 矢印キー)では、この関数では関知できない状態になります。
具体的には、ウィンドウの状態が、通常の状態(SW_SHOWNORMAL)であると報告されます。これだと、アプリは自分の状況を正しく認識できません。

なので、 Aero-Snap 状態であることを知るためにはもうちょっと小細工をする必要があります。答えをそのまま書くと、 SW_SHOWNORMAL と認識された場合には、 GetWindowRect を使って取得したウィンドウサイズと rcNormalPosition の値を比較すると、 Aero-Snap かどうかを区別できるようです。

bool isResizeByAerosnap(HWND wnd)
{
  // The function works because of the fact that:
  // When the window is resized by Aero-snap, GetWindowPlacement returns
  // SW_SHOWNORMAL but wp.rcNormalPosition is not identical to the size
  // returned by GetWindowRect.
  WINDOWPLACEMENT wp;
  wp.length = sizeof(WINDOWPLACEMENT);
  GetWindowPlacement(wnd, &wp);
  if (wp.showCmd != SW_SHOWNORMAL)
  	return false;
  RECT rc;
  GetWindowRect(wnd, &rc);
  return memcmp(&rc, &wp.rcNormalPosition, sizeof(RECT)) != 0;
}

まぁ、問題はそんなことよりも、 Aero-Snap 状態を再現する API がないことなんですけどねw