none
PictureBox 控件Click事件和DragDrop冲突怎么办? RRS feed

  • 问题

  • 我把DragDrop放在MouseDown里,发现触发不了Click事件了,有什么办法区分开吗?

    是不是可以这样加以区别?:

    单机单击PictureBox并马上MouseUp的时候激活Click事件,

    单机单击PictureBox按住2秒后激活DragDrop实现拖拽。

    要怎么计算这个按住时间差呢?


    • 已编辑 Lacuz 2013年10月1日 3:57
    2013年10月1日 3:57

答案

  • using System;
    using System.Drawing;
    using System.Threading;
    using System.Windows.Forms;
     
    namespace test
    {
        public partial class Form1 : Form
        {
            /// <summary>
            /// 确认是否按下了鼠标左键
            /// </summary>
            private volatile bool flag = false;
            /// <summary>
            /// 读秒计数器
            /// </summary>
            private int counter = 0;
            /// <summary>
            /// 计算时间的线程
            /// </summary>
            private Thread th = null;
            /// <summary>
            /// 自动延时成功后触发代码
            /// </summary>
            private event Action<PictureBox> DelayTimeSuccess = null;
     
            public Form1()
            {
                InitializeComponent();
                DelayTimeSuccess += new Action<PictureBox>(Form1_DelayTimeSuccess);
            }
     
            void Form1_DelayTimeSuccess(PictureBox obj)
            {
     
                base.DoDragDrop(objDragDropEffects.Move);
            }
     
            private void Form1_Load(object senderEventArgs e)
            {
                this.pnlDeck.AllowDrop = true;
                this.pnlDeck.DragDrop += new DragEventHandler(this.Deck_DragDrop);
                this.pnlDeck.DragEnter += new DragEventHandler(this.Deck_DragEnter);
     
                for (int i = 1i <= 12i++)
                {
                    PictureBox p = new PictureBox
                    {
                        Name = "PicDeck" + i,
                        Size = new Size(110110),
                        Margin = new Padding(3),
                        SizeMode = PictureBoxSizeMode.Zoom,
                        Image = Image.FromFile("pic/" + i + ".jpg"),
                        Tag = Image.FromFile("pic/" + i + ".jpg"),
                    };
                    p.BorderStyle = BorderStyle.FixedSingle;
                    p.Click += new EventHandler(this.Deck_Click);
                    p.MouseDown += new MouseEventHandler(this.Deck_MouseDown);
                    p.MouseUp += new MouseEventHandler(this.Deck_MouseUp);
                    this.pnlDeck.Controls.Add(p);
                }
            }
     
            //选择图片
            private void Deck_Click(object senderEventArgs e)
            {
     
            }
     
            private void Deck_MouseDown(object senderMouseEventArgs e)
            {
                PictureBox p = sender as PictureBox;
                if (e.Button == MouseButtons.Right)
                {
                    this.richTextBox1.AppendText("单击鼠标右键模式\n");
                    p.Tag = null;
                    p.Text = string.Empty;
                    p.Image = null;
                }
                else
                {
                    //按下了左键
                    flag = true;
                    //读秒计数器初始化
                    counter = 0;
     
                    this.richTextBox1.AppendText("单击鼠标左键模式\n");
     
                    //启动事件,侦听是否左键按下了两秒
                    th = new Thread(() => 
                    {
                        while (flag && counter<2)
                        {
                            //延时1秒
                            Thread.Sleep(1000);
                            counter++;
                        }
                        if (flag && counter >= 2)
                        {
                            this.richTextBox1.AppendText("延时2秒,现在可以移动。\n");
                            this.Invoke(new MethodInvoker(() => 
                            {
                                DelayTimeSuccess(p);
                            }));
                        }
                    });
                    th.IsBackground = true;
                    th.Start();
                }
            }
     
            private void Deck_MouseUp(object senderMouseEventArgs e)
            {
                //松开了左键
                flag = false;
                //立即释放线程
                th.Abort();
                th = null;
            }
     
            private void Deck_DragDrop(object senderDragEventArgs e)
            {
                Point pt = this.pnlDeck.PointToClient(new Point(e.Xe.Y));
                PictureBox childAtPoint = this.pnlDeck.GetChildAtPoint(ptas PictureBox;
                if (childAtPoint != null)
                {
                    Image item1;
                    Image item2;
     
                    if (e.Data.GetDataPresent(typeof(PictureBox)))
                    {
                        PictureBox data = e.Data.GetData(typeof(PictureBox)) as PictureBox;
                        item1 = childAtPoint.Tag as Image;
                        item2 = data.Tag as Image;
                        childAtPoint.Tag = item2;
                        data.Tag = item1;
                        if (item1 == null)
                        {
                            data.Image = null;
                        }
                        else
                        {
                            data.Image = item1;
                        }
                        if (item2 == null)
                        {
                            childAtPoint.Image = null;
                        }
                        else
                        {
                            childAtPoint.Image = item2;
                        }
                    }
                }
            }
     
            private void Deck_DragEnter(object senderDragEventArgs e)
            {
                this.richTextBox1.AppendText("拖拽模式\n");
                if (e.Data.GetDataPresent(typeof(PictureBox)))
                {
                    e.Effect = DragDropEffects.Move;
                }
                else
                {
                    e.Effect = DragDropEffects.None;
                }
            }
        }
    }
    2013年10月1日 12:05
    版主

全部回复

  • 可以给出:

    1)你的项目情景?

    2)你需要完成什么任务?

    3)你的完整代码(最好上传到SkyDrive)。

    谢谢。


    Click For donating:Free Rice For the poor
    For spamming-sender issues, you can either report it at Microsoft Spamming Issue, or just find "Report Spam Here+Number" at Forum Issue;You can also find "Verify Your Account+Number" at "Forum Issue", where you can submit to be confirmed to paste links or images.
    For more things to talk about? StackOverFlow is your choice.

    2013年10月1日 4:09
    版主
  • using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace test { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { this.flowLayoutPanel1.AllowDrop = true; this.flowLayoutPanel1.DragDrop += new DragEventHandler(this.Deck_DragDrop); this.flowLayoutPanel1.DragEnter += new DragEventHandler(this.Deck_DragEnter); for (int i = 1; i <= 12; i++) { PictureBox p = new PictureBox { Name = "PicDeck" + i, Size = new Size(110, 110), Margin = new Padding(3), SizeMode = PictureBoxSizeMode.Zoom //Image = Image.FromFile(i + ".gif") }; p.BorderStyle = BorderStyle.FixedSingle; p.MouseDown += new MouseEventHandler(this.Deck_MouseDown); p.Click += new EventHandler(this.Deck_Click); this.flowLayoutPanel1.Controls.Add(p); } } //选择图片 private void Deck_Click(object sender, EventArgs e) { MessageBox.Show("弹出选择窗"); } private void Deck_MouseDown(object sender, MouseEventArgs e) { PictureBox p = sender as PictureBox; if (e.Button == MouseButtons.Right) { p.Tag = null; p.Text = string.Empty; p.Image = null; } else { base.DoDragDrop(p, DragDropEffects.Move); } } //实现拖拽后两位置的图片位置交换 private void Deck_DragDrop(object sender, DragEventArgs e) { //已实现 } private void Deck_DragEnter(object sender, DragEventArgs e) {

               if (e.Data.GetDataPresent(typeof(PictureBox)))
                {
                    e.Effect = DragDropEffects.Move;
                }
                else
                {
                    e.Effect = DragDropEffects.None;
                }

    } } }

    项目牵涉的东西太多,我提取出来还原了一下,差不多是这个样子的。我要实现动态生成的12个图片控件,可以单击选择图片,还可以互相拖拽对换位置。

    现在就是单击和拖拽2个事件起冲突,我想单击选择图片选择不了,会直接激活拖拽的事件。



    • 已编辑 Lacuz 2013年10月1日 5:47
    2013年10月1日 5:43
  • 楼主你好:

    【问题原因】

    MouseDown发生在你一瞬间按下鼠标某个键的时候;同时按下的时候也触发了Click事件,这两个事件非常接近,以至于几乎是同时发生,你肉眼很难甄别。

    【解决方案】

    建议你在Click之后使用延时技术,此外结合考虑按键不到两秒的情况,所以可以统一放于一个MouseDown事件进行处理(针对同一个对象):

    1)在MouseDown的“else”部分,直接定义一个后台线程,其中里边判断flag是否为true,如果true,表示已经松开,直接退出线程。否则Thread.Sleep(1000),同时定义一个计数器计数,当计数器变量>=2的时候,直接调用DoDragDrop方法即可。当然,在MouseUp事件中判断松开鼠标左键,直接把flag设置为true。

    2)参考代码:

     public partial class Form1 : Form
        {
           private bool flag = false;
           private Thread th = null;
           private int counter = 0;
    
            private void Deck_MouseDown(object sender, MouseEventArgs e)
            {
                PictureBox p = sender as PictureBox;
                if (e.Button == MouseButtons.Right)
                {
                    p.Tag = null;
                    p.Text = string.Empty;
                    p.Image = null;
                }
                else
                {
                    MessageBox.……;
    counter = 0; flag = false; th = new Thread(()=> { while(counter<2 && !flag) { Thread.Sleep(1000); counter+=1; } if(counter>=2 && !flag) { //Do drag and drop } }); } } }

    Click For donating:Free Rice For the poor
    For spamming-sender issues, you can either report it at Microsoft Spamming Issue, or just find "Report Spam Here+Number" at Forum Issue;You can also find "Verify Your Account+Number" at "Forum Issue", where you can submit to be confirmed to paste links or images.
    For more things to talk about? StackOverFlow is your choice.



    2013年10月1日 6:08
    版主
  • 奇怪,为啥我进不了新建的进程。。
    • 已编辑 Lacuz 2013年10月1日 6:59
    2013年10月1日 6:59
  • 你调用启动方法了吗?Start?

    Click For donating:Free Rice For the poor
    For spamming-sender issues, you can either report it at Microsoft Spamming Issue, or just find "Report Spam Here+Number" at Forum Issue;You can also find "Verify Your Account+Number" at "Forum Issue", where you can submit to be confirmed to paste links or images.
    For more things to talk about? StackOverFlow is your choice.

    2013年10月1日 7:00
    版主
  • 发现base.DoDragDrop(p, DragDropEffects.Move);在这里面执行不了。。执行的到,但是拖拽不了,不知道什么原因
     if(counter>=2 && !flag)
                       {
                            //Do drag and drop
                       }
    放在线程之外能拖拽
    • 已编辑 Lacuz 2013年10月1日 7:43
    2013年10月1日 7:43
  • 哦,那看来你必须放入主线程中,这样修改看看:

     public partial class Form1 : Form
        {
           private bool flag = false;
           private Thread th = null;
           private int counter = 0;
           private event Action<PictureBox> MouseDownComplete=null;

    private void Form1_Load()
    {
    MouseDownComplete += new Action((arg)=>
    {
    base.DoDragDrop(arg,DragDropEffects.Move);
    });
    }
    private void Deck_MouseDown(object sender, MouseEventArgs e) { PictureBox p = sender as PictureBox; if (e.Button == MouseButtons.Right) { p.Tag = null; p.Text = string.Empty; p.Image = null; } else { MessageBox.……; counter = 0; flag = false; th = new Thread(()=> { while(counter<2 && !flag) { Thread.Sleep(1000); counter+=1; }
    if(counter>=2 && !flag)
                       {
                            //Raise the event
    MouseDownComplete(sender as PictureBox);
                       }
                    });
                     th.IsBackground=true;
                     th.Start();
                     
                }
            }
        }

    Click For donating:Free Rice For the poor
    For spamming-sender issues, you can either report it at Microsoft Spamming Issue, or just find "Report Spam Here+Number" at Forum Issue;You can also find "Verify Your Account+Number" at "Forum Issue", where you can submit to be confirmed to paste links or images.
    For more things to talk about? StackOverFlow is your choice.

    2013年10月1日 7:58
    版主
  • 这样子会提前走完整个函数,来不及等另个线程走完counter>=2
    2013年10月1日 8:15
  • 代码已经修改,请看看。谢谢!

    Click For donating:Free Rice For the poor
    For spamming-sender issues, you can either report it at Microsoft Spamming Issue, or just find "Report Spam Here+Number" at Forum Issue;You can also find "Verify Your Account+Number" at "Forum Issue", where you can submit to be confirmed to paste links or images.
    For more things to talk about? StackOverFlow is your choice.

    2013年10月1日 8:24
    版主
  • 拖拽还是生效不了,代码访问的到,也不出错,就是交换不了了
    2013年10月1日 8:42
  • 你把项目完整打包上传到SkyDrive,或者其它可以下载的网盘中,我下载看看。

    Click For donating:Free Rice For the poor
    For spamming-sender issues, you can either report it at Microsoft Spamming Issue, or just find "Report Spam Here+Number" at Forum Issue;You can also find "Verify Your Account+Number" at "Forum Issue", where you can submit to be confirmed to paste links or images.
    For more things to talk about? StackOverFlow is your choice.

    2013年10月1日 8:43
    版主
  • http://pan.baidu.com/s/13O2rY

    SkyDrive我这很慢,放到百度盘里了,耽误你这么多时间,真是抱歉,先谢谢了

    2013年10月1日 10:05
  • using System;
    using System.Drawing;
    using System.Threading;
    using System.Windows.Forms;
     
    namespace test
    {
        public partial class Form1 : Form
        {
            /// <summary>
            /// 确认是否按下了鼠标左键
            /// </summary>
            private volatile bool flag = false;
            /// <summary>
            /// 读秒计数器
            /// </summary>
            private int counter = 0;
            /// <summary>
            /// 计算时间的线程
            /// </summary>
            private Thread th = null;
            /// <summary>
            /// 自动延时成功后触发代码
            /// </summary>
            private event Action<PictureBox> DelayTimeSuccess = null;
     
            public Form1()
            {
                InitializeComponent();
                DelayTimeSuccess += new Action<PictureBox>(Form1_DelayTimeSuccess);
            }
     
            void Form1_DelayTimeSuccess(PictureBox obj)
            {
     
                base.DoDragDrop(objDragDropEffects.Move);
            }
     
            private void Form1_Load(object senderEventArgs e)
            {
                this.pnlDeck.AllowDrop = true;
                this.pnlDeck.DragDrop += new DragEventHandler(this.Deck_DragDrop);
                this.pnlDeck.DragEnter += new DragEventHandler(this.Deck_DragEnter);
     
                for (int i = 1i <= 12i++)
                {
                    PictureBox p = new PictureBox
                    {
                        Name = "PicDeck" + i,
                        Size = new Size(110110),
                        Margin = new Padding(3),
                        SizeMode = PictureBoxSizeMode.Zoom,
                        Image = Image.FromFile("pic/" + i + ".jpg"),
                        Tag = Image.FromFile("pic/" + i + ".jpg"),
                    };
                    p.BorderStyle = BorderStyle.FixedSingle;
                    p.Click += new EventHandler(this.Deck_Click);
                    p.MouseDown += new MouseEventHandler(this.Deck_MouseDown);
                    p.MouseUp += new MouseEventHandler(this.Deck_MouseUp);
                    this.pnlDeck.Controls.Add(p);
                }
            }
     
            //选择图片
            private void Deck_Click(object senderEventArgs e)
            {
     
            }
     
            private void Deck_MouseDown(object senderMouseEventArgs e)
            {
                PictureBox p = sender as PictureBox;
                if (e.Button == MouseButtons.Right)
                {
                    this.richTextBox1.AppendText("单击鼠标右键模式\n");
                    p.Tag = null;
                    p.Text = string.Empty;
                    p.Image = null;
                }
                else
                {
                    //按下了左键
                    flag = true;
                    //读秒计数器初始化
                    counter = 0;
     
                    this.richTextBox1.AppendText("单击鼠标左键模式\n");
     
                    //启动事件,侦听是否左键按下了两秒
                    th = new Thread(() => 
                    {
                        while (flag && counter<2)
                        {
                            //延时1秒
                            Thread.Sleep(1000);
                            counter++;
                        }
                        if (flag && counter >= 2)
                        {
                            this.richTextBox1.AppendText("延时2秒,现在可以移动。\n");
                            this.Invoke(new MethodInvoker(() => 
                            {
                                DelayTimeSuccess(p);
                            }));
                        }
                    });
                    th.IsBackground = true;
                    th.Start();
                }
            }
     
            private void Deck_MouseUp(object senderMouseEventArgs e)
            {
                //松开了左键
                flag = false;
                //立即释放线程
                th.Abort();
                th = null;
            }
     
            private void Deck_DragDrop(object senderDragEventArgs e)
            {
                Point pt = this.pnlDeck.PointToClient(new Point(e.Xe.Y));
                PictureBox childAtPoint = this.pnlDeck.GetChildAtPoint(ptas PictureBox;
                if (childAtPoint != null)
                {
                    Image item1;
                    Image item2;
     
                    if (e.Data.GetDataPresent(typeof(PictureBox)))
                    {
                        PictureBox data = e.Data.GetData(typeof(PictureBox)) as PictureBox;
                        item1 = childAtPoint.Tag as Image;
                        item2 = data.Tag as Image;
                        childAtPoint.Tag = item2;
                        data.Tag = item1;
                        if (item1 == null)
                        {
                            data.Image = null;
                        }
                        else
                        {
                            data.Image = item1;
                        }
                        if (item2 == null)
                        {
                            childAtPoint.Image = null;
                        }
                        else
                        {
                            childAtPoint.Image = item2;
                        }
                    }
                }
            }
     
            private void Deck_DragEnter(object senderDragEventArgs e)
            {
                this.richTextBox1.AppendText("拖拽模式\n");
                if (e.Data.GetDataPresent(typeof(PictureBox)))
                {
                    e.Effect = DragDropEffects.Move;
                }
                else
                {
                    e.Effect = DragDropEffects.None;
                }
            }
        }
    }
    2013年10月1日 12:05
    版主
  • 终于可以了!谢谢
    2013年10月1日 13:01