Pergunta

Estou renderização de texto usando FormattedText, mas não parece haver nenhuma maneira de realizar testes hit per-char na saída renderizada. É somente leitura, então eu basicamente só precisa de seleção, sem edição.

Eu usaria RichTextBox ou similar, mas eu preciso texto de saída com base em códigos de controle incorporar no próprio texto, então eles nem sempre ninho, o que torna a construção dos elementos em linha direito muito complexa. Eu também estou um pouco preocupado com o desempenho com essa solução; Eu tenho um grande número de linhas, e novas linhas são acrescentadas muitas vezes.

Eu olhei GlyphRun, parece que eu poderia começar a batida de testes a partir dele ou de uma classe relacionada, mas eu estaria reimplementar uma série de funcionalidades, e parece que deve haver uma maneira mais simples ...

Alguém sabe de uma boa maneira de implementar isso?

Foi útil?

Solução

A melhor maneira é criar uma boa estrutura de dados para armazenar o seu texto e que também considera hit-teste. Um exemplo poderia ser a de dividir o texto em blocos (palavras, linhas ou parágrafos, dependendo do que você precisa). Em seguida, cada tal bloco deve ter uma caixa delimitadora que devem ser recalculadas em quaisquer operações de formatação. Considere também posições de acento circunflexo em seu projeto.

Uma vez que você tem essa facilidade torna-se muito fácil de fazer hit-teste, basta usar as caixas delimitadoras. Ele também irá ajudar em operações subseqüentes como destacar uma parte específica do texto.

Outras dicas

Você pode obter a geometria de cada personagem de um objeto FormattedText e usar os limites de cada personagem para fazer o seu teste de hit.

var geometry = (GeometryGroup)((GeometryGroup)text.BuildGeometry(new Point(0, 0))).Children[0];
foreach (var c in geometry.Children)
{
  if (c.Bounds.Contains(point))
    return index;
  index++;
}

Em OnRender você pode processar estes geometria objetos em vez do texto formatado.

Completamente concordar com Sesh - a maneira mais fácil que você vai fugir com não re-implementação de toda uma carga de funcionalidade FormattedText vai ser por dividir os itens individuais que você quer bater-teste em seus próprios controles / inlines.

Considere usar um TextBlock e adicionando cada palavra como o seu próprio inline (ou), então ou se ligam a propriedade IsMouseDirectlyOver da linha, nossos delegados adicionar aos eventos MouseEnter e MouseLeave.

Se você quer fazer-nível de pixel bateu testando dos glifos reais (ou seja, é o mouse exatamente no ponto de este 'i'), então você vai precisar usar GlyphRuns e fazer testes de acerto manual sobre os glifos ( leia-se:. árduo trabalho)

Estou muito atrasado para a festa - se a festa não acabou, e você não precisa a geometria caráter real, descobri algo como isto útil:

 for (int i = 0; i < FormattedText.Text.Length; i++)
 {
            characterHighlightGeometry = FormattedText.BuildHighlightGeometry(new Point(), i, 1);
            CharacterHighlightGeometries.Children.Add(characterHighlightGeometry);
 }

BuildGeometry () inclui apenas a geometria caminho real de um personagem. BuildHighlightGeometry () gera os limites exteriores de todos os caracteres - incluindo espaços, portanto um índice para um espaço pode ser localizado por:

 foreach (var c in CharacterHighlightGeometries.Children)
        {
            if (c.Bounds.Contains(centerpoint))
            {
                q = c;
                cpos = index;
                break;
            }
            index++;
        }

Espero que isso ajude.

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