Pergunta

Eu estou respondendo a eventos MouseLeftButtonDown em elementos adicionados a uma tela WPF. Tudo funciona bem quando clicado (ou seja, os fogos EventHandler fora corretamente), mas requer muita precisão do ponteiro do mouse. Você tem que ser perfeitamente na parte superior do círculo para fazê-lo funcionar. Eu preciso que ele seja um pouco mais indulgente; talvez, pelo menos 1 ou 2 pixles perdoar. Os elementos na tela são agradáveis ??grandes círculos (sobre o tamanho de um quarto na tela), de modo que os círculos em si não são muito pequeno, mas o strokeWidth de cada um é um, por isso é uma linha fina.

Você pode ver um screenshot aqui: http://twitpic.com/1f2ci/full

A maioria dos gráficos aplicativo não são este exigente quanto a colheita do mouse, então eu quero dar ao usuário uma experiência familiar.

Como posso torná-lo um pouco mais indulgente.

Foi útil?

Solução

Você pode ligar para o evento MouseLeftButtonDown do seu objeto de layout raiz em vez disso, e verificar quais elementos está ao alcance de um clique, fazendo isso:

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

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

Para o parâmetro Point, você pode usar as MouseEventArgs parâmetro E, e chamar seu método GetPosition assim:

Point p = e.GetPosition(null)

Não me lembro se deve usar HitTest em vez dos FindElementsInHostCoordinates. Tente ambos.
http://msdn.microsoft.com/en-us/library/ms608752. aspx

Você pode criar 4 Ponto de objetos a partir da posição do mouse para criar um efeito falso Tolerância, e chamar tanto FindElementsInHostCoordinates ou HitTest para todos os 4 pontos.

Outras dicas

Você pode querer tentar preencher o círculo com a cor transparente para fazer todo o círculo clicável ...

Se isso falhar, você pode também desenhar círculos auxiliares no mesmo local que os outros círculos. Faça a cor de primeiro plano círculo transparente, e fazer a espessura do pincel alguns pixels mais amplo para uma região clickable mais aceitável ao redor do círculo ..

Espero que isso ajude!

Eu acho que eu tenho feito isso (com você ajuda a me começou) ...

Em primeiro lugar, eu mudei o manuseio para a tela em vez de cada Ellipse evento move. Isso é bom e ruim, do ponto de vista OOP. Pelo menos quando a manipulação de eventos do mouse é uma responsabilidade do HolePattern para defini-lo em cima de cada Hole (a elipse que é o visual do Hole), é abstraída para que qualquer consumidor do meu HolePattern receberá esta functioanality automactically. No entanto, movendo-a para o código UI principal, agora eu estou lidando com o meu evento do mouse tela em um nível superior. Mas isso não é tudo ruim. Poderíamos discutir esta parte durante dias.

O ponto é, eu projetei uma maneira de criar uma "margem de erro" quando pegar algo em uma tela com um mouse, e depois de ler o buraco que a elipse selecionada pertence, e então eu posso ler a HolePattern que Buraco pertence, e toda a minha UI (ListView, caixas de texto, gridview fo coordenadas) são atualizados pela XAML existente de ligação, ea tela é atualizada com uma chamada para um método existente para regenerar a tela.

Para ser honesto, eu não posso acreditar que eu percebi que tudo isso (com a sua ajuda e outros também, é claro). É esse sentimento um fresco para ter a visão deste isso e vê-lo vir a ser.

Confira o código principal aqui:

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;

            }
        }
    }
}

Apenas Aumento da espessura do traçado da elipse de modo que é ajustável

, portanto, as obras de eventos MouseLeftButtonDown Exemplo: Em Ellipse tag:

Ellipse Canvas.Left = "10" Canvas.Top = "133" height = "24" Name = "elipse1" width = "23" Stroke = "Red" MouseLeftButtonDown = "ellipse1_MouseLeftButtonDown" ToolTip = "Temp Close" StrokeEndLineCap = "Flat" StrokeThickness = "12"

vazio ellipse1_MouseLeftButtonDown (object sender, MouseButtonEventArgs e) privada { Aplicação curApp = Application.Current; curApp.Shutdown (); }

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top