2015年7月24日金曜日

PictureBoxで右クリック等を読み取る

C#のPictureBoxでクリック状態を検出する場合、Clickイベントでは右クリックを検出することは出来ません。右クリックを読み込むにはMouseDownイベントを使用する必要があります。

using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace PictureBoxClick {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();

            pictureBox1.MouseDown += pictureBox1_MouseDown;
            pictureBox1_MouseDown(pictureBox1, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0));
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e) {
            bool LeftClick = MouseButtons.None != (e.Button & MouseButtons.Left);
            bool RightClick = MouseButtons.None != (e.Button & MouseButtons.Right);
            bool MiddleClick = MouseButtons.None != (e.Button & MouseButtons.Middle);
            bool XButton1Click = MouseButtons.None != (e.Button & MouseButtons.XButton1);
            bool XButton2Click = MouseButtons.None != (e.Button & MouseButtons.XButton2);
            Point Location = e.Location;

            Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);

            using (Graphics gra = Graphics.FromImage(bmp))
            using (Font font = new Font("MS ゴシック", 12)) {
                gra.Clear(Color.Black);

                StringBuilder sb = new StringBuilder();

                sb.Append("Left    :" + LeftClick + "\n");
                sb.Append("Right   :" + RightClick + "\n");
                sb.Append("Middle  :" + MiddleClick + "\n");
                sb.Append("XButton1:" + XButton1Click + "\n");
                sb.Append("XButton2:" + XButton2Click + "\n");
                sb.Append("Location:" + Location + "\n");

                gra.DrawString(sb.ToString(), font, Brushes.White, new PointF());
            }

            if (pictureBox1.Image != null) {
                pictureBox1.Image.Dispose();
            }
            pictureBox1.Image = bmp;
        }
    }
}

Leftは左、Rightは右、Middleはホイール、XButton1は戻るボタン、XButton2は進むボタン が割り当てられています。またこれらはMouseButtons列挙体のORされた値ですし、実際にnew MouseEventArgsで各ボタンをORして渡せば複数のボタンクリック状態を引数に与えることができます。しかし、実際の動作においては複数ボタンをクリックした場合、クリックした順番で複数回のイベントが発生します。これはクリックしたタイミングの問題というより、内部処理の問題のようです。例えば、user32.dllを使用して左クリックと右クリックをORして同時に行わせた場合、2回のイベントが発生します。基本的にMouseDownイベントだけではマウスの同時押しによるファンクションは行えないと考えたほうがいいでしょう。

どうしても同時押しを検出したい場合は以下のようにします。

using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace PictureBoxClick {
    public partial class Form1 : Form {
        bool LeftClick, RightClick, MiddleClick, XButton1Click, XButton2Click;

        public Form1() {
            InitializeComponent();

            pictureBox1.MouseDown += pictureBox1_MouseDown;
            pictureBox1.MouseUp += pictureBox1_MouseUp;
            pictureBox1_MouseDown(pictureBox1, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0));
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e) {
            System.Diagnostics.Debug.WriteLine(e.Button.ToString());

            if (MouseButtons.None != (e.Button & MouseButtons.Left)) {
                LeftClick = true;
            }

            if (MouseButtons.None != (e.Button & MouseButtons.Right)) {
                RightClick = true;
            }

            if (MouseButtons.None != (e.Button & MouseButtons.Middle)) {
                MiddleClick = true;
            }

            if (MouseButtons.None != (e.Button & MouseButtons.XButton1)) {
                XButton1Click = true;
            }

            if (MouseButtons.None != (e.Button & MouseButtons.XButton2)) {
                XButton2Click = true;
            }

            Draw();
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e) {
            System.Diagnostics.Debug.WriteLine(e.Button.ToString());

            if (MouseButtons.None != (e.Button & MouseButtons.Left)) {
                LeftClick = false;
            }

            if (MouseButtons.None != (e.Button & MouseButtons.Right)) {
                RightClick = false;
            }

            if (MouseButtons.None != (e.Button & MouseButtons.Middle)) {
                MiddleClick = false;
            }

            if (MouseButtons.None != (e.Button & MouseButtons.XButton1)) {
                XButton1Click = false;
            }

            if (MouseButtons.None != (e.Button & MouseButtons.XButton2)) {
                XButton2Click = false;
            }

            Draw();
        }

        void Draw() {

            Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);

            using (Graphics gra = Graphics.FromImage(bmp))
            using (Font font = new Font("MS ゴシック", 12)) {
                gra.Clear(Color.Black);

                StringBuilder sb = new StringBuilder();

                sb.Append("Left    :" + LeftClick + "\n");
                sb.Append("Right   :" + RightClick + "\n");
                sb.Append("Middle  :" + MiddleClick + "\n");
                sb.Append("XButton1:" + XButton1Click + "\n");
                sb.Append("XButton2:" + XButton2Click + "\n");

                gra.DrawString(sb.ToString(), font, Brushes.White, new PointF());
            }

            if (pictureBox1.Image != null) {
                pictureBox1.Image.Dispose();
            }
            pictureBox1.Image = bmp;
        }
    }
}

このように、DownでフラグをTrueにし、UpでFalseにすれば、そのフラグを確認することにより任意のタイミングでマウス状態を獲得できます。ただ、この方法でも検出出来ない場合があることに注意が必要です。僕の環境では左・中・右の同時押しは検出できましたが、戻る・進む・右の同時押しは検出できませんでした。
そもそもマウスボタンの同時押しなど通常の動作状態ではありませんから、余程の理由がない限りは使用するべきではないと思います。

0 件のコメント:

コメントを投稿