none
マウスのクリック状態を知る方法を教えて下さい。 RRS feed

  • 質問

  • Visual Studio Community 2017 Version15.7.2 を使っております。

    複数の方眼上に並べたラベルがありそれをクリックで選んだ時に条件に合わせて色や値を付与しています。毎回のクリックだででなく

    MouseMove +「左クリックボタンが押されていれば」の条件でクリックを押したままなぞればどんどん描いていく、同様に

    MouseMove +「右クリックボタンが押されていれば」の条件でクリックを押したままなぞればどんどんリセットされていく様にしたいです。

    //現在どのマウスボタンが押されているか調べる
    if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)
    {
        処理
    }

    というのを MouseMove イベント内に貼ってみたのですが動きからして「状態」ではなく毎回クリックしなければなりませんでした。

    押したままなぞれば曲線などを描くようにどんどん実行したり、消したりしたい時どのように実装すればよいのでしょうか。

    なにかよい取得するプロパティなどはあるのでしょうか。

    どうかよろしくお願い致します。



    調べている中で

    if (e.Button == MouseButtons.Left){処理}

    これはどうも押されている時(状態を示す)ようなのですがこれを貼ると e.Button

    の箇所にエラーでます。

    using System.Windows.Forms;

    で使えるようなのですが何が足りないのでしょうか。

    使えた場合これで解決できるのでしょうか。

    2019年5月16日 6:09

すべての返信

  • 左と右の両方が押されていた場合はどういう動作になるのだろう…?

    > if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)

    if (MouseButtons.HasFlag(MouseButtons.Left))
    の方が分かりやすいかも知れません。(意味は同じ)

    > 毎回クリックしなければなりませんでした。

    いわゆるドラッグ操作の場合、マウスボタンを離すまでの間、MouseMove イベントは「最初に MouseDown されたコントロール」が受け取り続けます。

    そのため、Label を敷き詰めたような画面設計だと扱いにくいかもしれません。複数の Label を使う代わりに、大きな一つの PictureBox を用意して、その Paint イベントを通じて方眼状に描画するようにすれば、PictureBox の MouseMove だけで処理できるようになるでしょう。

    Label を敷き詰める画面構成を変更したくないのであれば、下記のような方法もあります。

    1. MouseMove のイベントハンドラはいったん取り除く。
    2. デザイン時に、各 Label の AllowDrop プロパティを true にしておく。
    3. Label 群の MouseDown イベントで、自身の DoDragDrop メソッドを呼び出す。
    4. Label 群の DragEnter / DragOver イベントで、MouseButtons の状態に応じて色や値を付与する。

    2019年5月16日 6:31
  • いろいろアプローチはあると思いますが、継承したラベルを作成する方法はどうでしょう。

    using System;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    class GridLabel : Label
    {
        const int
            WM_MOUSEFIRST = 0x0200,
            WM_MOUSELAST = 0x020A;
    
        [StructLayout(LayoutKind.Sequential)]
        struct POINT
        {
            public int x;
            public int y;
    
            public POINT(Point pt) {
                this.x = pt.X;
                this.y = pt.Y;
            }
        }
    
        [DllImport("User32", CharSet = CharSet.Auto)]
        static extern IntPtr WindowFromPoint(POINT pt);
    
        protected override void WndProc(ref Message m) {
            if (m.Msg >= WM_MOUSEFIRST && m.Msg <= WM_MOUSELAST) {
                POINT ps = new POINT(Control.MousePosition);
                IntPtr hwnd = WindowFromPoint(ps);
                GridLabel lbl = Control.FromHandle(hwnd) as GridLabel;
                if (lbl != null && this.Parent == lbl.Parent) {
                    var buttons = Control.MouseButtons;
                    if (buttons.HasFlag(MouseButtons.Right)) {
                        lbl.BackColor = Color.Empty;
                    } else if (buttons.HasFlag(MouseButtons.Left)) {
                        lbl.BackColor = Color.Red;
                    }
                }
            }
            base.WndProc(ref m);
        }
    }
    

    マウスの位置の直下のウインドウハンドルを求め、コントロールを取得し、GridLabel で親が同一なら処理を行っています。

    2019年5月16日 9:33
  • ご回答ありがとうございます。

    Label 群の MouseDown イベントで、自身の DoDragDrop メソッドを呼び出す。

    というところでつまづいています。いろいろ調べて試してみます。

    2019年5月16日 9:42