C#中的单击和双击事件无法正常工作

3

我有以下代码在我的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);

然而,我面临着一个奇怪的问题,双击事件不会被激活,唯一的方法是如果我注释掉单击事件才能正常工作。无论我是否注释或取消注释双击事件,单击事件都能正常工作。我查找了解决方案,但没有找到解决我的问题的方法。


当您通过删除 MessageBox.Show 进行测试时会发生什么? - L.B
你在 IDE 内调试它吗? - icbytes
@L.B 没有任何反应,我添加了 MessageBox.Show 用于测试目的。 - cyberbemon
@icbytes 我正在使用VS2012开发这个。 - cyberbemon
2个回答

2

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

我不知道如何正确处理它,但我们可以通过一些技巧使功能正常工作。我们可以引入一个“延迟”来使DoubleClickClick之前被检查。

这里我们使用一个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);
    }
}

编辑:

我上面使用的扩展方法是为了简化编写跨线程属性更新的代码。有关此主题的更多详细信息,请参见:自动化InvokeRequired代码模式

以下是关于扩展方法的一些详细信息:

扩展方法仅在非泛型、非嵌套静态类中声明时才起作用。要使其起作用,您需要声明一个新的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,但这样做会破坏我的应用程序,有没有其他解决方法? - cyberbemon
哦,这是一个控件的扩展方法。你不需要将你的表单改成public static class(而且这样做并没有帮助,因为这个函数不能嵌套在任何其他类中),而是要创建一个新的public static class。请参见编辑后的帖子 :) - nevets

1
当您更改图片框的边框时,您会重置单击事件。这就是为什么它不起作用并且只切换一个单击事件,如果您注释掉边框的更改,它将开始工作...抱歉,但我不知道为什么会发生这种情况,也不知道我的信息是否有用 =/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接