- ベストアンサー
ウインドウ位置の自動移動の解除
winXP VS2005 MFC SDI クライアント領域をクリックしてウインドウの移動を出来るようにしたのですが、 クライアント領域をクリックしながらウインドウを移動し、 ウインドウのタイトルバーがデスクトップ外に出た状態で 移動をやめる(マウスのクリックをやめる)とウインドウが自動で タイトルバーが表示されるところまで移動してしまいます。 (マウスを放した位置で止まってくれない) この自動的な動きを止める方法をよろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
★過去に『WM_NCLBUTTONUPについて』という質問に回答しました。 ・でも、この方法は今回使えないかもしれませんね。多分? http://oshiete1.goo.ne.jp/qa2710782.html→『WM_NCLBUTTONUPについて』 試していませんので、上記の質問を参照してテストしてみませんか? ・以上。結果報告待ってます。
その他の回答 (2)
- Oh-Orange
- ベストアンサー率63% (854/1345)
★申し訳ありません。 ・前回の回答は、勘違いしていました。 私も自動的に戻ってしまう動作を阻止する方法が分かりません。 『DefWindowProc』が何かの動作を行っているようですが…。推測ですが 『WM_MOVING』中でマウスの左クリックが離されてから『WM_EXITSIZEMOVE』 メッセージが発生する間で、戻る動作を行っているかもしれません。→内部で。 ・私にも今のところ詳しく分かりません。ごめんなさい。 他の回答者さんを待ってみて下さい。 アイディア: ・『DefWindowProc』の『WM_NCLBUTTONDOWN』メッセージと同等な処理を 自分で実装して、『DefWindowProc』の『WM_NCLBUTTONDOWN』メッセージを 殺せば自動的には戻らないと思いますが…。試していませんのでヒントです。 ・なお、自分で同等機能の実現方法としては、クライアント領域をクリック中に マウスの移動に変化があったらば、ウインドウも一緒に移動するようにします。 ・このとき、タイマー処理で約 200 msくらいの間隔でマウス座標をチェックして 200 ms前の位置とずれていたらば、ずれた分だけウインドウも移動するように すればよいと思います。 ・以上。おわり。→『WM_NCLBUTTONDOWN』もタイマー処理などを使っていそうです。
お礼
いえ、丁寧な回答ありがとうございます。 当方も、位置情報を保存する方法で試行錯誤しているのですが、 どのメッセージの合間がいいのか?、自動位置変更の判別条件等が かなりシビアで困っているところです。 タイマーは最後の手段で・・・ WM_NCLBUTTONUPにクライアントのクリックでも メッセージが飛んで来れば良いのですが・・・
- Oh-Orange
- ベストアンサー率63% (854/1345)
★クライアント領域のウインドウ移動は『WM_NCLBUTTONDOWN』で行えます。 ・ウインドウの移動は自分で処理するよりも『SendMessage』関数などで 『WM_NCLBUTTONDOWN』メッセージを使えば楽です。 あと『WM_SYSCOMMAND』メッセージでも行えます。 下にそのサンプルを2つ載せます。→どちらでも移動可能。 サンプル: SendMessage( hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0 ); PostMessage( hWnd, WM_SYSCOMMAND, (SC_MOVE|0x02), 0 ); ※『hWnd』が移動するウインドウのハンドルです。 移動停止: ・デスクトップ以外にウインドウが移動したときに『移動停止』する方法は分かりませんが、 デスクトップ以外にウインドウが移動しないような制御は出来ます。この制御が出来れば マウスのクリックを離した後でもデスクトップ領域の中にウインドウが残ります。 ・この処理を行うには、移動中にデスクトップ領域の外に出ないようにメッセージを処理する 必要があります。移動中の処理で有名なのは『WM_MOVE』ですが、『WM_MOVING』という メッセージがあります。このメッセージの中で移動中のウインドウの矩形領域がデスクトップの 外へ移動したかチェックします。外へ出た場合は『デスクトップ内』にウインドウ位置を 戻すようにします。 最後に: ・移動制御する前に『WM_ENTERSIZEMOVE』メッセージ内でマウスが移動できる範囲を『ClipCursor』 関数で設定します。設定する矩形は『GetDesktopWindow』関数で取得したウインドウに対して 『GetWindowRect』関数で取得します。あと『WM_EXITSIZEMOVE』メッセージを捕まえて設定した マウス移動の領域を解除します。→解除の方法は『ClipCursor(NULL);』にするだけです。 『WM_MOVING』メッセージは、『lParam』に移動中のウインドウ矩形が入っています。→『LPRECT』型 このパラメータを使ってデスクトップ画面の外へ出た場合は、デスクトップ画面内に収まるように 再設定(上書き)します。これで、ウインドウの移動中にデスクトップ画面の外へ出ないように制御 出来ます。 ・以上。おわり。→下の『参考URL』もどうぞ。
お礼
ありがとうございます。 やっとこさ出来ました。 winproc内のWM_MOVEで oldRect = newRect GetWindowRect(newRect) としてひとつ前のRECTを保存 DefWinProcのWM_NEXTSIZE(ドラッグ終了後、自動移動後に送られてくる) で一つ前の位置newRectに SetWindowRect です。 ありがとうございました。
補足
位置newRect→位置oldRect ↓↓↓↓↓↓↓↓↓