Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 画布上的MouseLeftButtonDown需要太多的精度_C#_Wpf_Canvas_Mouse_Precision - Fatal编程技术网

C# 画布上的MouseLeftButtonDown需要太多的精度

C# 画布上的MouseLeftButtonDown需要太多的精度,c#,wpf,canvas,mouse,precision,C#,Wpf,Canvas,Mouse,Precision,我正在响应添加到WPF画布的元素上的MouseLeftButtonDown事件。单击时一切正常(即eventhandler正确启动),但它需要鼠标指针的精度太高。你必须完全站在圆圈的顶端才能让它工作。我需要更宽容一点;也许至少有一两个皮克斯会原谅你。画布上的元素是漂亮的大圆圈(大约屏幕上四分之一的大小),因此圆圈本身并不太小,但每个圆圈的笔划宽度是1,因此它是一条细线 您可以在此处看到屏幕截图: 大多数图形应用程序对鼠标的选择并不挑剔,所以我想给用户一个熟悉的体验 如何让它更宽容一点。您可以连接

我正在响应添加到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;

            }
        }
    }
}