Entrada de texto personalizado

As APIs de texto principal no namespace Windows.UI.Text.Core permitem que um aplicativo do Windows receba entradas de texto de qualquer serviço de texto com suporte em dispositivos Windows. As APIs são semelhantes às APIs Estrutura de Serviços de Texto em que o aplicativo não precisa ter conhecimento detalhado dos serviços de texto. Isso permite que o aplicativo receba texto em qualquer idioma e de qualquer tipo de entrada, como teclado, fala ou caneta.

APIs importantes: Windows.UI.Text.Core, CoreTextEditContext

Por que usar APIs de texto básicas?

Para muitos aplicativos, os controles de caixa de texto XAML ou HTML são suficientes para entrada de texto e edição. No entanto, caso seu aplicativo trate cenários de texto complexos, como um aplicativo de processamento de texto, talvez você precise da flexibilidade de um controle de edição de texto personalizado. Você pode usar as APIs de teclado CoreWindow para criar o controle de edição de texto, mas elas não oferecem uma maneira de receber entrada de texto com base na composição, algo necessário para dar suporte a idiomas do leste asiático.

Em vez disso, use as APIs Windows.UI.Text.Core quando você precisar criar um controle de edição de texto personalizado. Essas APIs foram projetadas para dar muita flexibilidade no processamento de entrada de texto, em qualquer idioma e permitir que você ofereça a experiência de texto mais adequada ao seu aplicativo. Os controles de edição e entrada de texto criados com APIs de texto básicas podem receber entrada de texto de todos os métodos de entrada de texto em dispositivos Windows, dos Editores de Método de Entrada (IMEs) baseados na Estrutura de Serviços de Texto e manuscrito em computadores até o teclado WordFlow (que fornece correção automática, previsão e ditado) em dispositivos móveis.

Arquitetura

A seguir, uma representação simples do sistema de entrada de texto.

  • "Aplicativo" representa um aplicativo do Windows que hospeda um controle de edição personalizado criado usando as APIs de texto principal.
  • As APIs Windows.UI.Text.Core facilitam a comunicação com serviços de texto por meio do Windows. A comunicação entre o controle de edição de texto e os serviços de texto é tratada principalmente por meio de um objeto CoreTextEditContext que fornece os métodos e os eventos para facilitar a comunicação.

Diagrama de arquitetura do CoreText

Intervalos e seleção de texto

Os controles de edição dão espaço para entrada de texto, e os usuários esperam editar texto em qualquer lugar nesse espaço. Aqui, explicamos o sistema de posicionamento de texto usado pelas APIs de texto básicas e como os intervalos e as seleções são representados nesse sistema.

Posição do sinal de interpolação do aplicativo

Os intervalos de texto usados com as APIs de texto básicas são expressados em termos de posições de sinal de interpolação. Uma "Application Caret Position (ACP)" é um número baseado em zero que indica a contagem de caracteres desde o início do fluxo de texto pouco antes do sinal de interpolação, conforme mostrado aqui.

Captura de tela mostrando a contagem de caracteres da ACP (Posição do Cursor de Aplicativo)

Intervalos e seleção de texto

Os intervalos de texto e as seleções são representados pela estrutura CoreTextRange que contém dois campos:

Campo Tipo de dados Descrição
StartCaretPosition Número [JavaScript] | System.Int32 [.NET] | int32 [C++] A posição inicial de um intervalo é a ACP pouco antes do primeiro caractere.
EndCaretPosition Número [JavaScript] | System.Int32 [.NET] | int32 [C++] A posição final de um intervalo é a ACP logo depois do último caractere.

 

Por exemplo, no intervalo de texto mostrado anteriormente, o intervalo [0, 5] especifica a palavra "Olá". StartCaretPosition sempre deve ser menor ou igual a EndCaretPosition. O intervalo [5, 0] é inválido.

Ponto de inserção

A posição do sinal de interpolação atual, normalmente conhecida como o ponto de inserção, é representada definindo-se StartCaretPosition para ser igual a EndCaretPosition.

Seleção não contígua

Alguns controles de edição dão suporte a seleções não contíguas. Por exemplo, os aplicativos do Microsoft Office dão suporte a seleções arbitrárias, e muitos editores de código-fonte dão suporte à seleção de coluna. No entanto, as APIs de texto principal não dão suporte a seleções não contíguas. Os controles de edição devem informar somente uma seleção contígua única, normalmente o subintervalo ativo das seleções não contíguas.

Por exemplo, a imagem a seguir mostra um fluxo de texto com duas seleções não contíguas: [0, 1] e [6, 11] para as quais o controle de edição deve relatar apenas uma ([0, 1] ou [6, 11]).

Captura de tela mostrando uma seleção de texto não contíguo, em que o primeiro caractere e os últimos cinco caracteres estão selecionados.

Trabalhando com texto

A classe CoreTextEditContext permite o fluxo de texto entre o Windows e os controles de edição por meio do evento TextUpdating, do evento TextRequested e do método NotifyTextChanged.

O controle de edição recebe texto por meio de eventos TextUpdating gerados quando os usuários interagem com métodos de entrada de texto como teclados, fala ou IMEs.

Ao alterar o texto no seu controle de edição, por exemplo, colando o texto no controle, você precisa notificar o Windows chamando NotifyTextChanged.

