C # как зациклить, когда кнопка мыши удерживается нажатой - PullRequest
13 голосов
/ 08 ноября 2010

Можете ли вы указать мне правильное направление?Я пытаюсь заставить цикл срабатывать, пока кнопка формы нажата.

//pseudocode
While (button1 is pressed)
value1 += 1

И затем, конечно, прекратить зацикливание при отпускании кнопки

Ответы [ 12 ]

0 голосов
/ 07 марта 2016

Вы можете использовать событие mouseMove и проверить, удерживается ли кнопка мыши, как:

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if(e.Button==MouseButtons.Left)
        {
        //your code here
        }
    }
0 голосов
/ 17 июля 2015

На основании ответа Steztric, метод расширения с несколькими исправлениями ошибок и различными вариантами для скорости увеличения.

/// <summary>
/// An extension method to add a repeat click feature to a button. Clicking and holding  on a button will cause it
/// to repeatedly fire. This is useful for up-down spinner buttons. Typically the longer the mouse is held, the
/// more quickly the click events are fired. There are different options when it comes to increasing the rate of
/// clicks:
/// 1) Exponential - this is the mode used in the NumericUpDown buttons. The first delay starts off around 650 ms
/// and each successive delay is multiplied by 75% of the current delay.
/// 2) Linear - the delay more slowly reaches the fastest repeat speed. Each successive delay subtracts a fixed
/// amount from the current delay. Decreases in delays occur half a second apart.
/// 3) Two Speed - this delay starts off at a slow speed, and then increases to a faster speed after a specified delay.
/// 4) Three Speed - the repeat speed can increase from slow, to medium, to fastest after a specified delay.
///
/// If repeating is added to a button that already has it, then it will be replaced with the new values.
/// </summary>
public static class RepeatingButtonEx {

    private static Hashtable ht = new Hashtable();
    private class Data {
        private static readonly System.Reflection.MethodInfo methodOnClick = null;
        static Data() {
            methodOnClick = typeof(Button).GetMethod("OnClick", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        }

        public Button Button = null;
        private Timer Timer = new Timer();
        public double? GradientRate;
        public int? LinearGradient = null;
        public int FirstDelayMillis;
        public int FastestRepeatMillis;
        public int[] SwitchesMillis;
        public int[] SpeedsMillis;

        private DateTime lastEvent = DateTime.MinValue;
        private int millisCount = 0;
        private int currentSpeed = 0;
        private int waitSum = 0;

        public Data(Button button, double? gradientRate, int? linearGradient, int firstDelayMillis, int fastestRepeatMillis, int[] switchesMillis, int[] speedsMillis) {
            Button = button;
            GradientRate = gradientRate;
            LinearGradient = linearGradient;
            FirstDelayMillis = firstDelayMillis;
            FastestRepeatMillis = fastestRepeatMillis;
            SwitchesMillis = switchesMillis;
            SpeedsMillis = speedsMillis;
            Timer.Interval = firstDelayMillis;
            Timer.Tick += Timer_Tick;
            Button.MouseDown += Button_MouseDown;
            Button.MouseUp += Button_MouseUp;
            Button.MouseLeave += Button_MouseLeave;
        }

        void Button_MouseDown(object sender, MouseEventArgs e) {
            if (!Button.Enabled)
                return;

            lastEvent = DateTime.UtcNow;
            Timer.Start();
        }

        void Button_MouseUp(object sender, MouseEventArgs e) {
            Reset();
        }

        void Button_MouseLeave(object sender, EventArgs e) {
            Reset();
        }

        private void Reset() {
            Timer.Stop();
            Timer.Interval = FirstDelayMillis;
            millisCount = 0;
            currentSpeed = 0;
            waitSum = 0;
        }

        void Timer_Tick(object sender, EventArgs e) {
            if (!Button.Enabled) {
                Reset();
                return;
            }

            methodOnClick.Invoke(Button, new Object[] { EventArgs.Empty });
            //Button.PerformClick(); // if Button uses SetStyle(Selectable, false); then CanSelect is false, which prevents PerformClick from working.

            if (GradientRate.HasValue || LinearGradient.HasValue) {
                int millis = Timer.Interval;

                if (GradientRate.HasValue)
                    millis = (int) Math.Round(GradientRate.Value * millis);
                else if (LinearGradient.HasValue) {
                    DateTime now = DateTime.UtcNow;
                    var ts = now - lastEvent;
                    int ms = (int) ts.TotalMilliseconds;
                    millisCount += ms;
                    // only increase the rate every 500 milliseconds
                    // otherwise it appears too get to the maximum rate too quickly
                    if (millisCount >= 500) {
                        millis -= LinearGradient.Value;
                        millisCount -= 500;
                        lastEvent = now;
                    }
                }

                if (millis < FastestRepeatMillis)
                    millis = FastestRepeatMillis;

                Timer.Interval = millis;
            }
            else {
                if (currentSpeed < SpeedsMillis.Length) {
                    TimeSpan elapsed = DateTime.UtcNow - lastEvent; 
                    if (elapsed.TotalMilliseconds >= waitSum) {
                        waitSum += SwitchesMillis[currentSpeed];
                        Timer.Interval = SpeedsMillis[currentSpeed];
                        currentSpeed++;
                    }
                }
            }
        }

        public void Dispose() {
            Timer.Stop();
            Timer.Dispose();
            Button.MouseDown -= Button_MouseDown;
            Button.MouseUp -= Button_MouseUp;
            Button.MouseLeave -= Button_MouseLeave;
        }
    }

