Microsoft Blend允许通过连续拖动更改Left,Top等属性的数值。用户在属性值框中单击,保持按钮向下并向左或向右拖动以减小/增加值。简单。
关于它的特殊之处在于,如果光标到达屏幕的左端或右端并且用户仍想要拖动更多,则可以继续拖动,光标将从屏幕的另一端重新开始。
我尝试使用Thumb
控件在我的一个WPF应用程序中执行此操作。使用DragDetla
事件,如果我发现Thumb
已到达屏幕边缘,我会将其位置设置为远端。但这会使e.HorizontalChange
的值与整个屏幕的宽度一样大。如何在不影响水平变化值的情况下更改拇指在拖动期间的位置?
答案 0 :(得分:0)
我已经在WPF控件中通过使用文本框并订阅以下事件来实现了这一点:
拖动直到达到屏幕限制要求鼠标捕获或调用任何UIElement
上可用的CaptureMouse方法。另一方面,您需要在需要调用ReleaseMouseCapture方法的某个时候释放鼠标。解决方案可能是这样的:
声明枚举以建模拖动方向
internal enum MouseDirections
{
None,
LeftRight,
UpDown
}
声明一个类以保留鼠标起源(第一个位置)和当前位置的痕迹:
internal class MouseIncrementor
{
private MouseDirections _enumMouseDirection = MouseDirections.None;
private Point _objPoint;
private readonly Point _initialPoint;
public MouseIncrementor(Point objPoint, MouseDirections enumMouseDirection)
{
_objPoint = objPoint;
_initialPoint = _objPoint;
_enumMouseDirection = enumMouseDirection;
}
public MouseDirections MouseDirection
{
get
{
return _enumMouseDirection;
}
protected set
{
_enumMouseDirection = value;
}
}
public Point InitialPoint
{
get
{
return _initialPoint;
}
}
public Point Point
{
get
{
return _objPoint;
}
set
{
_objPoint = value;
}
}
internal MouseDirections SetMouseDirection(Point pos)
{
double deltaX = this.Point.X - pos.X;
double deltaY = this.Point.Y - pos.Y;
if (Math.Abs(deltaX) > Math.Abs(deltaY))
MouseDirection = MouseDirections.LeftRight;
else
{
if (Math.Abs(deltaX) < Math.Abs(deltaY))
MouseDirection = MouseDirections.UpDown;
}
return MouseDirection;
}
}
我有一个自定义控件,其中包含一个名为_PART_TextBox的TextBox
:
文字框_PART_TextBox;
...以及MouseIncrementor
的字段:
MouseIncrementor _objMouseIncr;
...这些连接方式如下:
_PART_TextBox.MouseEnter += _PART_TextBox_MouseEnter;
_PART_TextBox.GotKeyboardFocus += _PART_TextBox_GotKeyboardFocus;
_PART_TextBox.LostKeyboardFocus += _PART_TextBox_LostKeyboardFocus;
_PART_TextBox.MouseMove += _PART_TextBox_MouseMove;
_PART_TextBox.MouseUp += _PART_TextBox_MouseUp;
_PART_TextBox.PreviewMouseDown += _PART_TextBox_PreviewMouseDown;
_PART_TextBox.LostMouseCapture += _PART_TextBox_LostMouseCapture;
和一些事件处理程序才能使它起作用:
private void _PART_TextBox_LostMouseCapture(object sender, MouseEventArgs e)
{
_objMouseIncr = null;
}
private void _PART_TextBox_MouseUp(object sender, MouseButtonEventArgs e)
{
if (_objMouseIncr != null)
{
var mouseUpPosition = GetPositionFromThis(e);
if (_objMouseIncr.InitialPoint.Equals(mouseUpPosition))
{
_PART_TextBox.Focus();
}
}
_PART_TextBox.ReleaseMouseCapture();
_objMouseIncr = null;
}
private void _PART_TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (IsKeyboardFocusWithin == false)
{
_objMouseIncr = new MouseIncrementor(this.GetPositionFromThis(e), MouseDirections.None);
e.Handled = true;
}
}
private void _PART_TextBox_MouseMove(object sender, MouseEventArgs e)
{
// nothing to do here
if (_objMouseIncr == null)
return;
if (e.LeftButton != MouseButtonState.Pressed)
return;
if (CanIncreaseCommand() == false && CanDecreaseCommand() == false)
{
// since we can't parse the value, we are out of here, i.e. user put text in our number box
_objMouseIncr = null;
return;
}
var pos = GetPositionFromThis(e);
double deltaX = _objMouseIncr.Point.X - pos.X;
double deltaY = _objMouseIncr.Point.Y - pos.Y;
if (_objMouseIncr.MouseDirection == MouseDirections.None)
{
// this is our first time here, so we need to record if we are tracking x or y movements
if (_objMouseIncr.SetMouseDirection(pos) != MouseDirections.None)
_PART_TextBox.CaptureMouse();
}
if (_objMouseIncr.MouseDirection == MouseDirections.LeftRight)
{
if (deltaX > 0)
OnDecrement(LargeStepSize);
else
{
if (deltaX < 0)
OnIncrement(LargeStepSize);
}
}
else
{
if (_objMouseIncr.MouseDirection == MouseDirections.UpDown)
{
if (deltaY > 0)
{
if (CanIncreaseCommand() == true)
OnIncrease();
}
else
{
if (deltaY < 0)
{
if (CanDecreaseCommand() == true)
OnDecrease();
}
}
}
}
_objMouseIncr.Point = GetPositionFromThis(e);
}
private Point GetPositionFromThis(MouseEventArgs e)
{
return this.PointToScreen(e.GetPosition(this));
}
private void _PART_TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
_objMouseIncr = null;
(sender as TextBox).Cursor = Cursors.ScrollAll;
}
private void _PART_TextBox_MouseEnter(object sender, MouseEventArgs e)
{
if (IsMouseDragEnabled == false)
return;
if (IsKeyboardFocusWithin)
(sender as TextBox).Cursor = Cursors.IBeam;
else
(sender as TextBox).Cursor = Cursors.ScrollAll;
}
private void _PART_TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
_objMouseIncr = null;
(sender as TextBox).Cursor = Cursors.IBeam;
}
完整的项目位于:https://github.com/Dirkster99/NumericUpDownLib 请让我知道我是否缺少某些东西或还有其他问题。