我对WPF很陌生,所以我正在学习这个很难(但很有趣)的方式。我正在构建类似HSV的colorpicker usercontrol,并且想要获得我用的拇指的行为,因为“选择器”仅限于椭圆区域(实际上是圆圈)。当移到外面时,选择器应该粘在一边而根本不移动。我相信这是最常见的GUI行为,因此它应该如何表现。随意提出更好的行为!
是否有一个共同的,已知的和推荐的解决方案或是每个人每次都重新发明轮子?
如何解决这个问题的好主意?
代码隐藏:
public partial class HSVColorPicker : UserControl
{
public HSVColorPicker()
{
InitializeComponent();
}
void onDragDelta(object sender, DragDeltaEventArgs e)
{
Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);
}
}
XAML:
<Grid>
<Canvas x:Name="canvas">
<Image x:Name="wheel" Source="colorwheel.png" Width="300" Margin="5,5,0,0"/>
<Thumb Name="thumb" DragDelta="onDragDelta" Canvas.Left="104" Canvas.Top="68" Template="{StaticResource thumbTemplate}" />
</Canvas>
</Grid>
当我在这里时,拇指总是在光标后面拖动,还有另一种方法可以创建吗?正如我所说,我是WPF和GUI制作的新手,所以也许有明显的解决方案没有发生在我身上;)
答案 0 :(得分:1)
我做了一些重新思考并完全放弃了拇指,使用虚拟圆圈(名为拇指)代替。现在我在画布上听,mousedown,mouseup和mousemove并确定应该是什么,不是。这有一个很好的功能,当鼠标移出区域时,拇指会粘到色轮边缘,但是区域比色轮稍大一些,以便在边界上轻松获得一个点。不完整,但它解决了我的问题,所以我现在发布它。
private bool mousePressed { get; set; }
private bool mouseWithinArea { get; set; }
private Point circleMiddlePoint { get; set; }
private int margin;
private double mPX;
private double mPY;
private double localXpos;
private double globalXpos
{
get
{
return localXpos + mPX;
}
set
{
localXpos = value - mPX;
Canvas.SetLeft(thumb, value);
}
}
private double localYpos;
private double globalYpos
{
get
{
return mPY - localYpos;
}
set
{
localYpos = mPY - value;
Canvas.SetTop(thumb, value);
}
}
public HSVColorPicker()
{
InitializeComponent();
wheel.Width = 300;
margin = 15;
mPX = 150+margin;
mPY = 150+margin;
circleMiddlePoint = new Point(mPX, mPY);
}
private void CalcPosition(double X, double Y)
{
double radius = wheel.Width / 2.0;
double vectorX = X - mPX;
double vectorY = Y - mPY;
double distance = Math.Sqrt(vectorX * vectorX + vectorY * vectorY);
if (distance > radius)
{
double factor = radius / distance;
vectorX *= factor;
vectorY *= factor;
}
globalXpos = vectorX + mPX;
globalYpos = vectorY + mPY;
}
private void wheel_MouseDown(object sender, MouseButtonEventArgs e)
{
if (mouseWithinArea)
{
mousePressed = true;
Point mousePoint = e.GetPosition(this);
CalcPosition(mousePoint.X, mousePoint.Y);
}
}
private void wheel_MouseMove(object sender, MouseEventArgs e)
{
Point mousePoint = e.GetPosition(this);
double relX = mousePoint.X - mPX;
double relY = mPY - mousePoint.Y;
if (mouseWithinArea)
{
if (Math.Sqrt(relX * relX + relY * relY) > 150+margin)
{
mouseWithinArea = false;
}
else
{
if (mousePressed)
{
CalcPosition(mousePoint.X, mousePoint.Y);
}
}
}
else
{
if (Math.Sqrt(relX * relX + relY * relY) < 150+margin)
{
mouseWithinArea = true;
if (mousePressed)
{
CalcPosition(mousePoint.X, mousePoint.Y);
}
}
}
}
private void wheel_MouseUp(object sender, MouseButtonEventArgs e)
{
mousePressed = false;
}
}
<Canvas x:Name="canvas" Background="Transparent" MouseDown="wheel_MouseDown" MouseMove="wheel_MouseMove" MouseUp="wheel_MouseUp" Width="330" Height="330">
<Image x:Name="wheel" Source="colorwheel.png" Width="300" Margin="15,15,0,0" />
<Ellipse Margin="0,0,0,0"
x:Name="outerEll"
Stroke="Silver"
StrokeThickness="15"
Width="330"
Height="330"/>
<Ellipse Name="thumb" Stroke="Black" Fill="Silver" Canvas.Left="150" Canvas.Top="150" Width="15" Height="15" Margin="-12" />
</Canvas>
答案 1 :(得分:0)
您希望拇指的中心位于色轮内。
因此,拇指中心与色轮中心(即画布中心)之间的距离必须小于 或等于色轮的半径(即画布一半的半径)。
未经测试的c#代码:
void onDragDelta(object sender, DragDeltaEventArgs e)
{
double radius = canvas.RenderSize.Width / 2.0;
double thumbCenterX = Canvas.GetLeft(thumb) - thumb.RenderSize.Width + e.HorizontalChange;
double thumbCenterY = Canvas.GetTop(thumb) - thumb.RenderSize.Height + e.VerticalChange;
double colorWheelCenterX = canvas.RenderSize.Width / 2.0;
double colorWheelCenterY = canvas.RenderSize.Height / 2.0;
double vectorX = thumbCenterX - colorWheelCenterX;
double vectorY = thumbCenterY - colorWheelCenterY;
double distance = Math.Sqrt(vectorX * vectorX + vectorY * vectorY);
if(distance > radius) {
double factor = radius / distance;
vectorX *= factor;
vectorY *= factor;
}
Canvas.SetLeft(thumb, colorWheelCenterX + vectorX - thumb.RenderSize.Width / 2.0);
Canvas.SetTop(thumb, colorWheelCenterY + vectorY - thumb.RenderSize.Height / 2.0);
}