简体   繁体   中英

click and doubleclick event in c# not working

I have the following code in my C# application

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. The single click works whether or not I comment or un-comment the Doubleclick event. 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).

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 .

Here we use a Timer to do the job:

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

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.

// 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 =/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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