ClientToScreen と GetCursorPos なら。。。
この場合は、マウスポインタの位置と同期させて
ウィンドウ位置を変えているので、逐次ウィンドウ座標系が
変わることになります(相対的には同じだけど)
ので、頭の中が整理しやすいほうを使えばよいかと。。。
アドバイスをしていただいた皆様、長い間レスできなくて本当にすいませんでした。
別にやらなければならない作業が入りまして、そちらに追われていました。
>SetCapture()した時点でのマウスの位置とウィンドウの位置の差分だけ記憶しておけばOKだ
>と思いますが。
ウィンドウの位置は以下のようにOnMove()内で取得すればいいのでしょうか?
void CMainFrame::OnMove()
{
// TODO : ここにコマンド ハンドラ コードを追加します。
m_bMoving = TRUE;
CPoint point;
::GetCursorPos(&point);
m_pointOld = point;
SetCapture();
CRect rect;
GetWindowRect(&rect);
m_DistanceLeft = (rect.left - point.x);
m_DistanceTop = (rect.top - point.y);
}
> ウィンドウの位置は以下のようにOnMove()内で取得すればいいのでしょうか?
取得してどうだったでしょうか?
ココで取得すればいいかどうかは、動作させればわかると思うのですが..。
SetCapture / WM_MOUSEMOVE では、自プロセスで作成したウィンドウ上に
マウスカーソルがあるときしかマウス移動を追跡することはできないはずです。
#例外的に右ボタンを押したままの状態(ドラッグ中)ならウィンドウ外まで追跡できる
つまり、マウスカーソルをいきなり画面外にすっ飛ばした場合にはついていけない
可能性があると思います。
また、メニューを表示したときに目的の項目がメインウィンドウの外にあった場合、
#メニュー項目の数が多くてメニューの高さが画面縦幅を超えてしまっていたり、
#画面がスクリーン下方にあってメニューが上に伸びるケース
マウスを押して項目選択した時点で既に画面外なのでマウス移動が
検知できないんじゃないかと思います。
んで、マウス移動のトレースには、タイマを使って解決するケースが多々ありますね。
低級な解決方法と思われるかもしれませんが、カーソルを見失う可能性は回避できます。
WM_MOUSEMOVE でも厳密にピクセル単位で連続した軌跡が得られるわけではないので、
50ms くらいの WM_TIMER で GetCursorPos しても大差ないんじゃないかなぁ???
マウス移動が無くても CPU time を消費するけど、それもカスみたいなものだと思います
が...
>SetCapture / WM_MOUSEMOVE では、自プロセスで作成したウィンドウ上に
>マウスカーソルがあるときしかマウス移動を追跡することはできないはずです。
SetCapture のヘルプより
>マウスをキャプチャーしたウィンドウは、
>マウスカーソルがウィンドウの外側にあるときも、
>マウスの入力を受け取ります。
>#例外的に右ボタンを押したままの状態(ドラッグ中)ならウィンドウ外まで追跡できる
例外でもなんでもなく、そう処理しているからだと思うのですが。。。
>取得してどうだったでしょうか?
>ココで取得すればいいかどうかは、動作させればわかると思うのですが..。
すいません、OnMove()内で取得した後の使い方がよくわかりません。
m_DistanceLeft = (rect.left - point.x);
m_DistanceTop = (rect.top - point.y);
SetWindowPos()の引数として使えばいいのでしょうか?
>SetWindowPos()の引数として使えばいいのでしょうか?
使ってみてどうなりますか?
なんのために用意した変数ですか?
いわれるままにやるのではなく、なぜそうするのか考えてみてください
> すいません、OnMove()内で取得した後の使い方がよくわかりません。
> m_DistanceLeft = (rect.left - point.x);
> m_DistanceTop = (rect.top - point.y);
> SetWindowPos()の引数として使えばいいのでしょうか?
自動追尾モード(勝手に命名)がオンになったときのマウスカーソルの座標とウィンドウ座標の
位置関係を保つ場合を前提として『差分が要ります』と書込みしました。
動作させたいように使っていただけばよろしいかと思います。
たみあさん、どうもです。
>SetCapture のヘルプより
>
>>マウスをキャプチャーしたウィンドウは、
>>マウスカーソルがウィンドウの外側にあるときも、
>>マウスの入力を受け取ります。
これを、
「マウスカーソルがスクリーン上のどこにあってもマウスの入力を受け取る」
と解釈してしまう人が多いのでは?、と思ったので...
上記の記述は自アプリ上でだけ有効で、デスクトップ/他アプリ上のキャプチャは
できませんね。
例えば、ダイアログにボタンが配置されていて、
ボタンがマウスをキャプチャーしているとき、マウスがボタン外に出ても
ダイアログ上にあるならボタンに WM_MOUSEMOVE は飛んでくるけど、
ダイアログの外にまで出たら、WM_MOUSEMOVE は来なくなる。
まぁ、WM_MOUSEMOVE ハンドラでトレースメッセージを出せばすぐにわかる話ですけど。
キャプチャーしてあれば
ボタン押して、離すまでの間ならどこにあってもWM_MOUSEMOVEはきますよね。
この例の場合ドラッグ中のみの話なので、まず問題ないと思いますけど?
なにかボタンをクリックして(離して)、さらに何かあるまでの間のマウスの動きを
走査したいのならば、確かにWM_MOUSEMOVEでは問題ありです。
別スレッドが作ったウィンドウ上ではWM_MOUSEMOVEは来なかったとおもいます。
あ、ごめんなさい。勘違いしてた。
メニューなのね。ってことは選択したときボタンは離されているわけね。
で、そこからボタンを押すまでの間なのね。
ごめんなさい(平謝り)。
じゃあ、この操作をする前にマウスの位置に強引にウィンドウを移動して
TopMostにしておくってのはどうでしょ。
あれ、ごめんなさい>凸凹さん
ドラッグの処理しか書いたことなかったんで
勘違いしていました
それで、例外とおっしゃっていたのか。。。
で、この例ではなんでうまくいってるのだろう?
あれれ?
これってドラッグで移動の話だったんですか(@@)
メニューから[移動(M)]を選択(マウスを押して離す)したら、
マウスを放した状態のままで自動追尾、
もう一度マウスクリックしたら追尾解除、とか思ってました。
システムメニューの[移動(M)](画面左上アイコンをクリックして選択)の動作とは
どう違えたいんでしょ?
そのはずです<ドラッグで移動ではない
ので、なんでうまくいってるのでしょう?
このスレッドの質問と大きく話がずれますが。。。
いろいろ試しているうちに
「手放しドラッグ」というのをみつけてしまいました
・ウィンドウタイトルで右ボタンプレスする
・左ボタンプレスする
・右ボタンリリースする
・左ボタンリリースする
とやるとボタンを離したままウィンドウを動かせます
これって、バグですかねぇ?
それとも DefWindowProc がわざわざこうしているのだろうか。。。