2008年03月02日

WM_ENTERSIZEMOVEとWM_EXITSIZEMOVE

開発環境C/C++,WIN32

本記事は過去に書いた記事の焼き直しです。

Windowsアプリケーションの中には、ウィンドウのサイズ変更に時間がかかるものがあります。
代表的なものは画像ビューアです。画像の拡大縮小を綺麗にやろうとすると時間がかかるからです。
この時間がかかる処理をOnSize(WM_SIZEのハンドラ)に書くと、ウィンドウのサイズ変更がもっさりとしたアプリケーションになってしまいます。
本日紹介する方法は、サイズ変更のもっさり感を解消するための方法です。

まずは軽くて適当なサイズ変更処理を用意します。 例えば画像ビューアではニアレストネイバー法による拡大縮小処理が良いでしょう。
Windowsでは、サイズ変更前にWM_ENTERSIZEMOVEが送られてきて、サイズ変更後にWM_EXITSIZEMOVEが送られてくるので、 このメッセージの間にWM_SIZEが送られてきた場合は、軽くて適当なサイズ変更処理を実施します。 そして、WM_EXITSIZEMOVEで重くて正確なサイズ変更処理を実施するのです。
これでユーザがウィンドウフレームをドラッグしているときは軽いサイズ変更処理が行われるので、もっさり感はなくなります。

これらのメッセージを使うときの注意点を挙げます。

  • WM_ENTERSIZEMOVEWM_EXITSIZEMOVEは、ウィンドウを移動するときにも送られてきます。 よって、WM_EXITSIZEMOVEを受け取ったときはサイズ変更が実際に発生したかどうか判定するべきです。
  • システムメニューからサイズを変更した場合など、WM_ENTERSIZEMOVE無しにWM_SIZEが送られてくるときもあります。 このときは、正確なサイズ変更処理を行うべきです。

コードを以下に示します。上記注意点もケアされています。
ウィンドウメッセージの処理は、ご使用のライブラリの作法に合わせて変えて下さい。

// グローバル変数orウィンドウクラスのメンバ変数
bool SizeChanging_;
bool SizeChanged_;

// WM_SIZEのハンドラ
LRESULT OnSize(UINT, WPARAM, LPARAM, BOOL&)
{
  if (!SizeChanging_) {
    // 重たくて正確なサイズ変更処理
  }else {
    SizeChanged_ = true;
    // 軽くて適当なサイズ変更処理
  }
  return 0;
}

// WM_ENTERSIZEMOVEのハンドラ
LRESULT OnEnterSizeMove(UINT, WPARAM, LPARAM, BOOL&)
{
  SizeChanging_ = true;
  SizeChanged_ = false;
  return 0;
}

// WM_EXITSIZEMOVEのハンドラ
LRESULT OnExitSizeMove(UINT, WPARAM, LPARAM, BOOL&)
{
  SizeChanging_ = false;
  if (SizeChanged_) {
    // 重たくて正確なサイズ変更処理
  }
  return 0;
}
投稿者 MASATO : 2008年03月02日 21:08 | トラックバック
コメント
コメントする









名前、アドレスを登録しますか?