【问题标题】:MouseLeftButtonDown on canvas requires too much precision画布上的 MouseLeftButtonDown 需要太高的精度
【发布时间】:2009-02-24 06:14:43
【问题描述】:

我正在响应添加到 WPF 画布的元素上的 MouseLeftButtonDown 事件。单击时一切正常(即事件处理程序正确触发),但它需要鼠标指针的过多精度。你必须完美地站在圈子的顶端才能让它发挥作用。我需要它更宽容一点;也许至少 1 或 2 个像素可以原谅。画布上的元素都是漂亮的大圆圈(大约屏幕上四分之一的大小),所以圆圈本身并不算小,但每个圆圈的StrokeWidth都是1,所以它是一条细线。

你可以在这里看到截图:http://twitpic.com/1f2ci/full

大多数图形应用对鼠标的选择并不那么挑剔,所以我想给用户一种熟悉的体验。

我怎样才能让它更宽容一点。

【问题讨论】:

    标签: c# wpf canvas mouse precision


    【解决方案1】:

    您可以改为连接到根布局对象的 MouseLeftButtonDown 事件,并通过执行以下操作检查哪些元素在点击范围内:

    List<UIElement> hits = System.Windows.Media.VisualTreeHelper.FindElementsInHostCoordinates(Point, yourLayoutRootElement) as List<UIElement>;  
    

    http://msdn.microsoft.com/en-us/library/cc838402(VS.95).aspx

    对于Point参数,可以使用MouseEventArgs参数e,像这样调用它的GetPosition方法:

    Point p = e.GetPosition(null)
    

    我不记得是否使用 HitTest 代替 FindElementsInHostCoordinates。两个都试试。
    http://msdn.microsoft.com/en-us/library/ms608752.aspx

    您可以从鼠标位置创建 4 个 Point 对象以创建假公差效果,并为所有 4 个点调用 FindElementsInHostCoordinates 或 HitTest。

    【讨论】:

    • 好吧,你让我走了。注意:FindElementsInHostCoordinates si 仅适用于 silverlight,所以我不得不使用 HitTest。我也做了你的 4 点事情。在下面我的回答帖子中查看。谢谢。
    • 我将现在著名的“4 点事物”与 HitTest 函数结合使用,它对我来说很好用!谢谢!
    【解决方案2】:

    您可能想尝试用透明颜色填充圆圈以使整个圆圈可点击...

    如果失败,您还可以在与其他圆圈相同的位置绘制辅助圆圈。将圆形前景色设为透明,并将画笔的粗细调宽几个像素,以便在圆形周围形成更可接受的可点击区域。

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      我想我已经做到了(在你的帮助下让我开始)......

      首先,我已将移动事件处理移至 Canvas 而不是每个 Ellipse。从 OOP 的角度来看,这有好有坏。至少当鼠标事件处理是 HolePattern 的责任在每个 Hole 上设置它(椭圆是 Hole 的视觉对象)时,它被抽象出来,以便我的 HolePattern 的任何消费者都将自动获得此功能。但是,通过将其移至主 UI 代码,我现在正在更高级别处理我的画布鼠标事件。但这也不全是坏事。我们可以讨论这部分几天。

      关键是,我设计了一种方法,可以在用鼠标在画布上选择某物时创建“误差范围”,然后读取所选 Ellipse 所属的 Hole,然后我可以读取 HolePattern Hole 属于,我的整个 UI(ListView、文本框、gridview fo 坐标)都由现有的 XAML 绑定更新,并且通过调用现有方法来更新 Canvas 以重新生成画布。

      说实话,我不敢相信我已经弄清楚了这一切(当然,在你和其他人的帮助下)。有这样的愿景并看到它成为这样的感觉真是太酷了。

      在这里查看主要代码:

      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;
      
                  }
              }
          }
      }
      

      【讨论】:

      • 这很酷。我想你也可以在圆的顶部放置一个透明的 Rectangle,并连接它的 MouseLeftButtonDown 事件。但我认为它比您的解决方案更复杂。
      • 老兄!谢谢鼓励的话。如果您认为值得,请为我的帖子投票。
      【解决方案4】:

      只需增加椭圆的笔画粗细即可调整

      因此 MouseLeftButtonDown 事件有效 例子: 在椭圆标签中:

      椭圆 Canvas.Left="10" Canvas.Top="133" Height="24" Name="ellipse1" Width="23" Stroke="Red" MouseLeftButtonDown="ellipse1_MouseLeftButtonDown" ToolTip="Temp Close" StrokeEndLineCap="Flat" StrokeThickness="12"

      private void ellipse1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { 应用 curApp = Application.Current; curApp.Shutdown(); }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-17
        • 1970-01-01
        • 1970-01-01
        • 2012-05-17
        • 2012-01-29
        • 2023-03-24
        • 2012-03-10
        • 1970-01-01
        相关资源
        最近更新 更多