MouseLeftButtonDown на холсте требует слишком большой точности

StackOverflow https://stackoverflow.com/questions/580641

Вопрос

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

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

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

Как я могу сделать это немного более снисходительным.

Это было полезно?

Решение

Вместо этого вы можете подключиться к событию 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 вы можете использовать параметр e MouseEventArgs и вызвать его метод GetPosition следующим образом:

Point p = e.GetPosition(null)

Я не могу вспомнить, следует ли использовать HitTest вместо FindElementsInHostCoordinates.Попробуйте оба.
http://msdn.microsoft.com/en-us/library/ms608752.aspx

Вы можете создать 4-точечные объекты из положения мыши, чтобы создать эффект ложного допуска, и вызвать FindElementsInHostCoordinates или HitTest для всех 4 точек.

Другие советы

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

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

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

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

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

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

            }
        }
    }
}

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

таким образомВ теге Эллипс:

Эллипс 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 (отправитель объекта, mousebuttoneventargs e) {приложение curapp = application.current;curApp.Shutdown();}

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top