1

I need to determine if the value of a NumericUpDown control was changed by a mouseUp event.

I need to call an expensive function when the value of a numericupdown has changed. I can't just use "ValueChanged", I need to use MouseUp and KeyUp events.

enter image description here

Basically, I need to know:

Did the value of the numericUpDown change when the user let go of the mouse? If any area which is not highlighted in red is clicked, the answer is no. I need to IGNORE the mouse up event, when ANYWHERE but the red area is clicked.

How can I determine this by code? I find events a little confusing.

Bart
  • 19,692
  • 7
  • 68
  • 77
David
  • 15,652
  • 26
  • 115
  • 156
  • 3
    "I can't just use "ValueChanged", I need to use MouseUp and KeyUp events." - Why? – Tom W Jun 11 '12 at 13:14
  • "If any area which is not highlighted in red is clicked, the answer is no" WHAT? you might want to re-state your question, considering that we have no idea what your program does, or is supposed to do. Where does the red fit in? How do you usually make you numericupdown change? – General Grey Jun 11 '12 at 13:17
  • @TomW I said, I need to call an expensive 3D rendering function that takes a lot of time. If I call it EACH TIME the value changes, it results in a very laggy UI. I already use ValueChanged with a timer to try and solve this problem, but when the user lets go of the mouse, I just want it to render again, INSTANTLY. – David Jun 11 '12 at 13:17
  • What is the mouse doing when the user "Lets go of the mouse" has he clicked on something? – General Grey Jun 11 '12 at 13:18
  • @K'Leg Try this: Get a NumericUpDown control. Make it print "ValueChanged" each time the value changes. Click, and HOLD the up/down arrow. How many times is it called? Probably more than 30 times per second. That is unacceptable to me. HOWEVER, when the user lets go of the mouse (MouseUp), I need it to render again. I should ONLY render again, though - if the value of this numeric up down has changed. – David Jun 11 '12 at 13:21
  • That makes perfect sense. there is a mouseup event in the numericupdown control, have you tried using it? – General Grey Jun 11 '12 at 13:22
  • @K'Leg Yes. Now, try this. Wire up a NumericUpDown to a MouseUp event. Click on the white area. Or Double click on it. Did the value change? no. Would render have been called? Yes. I need to know if the Mouse was up AND if the value changed, simultaneously. Hope that was clear enough... – David Jun 11 '12 at 13:24
  • It is certainly starting to, might want to add all that to your question – General Grey Jun 11 '12 at 13:27
  • A probably better design would be to run your extensive function on a thread, and for each value change, cancel the running thread (if any) and recalculate. If a thread runs to completion, display its results. With Tasks and a CancellationTokenSource, that would be pretty easy to do, and it would avoid the exact same problem if the user, for example, keeps pressing the Up key. –  Jun 11 '12 at 14:06
  • Have updated with a new answer. You may check if that suits your requirement. it ignores the MouseUp from the textArea as you wanted. – Angshuman Agarwal Jun 11 '12 at 14:15

3 Answers3

2

This will fire when the user releases the mouse button. You might want to investigate which mousebutton was released.

EDIT

    decimal numvalue = 0;
    private void numericUpDown1_MouseUp(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left && numvalue != numericUpDown1.Value)
        {
            //expensive routines
            MessageBox.Show(numericUpDown1.Value.ToString());
        }

        numvalue = numericUpDown1.Value;
    }

EDIT 2 This will determine if the left mousebutton is still down, if it is exit before performing expensive routine, doesn't help with keyboard button down.

    private void numericUpDown1_ValueChanged(object sender, EventArgs e)
    {
        if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)
        {
            return;
        }
        //expensive routines


    }

Edit 3

How to detect the currently pressed key?

Will help solve the Any key down, Though I think the only ones that matter are the arrow keys

Community
  • 1
  • 1
General Grey
  • 3,598
  • 2
  • 25
  • 32
2

Problem - I need to IGNORE the mouse up event, when ANYWHERE but the red area is clicked.

Derive a custom numeric control as shown below. Get the TextArea of the Numeric Control and ignore the KeyUp.

class UpDownLabel : NumericUpDown
{
    private Label mLabel;
    private TextBox mBox;

    public UpDownLabel()
    {
        mBox = this.Controls[1] as TextBox;
        mBox.Enabled = false;
        mLabel = new Label();
        mLabel.Location = mBox.Location;
        mLabel.Size = mBox.Size;
        this.Controls.Add(mLabel);
        mLabel.BringToFront();
        mLabel.MouseUp += new MouseEventHandler(mLabel_MouseUp);
    }


    // ignore the KeyUp event in the textarea
    void mLabel_MouseUp(object sender, MouseEventArgs e)
    {
        return;
    }

    protected override void UpdateEditText()
    {
        base.UpdateEditText();
        if (mLabel != null) mLabel.Text = mBox.Text;
    }
}

In the MainForm, update your designer with this control i.e. UpDownLabel:-

private void numericUpDown1_MouseUp(object sender, MouseEventArgs e)
{
    MessageBox.Show("From Up/Down");
}

Referred from - https://stackoverflow.com/a/4059473/763026 & handled the MouseUp event.

Now, use this control instead of the standard one and hook on the KeyUp event. You will always get the KeyUp event from the Up/Down button only i.e. RED AREA when you click the spinner [Up/Down button, which is again a different control derived from UpDownBase].

Community
  • 1
  • 1
Angshuman Agarwal
  • 4,796
  • 7
  • 41
  • 89
1

I think you should use Leave event that when the focus of NumericUpDown control gone, it would called.

    int x = 0;
    private void numericUpDown1_Leave(object sender, EventArgs e)
    {
        x++;
        label1.Text = x.ToString();
    }
Hamed
  • 2,084
  • 6
  • 22
  • 42
  • Thank you, but not what I need. I need the event to fire instantly when clicked, not when the focus is gone :( – David Jun 11 '12 at 13:32