【问题标题】:click and doubleclick event in c# not workingc#中的单击和双击事件不起作用
【发布时间】:2014-10-14 03:16:00
【问题描述】:

我的 C# 应用程序中有以下代码

第一个决定当用户双击图片时会发生什么。

 private void pictureDoubleClick(Object sender, EventArgs e)
        {
            PictureBox picture = (PictureBox)sender;
            Console.WriteLine(picture.ImageLocation);
            MessageBox.Show("Test");
        }

还有一个单击:

private void picutureClick(Object sender, EventArgs e)
        {
            PictureBox picture = (PictureBox)sender;

            if (picture.BorderStyle == BorderStyle.None)
            {
                picture.BorderStyle = BorderStyle.Fixed3D;
                picture.BackColor = Color.Red;
            }
            else
            {
                picture.BorderStyle = BorderStyle.None;
                picture.BackColor = Color.White;
            }
        }

我已经像这样调用了这两个函数:

box.Click += new System.EventHandler(this.picutureClick);
box.DoubleClick += new System.EventHandler(this.pictureDoubleClick);

但是我遇到了一个奇怪的错误,DoubleClick 事件不会被激活,使其工作的唯一方法是注释掉单击。无论我是否评论或取消评论 Doubleclick 事件,单击都有效。我四处寻找解决方案,但找不到任何解决我的问题的方法。

【问题讨论】:

  • 当你通过删除MessageBox.Show来测试它时会发生什么
  • 你在 ide 中调试它吗?
  • @L.B 没有任何反应,我添加了 MessageBox.Show 用于测试目的。
  • @icbytes 我正在 VS2012 中开发这个

标签: c# winforms double-click


【解决方案1】:

当您更改图片框的边框时,您有点重置点击事件。这就是为什么它不起作用并且仅切换一键事件的原因,如果您评论边框的更改它将开始工作......对不起,但我不知道为什么会发生这种情况,也不知道它是否对我的信息有帮助=/

【讨论】:

    【解决方案2】:

    这是一种奇怪的行为,更改图片框的BorderStyle 会阻止点击传播(Click 事件总是在DoubleClick 事件之前引发)。

    我真的不知道如何正确处理它,但我们可以做一些 hack 以使该功能正常工作。我们可以在Click 和DoubleClick 之间引入一个“滞后”,以使DoubleClick 在Click 之前被检查。

    这里我们使用Timer 来完成这项工作:

    private Timer _timer;
    private PictureBox _sender;
    private int _clicks;
    
    public Form1()
    {
        InitializeComponent();
    
        pictureBox.Click += picutureClick;
        pictureBox.DoubleClick += (s, e) =>
                                        {
                                            // do your double click handling
    
                                            _clicks = 0;
                                        };
    
        // this Interval comes from trail and error, it's a balance between lag and  
        // correctness. To play safe, you can use SystemInformation.DoubleClickTime,
        // but may introduce a bit long lagging after you click and before you
        // see the effects.
        _timer = new Timer {Interval = 75}; 
        _timer.Tick += (s, e) =>
                            {
                                if (_clicks < 2)
                                {
                                    ClickHandler(_sender);
                                }
    
                                _clicks = 0;
    
                                _timer.Stop();
                            };
    }
    
    private void picutureClick(Object sender, EventArgs e)
    {
        _clicks++;
        _sender = (PictureBox) sender;
    
        if (_clicks == 1)
        {
            _timer.Start();
        }
    }
    
    private void ClickHandler(PictureBox picture)
    {
        if (picture.BorderStyle == BorderStyle.None)
        {
            // this line is not thread safe, but you could comment out the .InvokeIfRequire()
            // and uncomment this line to have a look at your form's behavior
            //picture.BorderStyle = BorderStyle.Fixed3D;
            picture.InvokeIfRequired(c => (c as PictureBox).BorderStyle = BorderStyle.Fixed3D);
            picture.BackColor = Color.Red;
        }
        else
        {
            // same for this
            //picture.BorderStyle = BorderStyle.Fixed3D;
            picture.InvokeIfRequired(c => (c as PictureBox).BorderStyle = BorderStyle.None);
            picture.BackColor = Color.White;
        }
    }
    

    在上面的代码中,我使用了扩展方法来处理跨线程属性更新:

    public static void InvokeIfRequired(this Control c, Action<Control> action)
    {
        if (c.InvokeRequired)
        {
            c.Invoke(new Action(() => action(c)));
        }
        else
        {
            action(c);
        }
    }
    

    编辑:

    我上面使用的扩展方法是为了简化编写跨线程属性更新的代码。可以在此处找到有关此主题的更多详细信息:Automating the InvokeRequired code pattern

    这里有一些关于扩展方法的细节:

    只有在非泛型、非嵌套静态类中声明的扩展方法才有效。要使其工作,您需要声明一个新的public static class 来保存该方法。

    // your form class declared here
    public partial class Form1 : Form
    {
        // code omitted here
    }
    
    // declare the extension method in this extension class
    public static class ControlExtensions
    {
        public static void InvokeIfRequired(this Control c, Action<Control> action)
        {
            if (c.InvokeRequired)
            {
                c.Invoke(new Action(() => action(c)));
            }
            else
            {
                action(c);
            }
        }
    }
    

    【讨论】:

    • 我有一个小问题,我的主要 Form.cs 是 public partial class form: form1 所以当我使用 public static 方法时它不起作用,所以让它起作用的唯一方法是开设课程public static class,但这样做会破坏我的应用程序,有没有办法解决这个问题?。
    • 哦,这是控件的扩展方法。您不需要将表单更改为public static class(这根本没有帮助,因为此函数不能嵌套在任何其他类中),而是创建一个新的public static class。查看编辑后的帖子:)
    猜你喜欢
    • 2013-04-28
    • 2018-10-21
    • 2014-04-14
    • 1970-01-01
    • 2011-06-05
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多