ボタンクリック中のマウス位置(動き)の取得

[戻る]
でんでん 2007/02/01(木) 16:35:09
VC++.net 2002 MFC でプログラミングしています

ボタンを押しながらマウスを動作させた時のマウスの位置の取得はどうすればよいので
しょうか?(ボタンはできればツールバー上のボタン)あるボタンを左クリックしなが
ら、マウスを上に動かすと、その動きに合わせて例えば数値が増加する。みたいなのを
考えています。VBではbottum click とmouse moveでできましたが、VC++ではボタンを押
している間(クリック中)はOnMouseMoveが働いていないようです。 GetCursorPosとタ
イマーの組み合わせしかないのでしょうか?

長文すいません。

Blue 2007/02/01(木) 16:52:57
ボタンをサブクラス化して、
(OnLButtonDownで押していますよフラグを立てて)
OnMouseMoveから親ウィンドウにメッセージを投げるとか。

Blue 2007/02/01(木) 17:19:15
> (OnLButtonDownで押していますよフラグを立てて)
これいらないかも。ボタンの上のMouseMoveイベントは必要ないのであれば、
こんな感じでしょうかね。

// ボタンをサブクラス化して、親のコントロールメンバ変数として持たせる

void CMyButton::OnMouseMove(UINT nFlags, CPoint point) 
{
    CRect rct;
    this->GetClientRect(&rct);
    // ボタン上の座標でない場合
    if (!rct.PtInRect(point))
    {
        CWnd* pWnd = this->GetParentOwner();
        if (pWnd)
        {
            // 親座標に変換
            this->MapWindowPoints(pWnd, &point, 1);
            // 親にOnMouseMoveイベントを通知
            pWnd->SendMessage(WM_MOUSEMOVE, nFlags,
                              MAKELPARAM(point.x, point.y));
        }
    }
    CButton::OnMouseMove(nFlags, point);
}

Blue 2007/02/01(木) 17:30:37
よく考えたらダメかも。
上のコードだとボタンを押していれば、ボタン以外の位置であれば
どこにあっても親にWM_MOUSEMOVEを投げちゃいますね。

つまり、親ウィンドウの外でも、別のコントロール上にマウスカーソルがあっても
WM_MOUSEMOVEイベントが発生してしまいます。

前者は親ウィンドウの領域をとってPtInRectで判定すれば出来そうですが、
後者はほかのコントロールの上にあるって事までは(ボタン側では)判定できませんね。
(親側から判定するしかないかな。)

でんでん 2007/02/01(木) 19:16:35
お返事ありがとうございます。
初心者なのでなかなか理解できないのですが、親にOnMouseMoveイベントを通知とありま
すがこれをどのように親側で受け取ればよいのでしょうか?
変な質問していたら申し訳ありません。

Blue 2007/02/01(木) 19:47:29
どこまでできていますか?
CButtonを継承したクラスをダイアログ(だと思う)のメンバ変数にしてWM_MOUSEMOVEをハ
ンドルして、17:19:15のコードを貼り付け、
そのクラスをコントロールメンバ変数としてダイアログのメンバに追加までできていま
すか?

そしたらダイアログクラスのWM_MOUSEMOVEをハンドルしたOnMouseMoveを追加すれば
勝手にそこに送られてくるはずです。

確認用
void CXXXXDlg::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出し
ます。
    TRACE2("%d,%d\n", point.x, point.y);
    CDialog::OnMouseMove(nFlags, point);
}

これで、デバッグ実行すると「出力」ウィンドウに座標が出力されます。

でんでん 2007/02/01(木) 22:26:50
返信ありがとうございます。
@Buttonをダイアログに1つつくる。(te2Dlg.cpp)
Aクラスの追加ー>MSCクラスで
基本クラスCBottun, クラス名subclassとする
Bsubclassで
void subslass::OnMouseMove(UINT nFlags, CPoint point) 
{
   
....略17:19:15のコード

    CButton::OnMouseMove(nFlags, point);
}
CダイアログでButtonを選択して変数の追加
変数の種類CButton 名前m_btn1
D確認用に
void Cte2Dlg::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出し
ます。
    CString str;
    str.Format("%d", point.y);
    m_edit1.SetWindowText(str);   


    CDialog::OnMouseMove(nFlags, point);
}
で表示。(edicontrol上に表示しています)

で結果は通常のCte2Dlg::OnMouseMoveとまったく同じです。

なんか抜けてますよね?

Blue 2007/02/01(木) 23:05:09
>変数の種類CButton 名前m_btn1
が間違っているようです。

変数の追加のダイアログではおそらくCButtonしか選べないですが
ここをサブクラス化したクラスにしないとだめです。

まぁやり直すのは面倒ですので、
ダイアログのヘッダファイルに
・#include "subclass.h" を追加
・CButton m_btn1; を subclass m_btn1; に変更
としてみてください。

でんでん 2007/02/01(木) 23:43:23
ご指摘のようにしてみましたが、通常のCte2Dlg::OnMouseMoveとまったく同じでした。
はじめから作り直してもみたのですが。。。
ボタンを押さなくてもカーソル位置が帰ってきます。

ほかに何かすべきことがあるのでしょうか?

Blue 2007/02/01(木) 23:53:01
>CダイアログでButtonを選択して変数の追加
が根本的に間違っているのかな?

「コントロール変数」ってのにチェックを入れて
該当のボタンのコントロールと結びついていないと意味ないです。

ソースコード中に

DDX_Control(pDX, IDC_BUTTON1, m_btn1);

のような記述があるか確認してください。
ないのであれば手動で

CDialog::DoDataExchange(pDX);

のしたに入れてください。

で確認時ですが、
>void subslass::OnMouseMove(UINT nFlags, CPoint point) 
の関数内の記述のどこかにブレイクポイント(F9)でもおいて
デバッグ実行してちゃんととまるかやってみてください。

ぬふや 2007/02/01(木) 23:58:26
てーかさ、キャプチャすればいいだけじゃないの?
キャプチャ設定したウィンドウ上にカーソルが無くてもMOVEメッセージがカーソルに
飛んで来るんだし、要するにドラッグ処理なわけだから。

でんでん 2007/02/02(金) 00:19:12
[[解決]]
うまくいきました。ありがとうございます。
最後のところはそのように以前もしていたのですが、とにかくできました。

これを元にいろいろ先の処理を考えたいと思います。一歩前進しました。
また、お尋ねすることがあると思いますがよろしくお願いします。

迅速なお返事大変感謝しております。

古いスレッドには追加発言できません。