Se o serviço de texto exigir o novo texto, um evento TextRequested será acionado. Você deve fornecer o novo texto no manipulador de eventos TextRequested.

Aceitando atualizações de texto

O controle de edição normalmente deve aceitar solicitações de atualização de texto, porque elas representam o texto que o usuário deseja inserir. No manipulador de eventos TextUpdating, essas ações são esperadas de seu controle de edição:

  1. Insira o texto especificado em CoreTextTextUpdatingEventArgs.Text na posição especificada em CoreTextTextUpdatingEventArgs.Range.
  2. Coloque a seleção na posição especificada em CoreTextTextUpdatingEventArgs.NewSelection.
  3. Notifique o sistema de que a atualização foi bem-sucedida definindo CoreTextTextUpdatingEventArgs.Result como CoreTextTextUpdatingResult.Succeeded.

Por exemplo, esse é o estado de um controle de edição antes de o usuário digitar "d". O ponto de inserção está em [10, 10].

Captura de tela de um diagrama de fluxo de texto mostrando o ponto de inserção em [10, 10], antes de uma inserção

Quando o usuário digita "d", um evento TextUpdating é gerado com os seguintes dados CoreTextTextUpdatingEventArgs :

Em seu controle de edição, aplique as alterações especificadas e defina Result como Succeeded. Aqui está o estado do controle após as alterações serem aplicadas.

Captura de tela de um diagrama de fluxo de texto mostrando o ponto de inserção em \[11, 11\], após uma inserção

Rejeitando atualizações de texto

Às vezes, você não consegue aplicar atualizações de texto porque o intervalo solicitado está em uma área do controle de edição que não deve ser alterada. Nesse caso, você não deve aplicar alterações. Em vez disso, notifique o sistema de que a atualização falhou definindo CoreTextTextUpdatingEventArgs.Result como CoreTextTextUpdatingResult.Failed.

Por exemplo, considere um controle de edição que aceita apenas um endereço de email. Os espaços devem ser rejeitados porque endereços de email não podem conter espaços. Assim, quando eventos TextUpdating forem acionados para a tecla de espaço, você deverá simplesmente definir Result como Failed no seu controle de edição.

Notificando alterações de texto

Às vezes, o controle de edição faz alterações no texto, como quando o texto é colado ou corrigido automaticamente. Nesses casos, você deve notificar os serviços de texto dessas alterações chamando o método NotifyTextChanged.

Por exemplo, esse é o estado de um controle de edição antes de o usuário colar "World". O ponto de inserção está em [6, 6].

Captura de tela de um diagrama de fluxo de texto mostrando o ponto de inserção em [6, 6], antes de uma inserção

O usuário executa a ação de colagem e o controle de edição depois que as alterações são aplicadas:

Captura de tela de um diagrama de fluxo de texto mostrando o ponto de inserção em \[11, 11\], após uma inserção

Quando isso acontece, você deve chamar NotifyTextChanged com estes argumentos:

  • modifiedRange = [6, 6]
  • newLength = 5
  • newSelection = [11, 11]

Um ou mais TextRequested eventos virão depois, tratados para atualizar o texto com que os serviços de texto estão trabalhando.

Substituindo atualizações de texto

No controle de edição, convém substituir uma atualização de texto para fornecer recursos de correção automática.

Por exemplo, considere um controle de edição que forneça um recurso de correção que formaliza contrações. Esse é o estado do controle de edição antes de o usuário digitar a tecla de espaço para acionar a correção. O ponto de inserção está em [3, 3].

Captura de tela de um diagrama de fluxo de texto mostrando o ponto de inserção em [3, 3], antes de uma inserção

O usuário pressiona a tecla de espaço e um evento TextUpdating correspondente é gerado. O controle de edição aceita a atualização de texto. Esse é o estado do controle de edição para um breve momento antes de a correção ser concluída. O ponto de inserção está em [4, 4].

Captura de tela de um diagrama de fluxo de texto mostrando o ponto de inserção em [4, 4], após uma inserção

Fora do manipulador de eventos TextUpdating , o controle de edição faz a seguinte correção. Este é o estado do controle de edição após a correção estar concluída. O ponto de inserção está em [5, 5].

Captura de tela de um diagrama de fluxo de texto mostrando o ponto de inserção em [5, 5]

Quando isso acontece, você deve chamar NotifyTextChanged com estes argumentos:

  • modifiedRange = [1, 2]
  • newLength = 2
  • newSelection = [5, 5]

Um ou mais TextRequested eventos virão depois, tratados para atualizar o texto com que os serviços de texto estão trabalhando.

Fornecendo texto solicitado

É importante que os serviços de texto tenham o texto correto para fornecer recursos como a correção automática ou a previsão, especialmente para o texto que já existia no controle de edição, carregando um documento, por exemplo, ou texto inserido pelo controle de edição, conforme explicado nas seções anteriores. Portanto, sempre que um evento TextRequested é acionado, você deve fornecer o texto atualmente no seu controle de edição para o intervalo especificado.

Haverá vezes em que o Range em CoreTextTextRequest especificará um intervalo que o controle de edição não poderá acomodar como está. Por exemplo, o Range é maior do que o tamanho do controle de edição no momento do evento TextRequested ou o final do Range está fora dos limites. Nesses casos, você deve retornar o intervalo que fizer sentido, que normalmente é um subconjunto do intervalo solicitado.

Exemplos

Exemplos de arquivo-morto