MouseLeftButtonDown на холсте требует слишком большой точности - PullRequest
3 голосов
/ 24 февраля 2009

Я отвечаю на события MouseLeftButtonDown для элементов, добавленных на холст WPF. При щелчке все работает нормально (то есть обработчик событий срабатывает корректно), но требует слишком большой точности от указателя мыши. Вы должны быть идеально на вершине круга, чтобы он работал. Мне нужно, чтобы это было немного более прощающим; может быть, по крайней мере, 1 или 2 прощения пикселей. Элементы на холсте - это красивые большие круги (размером с четверть на экране), поэтому сами круги не слишком малы, но StrokeWidth каждого из них равен 1, поэтому это тонкая линия.

Вы можете увидеть скриншот здесь: http://twitpic.com/1f2ci/full

Большинство графических приложений не слишком требовательны к выбору мыши, поэтому я хочу дать пользователю знакомый опыт.

Как я могу сделать это немного более прощающим.

Ответы [ 4 ]

4 голосов
/ 24 февраля 2009

Возможно, вы захотите попробовать заполнить круг прозрачным цветом, чтобы сделать весь круг кликабельным ...

Если это не помогло, вы также можете нарисовать вспомогательные круги в том же месте, что и другие круги. Сделайте цвет переднего плана круга прозрачным, а толщину кисти - на несколько пикселей больше, чтобы сделать область вокруг круга более привлекательной для клика.

Надеюсь, это поможет!

4 голосов
/ 24 февраля 2009

Вместо этого вы можете подключиться к событию 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-точечные объекты из позиции мыши, чтобы создать эффект ложной толерантности, и вызвать FindElementsInHostCoordinates или HitTest для всех 4 точек.

1 голос
/ 12 февраля 2011

Просто увеличьте толщину обводки эллипса, чтобы его можно было регулировать

, таким образом, событие MouseLeftButtonDown работает Пример: В теге эллипса:

Эллипс Canvas. StrokeThickness = "12"

private void ellipse1_MouseLeftButtonDown (отправитель объекта, MouseButtonEventArgs e) { Application curApp = Application.Current; curApp.Shutdown (); }

1 голос
/ 24 февраля 2009

Я думаю, что я сделал это (с вашей помощью, чтобы начать меня) ...

Во-первых, я переместил обработку событий перемещения на холст вместо каждого эллипса. Это хорошо и плохо с точки зрения ООП. По крайней мере, когда обработка событий мыши является обязанностью HolePattern, чтобы установить его на каждое Отверстие (эллипс, который является визуальным элементом Отверстия), он абстрагируется так, что любой потребитель моего HolePattern получит эту функцию автоматически. Однако, переместив его в основной код пользовательского интерфейса, я теперь имею дело с событием мыши на холсте на более высоком уровне. Но это еще не все плохо. Мы могли бы обсудить эту часть в течение нескольких дней.

Дело в том, что я разработал способ создания «поля погрешности», когда выбираю что-то на холсте с помощью мыши, а затем читаю Отверстие, к которому принадлежит выбранный Эллипс, и затем я могу прочитать HolePattern, который Отверстие принадлежит, и весь мой пользовательский интерфейс (ListView, текстовые поля, координатная сетка) обновляются ВСЕМ существующей привязкой 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;

            }
        }
    }
}
...