C# 画布上的MouseLeftButtonDown需要太多的精度
我正在响应添加到WPF画布的元素上的MouseLeftButtonDown事件。单击时一切正常(即eventhandler正确启动),但它需要鼠标指针的精度太高。你必须完全站在圆圈的顶端才能让它工作。我需要更宽容一点;也许至少有一两个皮克斯会原谅你。画布上的元素是漂亮的大圆圈(大约屏幕上四分之一的大小),因此圆圈本身并不太小,但每个圆圈的笔划宽度是1,因此它是一条细线 您可以在此处看到屏幕截图: 大多数图形应用程序对鼠标的选择并不挑剔,所以我想给用户一个熟悉的体验C# 画布上的MouseLeftButtonDown需要太多的精度,c#,wpf,canvas,mouse,precision,C#,Wpf,Canvas,Mouse,Precision,我正在响应添加到WPF画布的元素上的MouseLeftButtonDown事件。单击时一切正常(即eventhandler正确启动),但它需要鼠标指针的精度太高。你必须完全站在圆圈的顶端才能让它工作。我需要更宽容一点;也许至少有一两个皮克斯会原谅你。画布上的元素是漂亮的大圆圈(大约屏幕上四分之一的大小),因此圆圈本身并不太小,但每个圆圈的笔划宽度是1,因此它是一条细线 您可以在此处看到屏幕截图: 大多数图形应用程序对鼠标的选择并不挑剔,所以我想给用户一个熟悉的体验 如何让它更宽容一点。您可以连接
如何让它更宽容一点。您可以连接到根布局对象的MouseLeftButtonDown事件,并通过执行以下操作检查哪些元素在单击范围内:
List<UIElement> hits = System.Windows.Media.VisualTreeHelper.FindElementsInHostCoordinates(Point, yourLayoutRootElement) as List<UIElement>;
我不记得是否使用HitTest而不是FindElementsInHostCoordinates。两种都试试。您可以从鼠标位置创建4个点对象以创建假公差效果,并为所有4个点调用FindElementsInHostCoordinates或HitTest。您可能希望尝试使用透明颜色填充圆,以使整个圆可单击 如果失败,还可以在与其他圆相同的位置绘制辅助圆。使圆圈的前景颜色透明,并使画笔的厚度变宽几个像素,以便在圆圈周围形成更可接受的可单击区域 希望这有帮助 我想我已经做到了(有你的帮助我开始) 首先,我将移动事件处理移动到画布上,而不是每个椭圆。从面向对象的角度来看,这是好是坏。至少当鼠标事件处理由HolePattern负责在每个孔上设置它时(该孔的可视椭圆),它会被抽象掉,以便我的HolePattern的任何消费者都能自动获得该功能。但是,通过将其移动到主UI代码,我现在可以在更高级别上处理画布鼠标事件。但这也不全是坏事。这部分我们可以讨论几天 关键是,我设计了一种方法,当用鼠标在画布上拾取某个东西,然后读取选定椭圆所属的孔时,我可以创建一个“误差范围”,然后我可以读取该孔所属的孔模式以及我的整个UI(ListView、TextBox、gridview和坐标)都由现有的XAML绑定更新,画布通过一次对现有方法的调用来更新,以重新生成画布 老实说,我不敢相信我已经解决了所有这些问题(当然是在你和其他人的帮助下)。这是一种很酷的感觉,看到了这一点,并看到它成为现实 请在此处查看主代码:
void canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
int ClickMargin = 2;
Point ClickedPoint = e.GetPosition(canvas1);
Point p1 = new Point(ClickedPoint.X - ClickMargin, ClickedPoint.Y - ClickMargin);
Point p2 = new Point(ClickedPoint.X - ClickMargin, ClickedPoint.Y + ClickMargin);
Point p3 = new Point(ClickedPoint.X + ClickMargin, ClickedPoint.Y + ClickMargin);
Point p4 = new Point(ClickedPoint.X + ClickMargin, ClickedPoint.Y - ClickMargin);
var PointPickList = new Collection<Point>();
PointPickList.Add(ClickedPoint);
PointPickList.Add(p1);
PointPickList.Add(p2);
PointPickList.Add(p3);
PointPickList.Add(p4);
foreach (Point p in PointPickList)
{
HitTestResult SelectedCanvasItem = System.Windows.Media.VisualTreeHelper.HitTest(canvas1, p);
if (SelectedCanvasItem.VisualHit.GetType() == typeof(Ellipse))
{
var SelectedEllipseTag = SelectedCanvasItem.VisualHit.GetValue(Ellipse.TagProperty);
if (SelectedEllipseTag!=null && SelectedEllipseTag.GetType().BaseType == typeof(Hole))
{
Hole SelectedHole = (Hole)SelectedEllipseTag;
SetActivePattern(SelectedHole.ParentPattern);
SelectedHole.ParentPattern.CurrentHole = SelectedHole;
}
}
}
}
void canvas1\u MouseLeftButtonDown(对象发送器,MouseButtonEventArgs e)
{
int ClickMargin=2;
点击点=e.GetPosition(画布1);
点p1=新点(点击点X-点击边距,点击点Y-点击边距);
点p2=新点(点击点X-点击边距,点击点Y+点击边距);
点p3=新点(点击点X+点击边距,点击点Y+点击边距);
点p4=新点(ClickedPoint.X+ClickedMargin,ClickedPoint.Y-ClickedMargin);
var PointPickList=新集合();
点选取列表。添加(单击点);
PointPickList.Add(p1);
PointPickList.Add(p2);
PointPickList.Add(p3);
PointPickList.Add(p4);
foreach(点选取列表中的点p)
{
HitTestResult SelectedCanvasItem=System.Windows.Media.VisualTreeHelper.HitTest(canvas1,p);
if(SelectedCanvasItem.VisualHit.GetType()==typeof(椭圆))
{
var SelectedEllipseTag=SelectedCanvasItem.VisualHit.GetValue(Ellipse.TagProperty);
if(SelectedEllipseTag!=null&&SelectedEllipseTag.GetType().BaseType==typeof(Hole))
{
选择的孔孔=(孔)选择的孔;
SetActivePattern(SelectedHole.ParentPattern);
SelectedHole.ParentPattern.CurrentHole=SelectedHole;
}
}
}
}
只要增加椭圆的笔划厚度,使其可调即可
因此MouseLeftButtonDown事件起作用
例子:
在椭圆标记中:
椭圆
Canvas.Left=“10”Canvas.Top=“133”Height=“24”Name=“ellipse1”Width=“23”Stroke=“Red”MouseLeftButtonDown=“ellipse1\u MouseLeftButtonDown”ToolTip=“Temp Close”StrokeEndLineCap=“Flat”strokehickness=“12”
私有void ellipse1u MouseLeftButtonDown(对象发送器,MouseButtonEventArgs e)
{
Application curApp=Application.Current;
curApp.Shutdown();
}好吧,你让我走了。注意:FinDelementSinHostSi仅用于silverlight,因此我必须使用HitTest。我也做了你的4点。请在下面我的答题贴上查看。谢谢。我正在使用现在著名的“4点东西”和HitTest函数,它对我来说很好!谢谢那很酷。我想你也可以在圆圈的顶部放置一个透明的矩形,然后连接它的MouseLeftButtonDown事件。但我觉得这比你的解决方案更复杂,伙计!谢谢你的鼓励。如果你认为我的帖子值得的话,请投我一票。
void canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
int ClickMargin = 2;
Point ClickedPoint = e.GetPosition(canvas1);
Point p1 = new Point(ClickedPoint.X - ClickMargin, ClickedPoint.Y - ClickMargin);
Point p2 = new Point(ClickedPoint.X - ClickMargin, ClickedPoint.Y + ClickMargin);
Point p3 = new Point(ClickedPoint.X + ClickMargin, ClickedPoint.Y + ClickMargin);
Point p4 = new Point(ClickedPoint.X + ClickMargin, ClickedPoint.Y - ClickMargin);
var PointPickList = new Collection<Point>();
PointPickList.Add(ClickedPoint);
PointPickList.Add(p1);
PointPickList.Add(p2);
PointPickList.Add(p3);
PointPickList.Add(p4);
foreach (Point p in PointPickList)
{
HitTestResult SelectedCanvasItem = System.Windows.Media.VisualTreeHelper.HitTest(canvas1, p);
if (SelectedCanvasItem.VisualHit.GetType() == typeof(Ellipse))
{
var SelectedEllipseTag = SelectedCanvasItem.VisualHit.GetValue(Ellipse.TagProperty);
if (SelectedEllipseTag!=null && SelectedEllipseTag.GetType().BaseType == typeof(Hole))
{
Hole SelectedHole = (Hole)SelectedEllipseTag;
SetActivePattern(SelectedHole.ParentPattern);
SelectedHole.ParentPattern.CurrentHole = SelectedHole;
}
}
}
}