Numericupdownマウスホイールイベントは、小数を1つ以上インクリメントします

2011年03月08日に質問されました。  ·  閲覧回数 9.6k回  ·  ソース

JonF picture
2011年03月08日

マウスホイールコントロールをオーバーライドして、マウスホイールを上下に動かしたときに、numericupdownフィールドの値が1だけ増えるようにしようとしています。現在、コントロールパネルに保存されているものを使用しており、毎回3ずつの値。

私は次のコードを使用しています。 numberOfTextLinesToMoveが1だけで、txtPrice.Valueが期待どおりに入力されていることがわかった場合でも、設定した値がnumericupdownボックスに表示されているものではないため、他の何かが上書きしています。

void txtPrice_MouseWheel(object sender, MouseEventArgs e)
        {
            int numberOfTextLinesToMove = e.Delta  / 120;
            if (numberOfTextLinesToMove > 0)
            {
                txtPrice.Value = txtPrice.Value + (txtPrice.Increment * numberOfTextLinesToMove);
            }
            else 
            {

                txtPrice.Value = txtPrice.Value - (txtPrice.Increment * numberOfTextLinesToMove);
            }

        }

回答

Evan picture
2013年05月02日
11

最近この問題が発生し、増分を変更することで問題を回避しました。

numericUpDown1.Increment = 1m / SystemInformation.MouseWheelScrollLines;

編集:これは、マウスホイールのみを使用して値を変更する場合にのみ適切なソリューションです。 すべての状況でこれを修正するには、クラスをオーバーライドする必要があります。 これが簡単なバージョンです。

public class NumericUpDownFix : System.Windows.Forms.NumericUpDown
{
    protected override void OnMouseWheel(MouseEventArgs e)
    {
        HandledMouseEventArgs hme = e as HandledMouseEventArgs;
        if (hme != null)
            hme.Handled = true;

        if (e.Delta > 0)
            this.Value += this.Increment;
        else if (e.Delta < 0)
            this.Value -= this.Increment;
    }
}
Paccc picture
2013年01月11日
5

私はHansPassantのアドバイスを受けて、この機能を追加するためにNumericUpDownをサブクラス化しました。 OnMouseWheelメソッドにReflectorのコードの修正バージョンを使用します。 興味のある人のために私が最終的に得たものは次のとおりです。

using System;
using System.ComponentModel;
using System.Windows.Forms;

/// <summary>
/// Extends the NumericUpDown control by providing a property to 
/// set the number of steps that are added to or subtracted from
/// the value when the mouse wheel is scrolled.
/// </summary>
public class NumericUpDownExt : NumericUpDown
{
    private int wheelDelta = 0;
    private int mouseWheelScrollLines = 1;

    /// <summary>
    /// Gets or sets the number of step sizes to increment or 
    /// decrement from the value when the mouse wheel is scrolled.
    /// Set this value to -1 to use the system default.
    /// </summary>
    [DefaultValue(1)]
    [Description("Gets or sets the number of step sizes to increment or decrement from the value when the mouse wheel is scrolled. Set this value to -1 to use the system default.")]
    public Int32 MouseWheelScrollLines {
        get { return mouseWheelScrollLines; }
        set {
            if (value < -1)
                throw new ArgumentOutOfRangeException("value must be greater than or equal to -1.");
            if (value == -1)
                mouseWheelScrollLines = SystemInformation.MouseWheelScrollLines;
            else
                mouseWheelScrollLines = value;
        }
    }

    protected override void OnMouseWheel(MouseEventArgs e) {
        HandledMouseEventArgs args = e as HandledMouseEventArgs;
        if (args != null) {
            if (args.Handled) {
                base.OnMouseWheel(e);
                return;
            }
            args.Handled = true;
        }

        base.OnMouseWheel(e);

        if ((Control.ModifierKeys & (Keys.Alt | Keys.Shift)) == Keys.None && Control.MouseButtons == MouseButtons.None) {
            if (mouseWheelScrollLines != 0) {
                this.wheelDelta += e.Delta;
                float num2 = (float)this.wheelDelta / 120f;
                if (mouseWheelScrollLines == -1) 
                    mouseWheelScrollLines = 1;
                int num3 = (int)(mouseWheelScrollLines * num2);
                if (num3 != 0) {
                    int num4;
                    if (num3 > 0) {
                        for (num4 = num3; num4 > 0; num4--) 
                            this.UpButton();
                        this.wheelDelta -= (int)(num3 * (120f / (float)mouseWheelScrollLines));
                    } else {
                        for (num4 = -num3; num4 > 0; num4--) 
                            this.DownButton();
                        this.wheelDelta -= (int)(num3 * (120f / (float)mouseWheelScrollLines));
                    }
                }
            }
        }
    }
}
vjou picture
2014年09月06日
4

user3610013の答えは非常にうまく機能しています。 これはわずかな変更であり、誰かにとって便利な場合があります。

private void ScrollHandlerFunction(object sender, MouseEventArgs e)
{
    NumericUpDown control = (NumericUpDown)sender;
    ((HandledMouseEventArgs)e).Handled = true;
    decimal value = control.Value + ((e.Delta > 0) ? control.Increment : -control.Increment);
    control.Value = Math.Max(control.Minimum, Math.Min(value, control.Maximum));
}
user3610013 picture
2014年05月07日
3

同様の質問を調べたところ、サブクラスを作成せずにこれを回避できることもわかりました。たとえば、このコードは、1つだけスクロールする(コントロールにフォーカスがある場合のみ)numericUpDownを提供します。

コンテナのコンストラクタでデリゲートを設定します。

numericUpDown1.MouseWheel += new MouseEventHandler(this.ScrollHandlerFunction);

...次に、クラスの他の場所で関数を定義します。

private void ScrollHandlerFunction(object sender, MouseEventArgs e)
{
    HandledMouseEventArgs handledArgs = e as HandledMouseEventArgs;
    handledArgs.Handled = true;
    numericUpDown1.Value += (handledArgs.Delta > 0) ? 1 : -1;
}

また、クラッシュするため、コントロールの範囲外にスクロールしようとしていないことを確認する必要があります。

Itay Gal picture
2014年12月17日
1

Jay Riggsの回答に基づいて、これがよりクリーンなバージョンです(私の意見では):

namespace MyControls
{
    public partial class NumericUpDown : System.Windows.Forms.NumericUpDown
    {
        public Decimal MouseWheelIncrement { get; set; }

        public NumericUpDown()
        {
            MouseWheelIncrement = 1;
            InitializeComponent();
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            decimal newValue = Value;
            if (e.Delta > 0)
                newValue += MouseWheelIncrement;
            else
                newValue -= MouseWheelIncrement;
            if (newValue > Maximum)
                newValue = Maximum;
            else
                if (newValue < Minimum)
                    newValue = Minimum;
            Value = newValue;
        }
    }
}
somebody4 picture
2018年07月18日
0

次のコードは、フォーム全体をウォークダウンし、すべての適切なNumericUpDownコントロールを修正します。

これこれに基づいて書き直しました

次のコードをクラス(またはユーティリティクラス)に追加します。

static void FixNumericUpDownMouseWheel(Control c) {
    foreach (var num in c.Controls.OfType<NumericUpDown>())
        num.MouseWheel += FixNumericUpDownMouseWheelHandler;

    foreach (var child in c.Controls.OfType<Control>())
        FixNumericUpDownMouseWheel(child);
}

static private void FixNumericUpDownMouseWheelHandler(object sender, MouseEventArgs e) {
    ((HandledMouseEventArgs)e).Handled = true;
    var self = ((NumericUpDown)sender);
    self.Value = Math.Max(Math.Min(
        self.Value + ((e.Delta > 0) ? self.Increment : -self.Increment), self.Maximum), self.Minimum);

}

次に、フォームの作成者で、 InitializeComponent()後に、次の行を挿入します。

FixNumericUpDownMouseWheel(this);
Jay Riggs picture
2011年03月08日
-1

これはここで報告されているバグです: NumericUpDown-マウスホイールを使用すると、異なる増分が発生する可能性があります

2007年2月のMicrosoftの回答では、このVisual Studio2008に対応できないと述べています。

投稿された回避策は2つあり、どちらもサブクラスNumericUpDownです。 リンクの[回避策]タブを確認してください。

私が試したものは私のために働いた(「NanoWizard」によって投稿された):

using System;
using System.Windows.Forms;

internal class NumericUpDownControl : NumericUpDown
{
#region Constants
protected const String UpKey = "{UP}";
protected const String DownKey = "{DOWN}";
#endregion Constants

#region Base Class Overrides
protected override void OnMouseWheel(MouseEventArgs e_)
{
    String key = GetKey(e_.Delta);
    SendKeys.Send(key);
}
#endregion Base Class Overrides

#region Protected Methods
protected static String GetKey(int delta_)
{
    String key = (delta_ < 0) ? DownKey : UpKey;
    return key;
}
#endregion Protected Methods
}