FAQ1-3

Q. タイトルバー以外の場所で「ウィンドウ移動」は

 よく,タイトルバー以外の場所をドラッグして,ウィンドウの移動ができるものを見掛けますが,これはいったいどのようにしくみになっているのでしょうか.
 いちいち自分で移動枠を描いて,タイトルバーで移動させるのとまったく同じことをしているのだろうかとも思ったのですが,どうも違うようです.
 ウィンドウのドラッグ移動を開始させる関数を探してみても,それらしいものはないのです.もしそのような関数があったら教えてください.


A. WM_NCHITTESTメッセージに応答することで,Windowsにタイトルバーが押されたと思わせてドラッグ移動することが可能になる

WM_NCHITTESTメッセージ

 タイトルバーが押されたと思わせるには,リターン値にHTCAPTIONを指定します.
 WM_NCHITTESTは,いまマウスはウィンドウ上のどういう位置にいるか? というWindowsからアプリケーションに送られる問い合わせのメッセージです.
 通常,このメッセージは処理せず,DefWindowProc()に渡すと現在マウスのある位置に対応した値を返すのですが,これをドラッグ移動したい位置にきたときだけ,HTCAPTION(いまタイトルバーの上にいますよー)という値を返して,それ以外の位置のときDefWindowProc()に流すようにすればいいわけです.
 しかし,これだとダブルクリックをすると最大化/復元もやってくれるので,少々ありがた迷惑です.ダブルクリックのときは別の処理をしたい場合もあります.
 そこで,少々裏技的なのですが,WM_SYSCOMMANDを自分自身に送ってドラッグ移動を開始させる方法もあります.
 システムメニューから「移動(M)」を選んだ場合,WM_SYSCOMMANDでwParamにSC_MOVEが来るのですが,これをDefWindowProc()に流した場合,さらにWM_SYSCOMMANDでwParamに0xF012という値を入れたメッセージが来ます.
 これはwindows.hに定義されていない値ですが,これはどうやら「マウスによるドラッグ移動の開始」というメッセージのようなのです.
 これをWM_LBUTTONDOWNが来たときに自分自身に投げてやれば,ドラッグ移動が開始できてしまいます.あまりお薦めできませんが,APIのようにポンと使えてしまうので結構便利です.

Back to FAQ main page