简体   繁体   English

点击并双击c#中的事件不起作用

[英]click and doubleclick event in c# not working

I have the following code in my C# application 我在C#应用程序中有以下代码

The first determines what happens when the user double-clicks a picture. 第一个决定用户双击图片时会发生什么。

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

And another one for single click: 另一个单击:

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;
            }
        }

I've called both the functions like so: 我把这两个函数称为:

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

However I'm facing a strange bug, the DoubleClick event won't get activated, the only way to make it work is if I comment out the single click. 但是,我面临一个奇怪的错误,DoubleClick事件将不会被激活,唯一的方法是让我的注释单击。 The single click works whether or not I comment or un-comment the Doubleclick event. 无论我是否评论或取消评论Doubleclick事件,单击都有效。 I looked around for solutions but I couldn't find any that resolved my issue. 我四处寻找解决方案,但我找不到任何解决了我的问题。

It's a weird behavior, that changing BorderStyle of a picture box will stop the click to propagate (a Click event will always raise before DoubleClick event). 这是一种奇怪的行为,更改图片框的BorderStyle将阻止点击传播( Click事件将始终在DoubleClick事件之前提升)。

I do not really know how to handle it properly, but we could do some hack to make the feature work. 我真的不知道如何正确处理它,但我们可以做一些黑客来使功能工作。 We can introduce a "lag" between a Click and DoubleClick to make the DoubleClick is checked before Click . 我们可以在ClickDoubleClick之间引入“延迟”,以便在Click之前检查DoubleClick

Here we use a Timer to do the job: 这里我们使用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;
    }
}

In the above code, I used an extension method to handle cross-thread property updating: 在上面的代码中,我使用了一个扩展方法来处理跨线程属性更新:

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

Edit: 编辑:

The extension method I used above is to simplify the code written to do cross-thread property update. 我上面使用的扩展方法是简化为执行跨线程属性更新而编写的代码。 More details on this topic can be found here: Automating the InvokeRequired code pattern 有关此主题的更多详细信息,请参见此处: 自动调用InvokeRequired代码模式

Here are some details on Extension Method : 以下是扩展方法的一些细节:

An extension method only works if it's declared in a non-generic, non-nested static class. 扩展方法仅在非泛型非嵌套静态类中声明时才有效。 To make it work, you need to declare a new public static class to hold the method. 要使其工作,您需要声明一个新的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);
        }
    }
}

When you change the border of the picture box you're kinda of resetting the click event. 当你更改图片框的边框时,你有点重置点击事件。 That's why it's not working and only toggling the one click event, if you comment the change of the border it'll start working... Sorry but I don't know why this is happening and don't know if it's helpful my information =/ 这就是为什么它没有工作,只切换一次点击事件,如果你评论边界的变化,它将开始工作...抱歉,但我不知道为什么会发生这种情况,不知道这是否有用我的信息= /

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM