Numericupdown mousewheel 事件增加十进制多于一个增量
Posted
技术标签:
【中文标题】Numericupdown mousewheel 事件增加十进制多于一个增量【英文标题】:Numericupdown mousewheel event increases decimal more than one increment 【发布时间】:2011-07-10 17:55:17 【问题描述】:我正在尝试覆盖鼠标滚轮控件,这样当鼠标滚轮向上或向下移动时,它只会将 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);
【问题讨论】:
【参考方案1】:我最近遇到了这个问题,通过更改增量解决了这个问题。
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;
【讨论】:
+1 用于时尚的解决方案,但添加边界检查。我使用了if (e.Delta > 0 && (this.Value + this.Increment) <= this.Maximum)
和else if (e.Delta < 0 && (this.Value - this.Increment) >= this.Minimum)
。【参考方案2】:
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));
【讨论】:
【参考方案3】:我采纳了 Hans Passant 的建议,并将 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));
【讨论】:
【参考方案4】:在查看了类似的问题后,我发现您也可以在不创建子类的情况下解决此问题 - 例如,此代码将为您提供一个 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;
您还应该检查以确保您没有尝试滚动到控件的范围之外,因为那样会崩溃。
【讨论】:
这不会编译 - 大概应该是handledArgs。这也不处理可能的值,例如超出控件的最大属性。请参阅 vjou 的答案以获得更好的版本。 完美运行! - C#.net 4.7【参考方案5】:根据 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;
【讨论】:
【参考方案6】:以下代码将遍历整个表单并修复每个后代 NumericUpDown 控件。
基于this重写 和this
将以下代码添加到您的类(或某些实用程序类)中:
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);
【讨论】:
【参考方案7】:这是此处报告的错误:NumericUpDown - use of mouse wheel may result in different increment
微软在 2007 年 2 月的回应中表示他们无法解决这个 Visual Studio 2008。
有两个已发布的解决方法,它们都是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
【讨论】:
这是非常糟糕的代码,但我想它在大多数情况下都能正常工作。不要把它放在可滚动的面板上。最好的办法是从可以从 Reflector 或参考源 UpDownBase.OnMouseWheel 方法获得的代码开始。只需将 SystemInformation.MouseWheelScrollLines 的调用替换为 1。 我同意这很恶心,为什么不: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;
答案提到了 Visual Studio 2008,但请注意,这在 Visual Studio 2015 中并未修复。此外,错误报告链接已失效,我找不到它的任何存档。太糟糕了,我很想读它,我很好奇为什么鼠标滚轮事件没有使用内置的Increment
属性值。可能是 Raymond Chen 博客的好主题?以上是关于Numericupdown mousewheel 事件增加十进制多于一个增量的主要内容,如果未能解决你的问题,请参考以下文章