MFCでSDIのアプリケーションを作成しています。
開発環境はVisualC++7.0/Windows2000です。
Windowのメニューに新規で[移動(M)]を追加して、[移動(M)]を選択するとマウスの動きにあわ
せてWindowが動くようにしたいのですが、どのようにしていいのかわかりません。
メニューの[移動(M)]を選択したときに呼び出される関数が
void CMainFrame::OnMove()
{
// TODO : ここにコマンド ハンドラ コードを追加します。
}
なのですが、この関数内でどのようにすればいいのかわかりません。
お手数ですが、初心者のため簡単に説明していただきたいと思います。
宜しくお願いします。
その移動状態を解除(固定)する動作はどうするのでしょう
マウスで移動中に左クリックが押されると解除するようにしたいです。
以下の処理を行います。
1) 現在のマウスカーソル位置を記録
2) OnMouseMove内で新しいカーソル位置と直前のカーソル位置の差を求める
3) 求めた差の分だけSetWindowPosで移動させる。
> お手数ですが、初心者のため簡単に説明していただきたいと思います。
「簡単に」じゃなくて「詳細に」ですよね(^^;
どんな初心者にでも分かるように説明するのは、とても骨の折れる仕事です。
しかし、MoriMoriさん個人に分かるように説明するのは、比較的容易だと予想されます。
というわけで、一般解を求めるようなことを仰らず、
MoriMoriさんが分からないところを質問してください。
早速、質問です。
1) 現在のマウスカーソル位置を記録
これはGetCursorPos()で取得できると思うのですが、GetCursorPos()はOnMove()内で使えば
いいのでしょうか?
> これはGetCursorPos()で取得できると思うのですが、GetCursorPos()はOnMove()内で使え
ば
> いいのでしょうか?
よいと思います。
あとOnMove()内で行う処理は、『ただ今マウスの動きに合わせてウィンドウを移動するモード
です』を表すフラグを立てる事ですね。
で、マウスが動いた時にフラグが立っていたらウィンドウも一緒に移動します。
左マウスボタンが押されたらフラグをリセットします。
こんな感じでどうでしょう?
みなさんアドバイスありがとうございます。
以下のようにしてコンパイルは通るのですが、うまく動きません。
OnMouseMove()の中での処理が間違っているのでしょうか?
>OnMove()内で行う処理は、『ただ今マウスの動きに合わせてウィンドウを移動するモード
>です』を表すフラグを立てる事ですね。
void CMainFrame::OnMove()
{
m_bMoving = TRUE;
CPoint point;
::GetCursorPos(&point);
m_pointOld = point;
}
>2) OnMouseMove内で新しいカーソル位置と直前のカーソル位置の差を求める
>3) 求めた差の分だけSetWindowPosで移動させる。
void CMainFrame::OnMouseMove(UINT nFlags, CPoint point)
{
if(m_bMoving == TRUE)
{
CPoint point;
::GetCursorPos(&point);
m_pointNew = point;
CRect rect;
GetWindowRect(&rect);
rect.left = (m_pointNew.x - m_pointOld.x);
rect.right = (m_pointNew.x - m_pointOld.x);
rect.top = (m_pointNew.y - m_pointOld.y);
rect.bottom = (m_pointNew.y - m_pointOld.y);
SetWindowPos(&wndTopMost, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_SHOWWINDOW);
}
CFrameWnd::OnMouseMove(nFlags, point);
}
>左マウスボタンが押されたらフラグをリセットします。
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bMoving = FALSE;
CFrameWnd::OnLButtonDown(nFlags, point);
}
SetWindowPosには移動量ではなくて
画面上の左上座標とサイズを指定します。
たとえばleftは次のようになります。
rect.left += (m_pointOld.x - m_pointNew.x);
OnMouseMove()を以下のような変えてみましたが、うまく動きません。
デバックしてみると、OnMouseMove()がマウスを動かしても呼ばれません。
マウスを動かしたときにOnMouseMove()は自動的に呼ばれるのではないのでしょうか?
void CMainFrame::OnMouseMove(UINT nFlags, CPoint point)
{
if(m_bMoving == TRUE)
{
CPoint point;
::GetCursorPos(&point);
m_pointNew = point;
CRect rect;
GetWindowRect(&rect);
rect.left += (m_pointOld.x - m_pointNew.x);
rect.right += (m_pointOld.x - m_pointNew.x);
rect.top += (m_pointOld.y - m_pointNew.y);
rect.bottom += (m_pointOld.y - m_pointNew.y);
SetWindowPos(&wndTopMost, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_SHOWWINDOW);
}
CFrameWnd::OnMouseMove(nFlags, point);
}
CMainFrameの”上で動かした時”には呼ばれると思います。
OnMouseMoveはクラスウィザードで追加しましたか?
rect.left += (m_pointOld.x - m_pointNew.x);
rect.right += (m_pointOld.x - m_pointNew.x);
rect.top += (m_pointOld.y - m_pointNew.y);
rect.bottom += (m_pointOld.y - m_pointNew.y);
参考までに、上記は下記のようにも書けます。
rect += m_pointOld - m_pointNew;
SetWindowPos(&wndTopMost, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_SHOWWINDOW);
また、移動するだけであれば、上記も下記の様に書けます。
SetWindowPos(NULL, rect.left, rect.top, 0, 0,
SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW);
>CMainFrameの”上で動かした時”には呼ばれると思います。
CMainFrameの”上で動かした時”とはどういうことなのでしょうか?
>OnMouseMoveはクラスウィザードで追加しましたか?
はい。
> CMainFrameの”上で動かした時”とはどういうことなのでしょうか?
すみません、メインのウィンドウの上にマウスカーソルがある時という事です。
CMainFrameでOnMouseMove()を作成したのですから、CMainFrame上にマウスカーソルが無いと
メッセージが来ません。
また、ビューなどがあるとその上にマウスカーソルがあってもメッセージは来なくて、ビューが
親にWM_MOUSEMOVEが来た事を知らせるようにしないとダメだったと思います。