    ///<summary>The repeating speed becomes exponentially faster. This is the default behavior of the NumericUpDown control.</summary>
    ///<param name="button">The button to add the behavior.<param>
    ///<param name="firstDelayMillis">The delay before first repeat in milliseconds.</param>
    ///<param name="fastestRepeatMillis">The smallest delay allowed. Note: Masharling between the timer and the UI thread has an unavoidable limit of about 10 milliseconds.</param>
    ///<param name="gradientRate">The new interval is the current interval multiplied by the gradient rate.</param>
    public static void AddRepeatingExponential(this Button button, int firstDelayMillis = 500, int fastestRepeatMillis = 15, double gradientRate = 0.75) {
        AddRepeating(button, firstDelayMillis, fastestRepeatMillis, gradientRate, null, null, null);
    }

    ///<summary>The repeating speed becomes linearily faster.</param>
    ///<param name="button">The button to add the behavior.<param>
    ///<param name="firstDelayMillis">The delay before first repeat in milliseconds.</param>
    ///<param name="fastestRepeatMillis">The smallest delay allowed. Note: Masharling between the timer and the UI thread has an unavoidable limit of about 10 milliseconds.</param>
    ///<param name="linearGradient">If specified, the repeats gradually happen more quickly. The new interval is the current interval minus the linear gradient.</param>
    public static void AddRepeatingLinear(this Button button, int firstDelayMillis = 500, int fastestRepeatMillis = 50, int linearGradient = 25) {
        AddRepeating(button, firstDelayMillis, fastestRepeatMillis, null, linearGradient, null, null);
    }

    ///<summary>The repeating speed switches from the slow speed to the fastest speed after the specified amount of milliseconds.</summary>
    ///<param name="button">The button to add the behavior.<param>
    ///<param name="firstDelayMillis">The delay before first repeat in milliseconds.</param>
    ///<param name="fastestRepeatMillis">The smallest delay allowed. Note: Masharling between the timer and the UI thread has an unavoidable limit of about 10 milliseconds.</param>
    ///<param name="slowRepeatMillis">The delay in milliseconds between repeats when in the slow repeat state.</param>
    ///<param name="slowToFastestSwitchMillis">The delay in milliseconds before switching from the slow repeat speed to the fastest repeat speed.</param>
    public static void AddRepeatingTwoSpeed(this Button button, int firstDelayMillis = 500, int fastestRepeatMillis = 100, int slowRepeatMillis = 300, int slowToFastestSwitchMillis = 2000) {
        AddRepeating(button, firstDelayMillis, fastestRepeatMillis, null, null, new[] { slowRepeatMillis, fastestRepeatMillis }, new [] { slowToFastestSwitchMillis, 0 });
    }

    ///<summary>The repeating speed switches from the slow to medium to fastest at speed switch interval specified.</summary>
    ///<param name="button">The button to add the behavior.<param>
    ///<param name="firstDelayMillis">The delay before first repeat in milliseconds.</param>
    ///<param name="fastestRepeatMillis">The smallest delay allowed. Note: Masharling between the timer and the UI thread has an unavoidable limit of about 10 milliseconds.</param>
    ///<param name="slowRepeatMillis">The delay in milliseconds between repeats when in the slow repeat state.</param>
    ///<param name="mediumRepeatMillis">The delay in milliseconds between repeats when in the medium repeat state.</param>
    ///<param name="speedSwitchMillis">The delay in milliseconds before switching from one speed state to the next speed state.</param>
    public static void AddRepeatingThreeSpeed(this Button button, int firstDelayMillis = 500, int fastestRepeatMillis = 75, int slowRepeatMillis = 300, int mediumRepeatMillis = 150, int speedSwitchMillis = 2000) {
        AddRepeating(button, firstDelayMillis, fastestRepeatMillis, null, null, new[] { slowRepeatMillis, mediumRepeatMillis, fastestRepeatMillis }, new [] { speedSwitchMillis, speedSwitchMillis, 0 });
    }

    private static void AddRepeating(this Button button, int firstDelayMillis, int fastestRepeatMillis, double? gradientRate, int? linearGradient, int[] speedsMillis, int[] switchesMillis) {
        Data d = (Data) ht[button];
        if (d != null)
            RemoveRepeating(button);

        d = new Data(button, gradientRate, linearGradient, firstDelayMillis, fastestRepeatMillis, switchesMillis, speedsMillis);
        ht[button] = d;
        button.Disposed += delegate {
            RemoveRepeating(button);
        };
    }

    ///<summary>Removes the repeating behavior from the button.</summary>
    public static void RemoveRepeating(this Button button) {
        Data d = (Data) ht[button];
        if (d == null)
            return;

        ht.Remove(button);
        d.Dispose();
    }
}
...